diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..1ad2fd0e --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +doc.vvbin.cn diff --git a/README.html b/README.html new file mode 100644 index 00000000..e218982f --- /dev/null +++ b/README.html @@ -0,0 +1,39 @@ + + + + + + vue-vben-admin-doc | Vben Admin + + + + + + + + + + + + + + + + +

vue-vben-admin-doc

如何本地开发

# 克隆本仓库
+$ git clone git@github.com:vbenjs/vue-vben-admin-doc.git
+
+# 或者使用 yarn
+$ yarn install
+
+# 启动开发服务器
+$ yarn dev
+
+ + + + \ No newline at end of file diff --git a/assets/Home.559a09dc.js b/assets/Home.559a09dc.js new file mode 100644 index 00000000..ce6c90ae --- /dev/null +++ b/assets/Home.559a09dc.js @@ -0,0 +1 @@ +import{c as n,_ as m,d as y,u as t,e as s,f as o,g as l,j as r,t as u,p as k,F as T,z as F,J as I,A as v,H as p}from"./plugin-vue_export-helper.147b70e9.js";import{u as B,a as L,N as H}from"./app.b8b99788.js";function x(){const i=B();return n(()=>i.value.frontmatter)}const C={key:0,class:"home-hero"},N={key:0,class:"figure"},D=["src","alt"],w={key:1,id:"main-title",class:"title"},S={key:2,class:"description"},V=y({setup(i){const a=L(),e=x(),_=n(()=>e.value.heroImage||f.value||c.value||g.value),f=n(()=>e.value.heroText!==null),$=n(()=>e.value.heroText||a.value.title),c=n(()=>e.value.tagline!==null),h=n(()=>e.value.tagline||a.value.description),g=n(()=>e.value.actionLink&&e.value.actionText),A=n(()=>e.value.altActionLink&&e.value.altActionText);return(d,ee)=>t(_)?(s(),o("header",C,[d.$frontmatter.heroImage?(s(),o("figure",N,[l("img",{class:"image",src:d.$withBase(d.$frontmatter.heroImage),alt:d.$frontmatter.heroAlt},null,8,D)])):r("v-if",!0),t(f)?(s(),o("h1",w,u(t($)),1)):r("v-if",!0),t(c)?(s(),o("p",S,u(t(h)),1)):r("v-if",!0),t(g)?(s(),k(H,{key:3,item:{link:t(e).actionLink,text:t(e).actionText},class:"action"},null,8,["item"])):r("v-if",!0),t(A)?(s(),k(H,{key:4,item:{link:t(e).altActionLink,text:t(e).altActionText},class:"action alt"},null,8,["item"])):r("v-if",!0)])):r("v-if",!0)}});var b=m(V,[["__scopeId","data-v-e065f044"]]);const j={key:0,class:"home-features"},z={class:"wrapper"},E={class:"container"},J={class:"features"},P={key:0,class:"title"},R={key:1,class:"details"},q=y({setup(i){const a=x(),e=n(()=>a.value.features&&a.value.features.length>0),_=n(()=>a.value.features?a.value.features:[]);return(f,$)=>t(e)?(s(),o("div",j,[l("div",z,[l("div",E,[l("div",J,[(s(!0),o(T,null,F(t(_),(c,h)=>(s(),o("section",{key:h,class:"feature"},[c.title?(s(),o("h2",P,u(c.title),1)):r("v-if",!0),c.details?(s(),o("p",R,u(c.details),1)):r("v-if",!0)]))),128))])])])])):r("v-if",!0)}});var G=m(q,[["__scopeId","data-v-9c9c2344"]]);const K={},M={key:0,class:"footer"},O={class:"container"},Q={class:"text"};function U(i,a){return i.$frontmatter.footer?(s(),o("footer",M,[l("div",O,[l("p",Q,u(i.$frontmatter.footer),1)])])):r("v-if",!0)}var W=m(K,[["render",U],["__scopeId","data-v-44324124"]]);const X={class:"home","aria-labelledby":"main-title"},Y={class:"home-content"},Z=y({setup(i){return(a,e)=>{const _=I("Content");return s(),o("main",X,[v(b),p(a.$slots,"hero",{},void 0,!0),v(G),l("div",Y,[v(_)]),p(a.$slots,"features",{},void 0,!0),v(W),p(a.$slots,"footer",{},void 0,!0)])}}});var ae=m(Z,[["__scopeId","data-v-1fd43058"]]);export{ae as default}; diff --git a/assets/README.md.c6655550.js b/assets/README.md.c6655550.js new file mode 100644 index 00000000..b25f9631 --- /dev/null +++ b/assets/README.md.c6655550.js @@ -0,0 +1,9 @@ +import{_ as n,f as a,e,N as s}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"vue-vben-admin-doc","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u5982\u4F55\u672C\u5730\u5F00\u53D1","slug":"\u5982\u4F55\u672C\u5730\u5F00\u53D1"}],"relativePath":"README.md","lastUpdated":1694442156381}',t={},c=s(`

vue-vben-admin-doc

\u5982\u4F55\u672C\u5730\u5F00\u53D1

# \u514B\u9686\u672C\u4ED3\u5E93
+$ git clone git@github.com:vbenjs/vue-vben-admin-doc.git
+
+# \u6216\u8005\u4F7F\u7528 yarn
+$ yarn install
+
+# \u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668
+$ yarn dev
+
`,3),o=[c];function d(i,r,l,p,_,h){return e(),a("div",null,o)}var v=n(t,[["render",d]]);export{m as __pageData,v as default}; diff --git a/assets/README.md.c6655550.lean.js b/assets/README.md.c6655550.lean.js new file mode 100644 index 00000000..2013b895 --- /dev/null +++ b/assets/README.md.c6655550.lean.js @@ -0,0 +1,9 @@ +import{_ as n,f as a,e,N as s}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"vue-vben-admin-doc","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u5982\u4F55\u672C\u5730\u5F00\u53D1","slug":"\u5982\u4F55\u672C\u5730\u5F00\u53D1"}],"relativePath":"README.md","lastUpdated":1694442156381}',t={},c=s(`__VP_STATIC_START__

vue-vben-admin-doc

\u5982\u4F55\u672C\u5730\u5F00\u53D1

# \u514B\u9686\u672C\u4ED3\u5E93
+$ git clone git@github.com:vbenjs/vue-vben-admin-doc.git
+
+# \u6216\u8005\u4F7F\u7528 yarn
+$ yarn install
+
+# \u542F\u52A8\u5F00\u53D1\u670D\u52A1\u5668
+$ yarn dev
+
__VP_STATIC_END__`,3),o=[c];function d(i,r,l,p,_,h){return e(),a("div",null,o)}var v=n(t,[["render",d]]);export{m as __pageData,v as default}; diff --git a/assets/app.b8b99788.js b/assets/app.b8b99788.js new file mode 100644 index 00000000..a577a098 --- /dev/null +++ b/assets/app.b8b99788.js @@ -0,0 +1,16 @@ +var Ve=Object.defineProperty,Je=Object.defineProperties;var Ye=Object.getOwnPropertyDescriptors;var le=Object.getOwnPropertySymbols;var Qe=Object.prototype.hasOwnProperty,Xe=Object.prototype.propertyIsEnumerable;var ue=(e,t,n)=>t in e?Ve(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,D=(e,t)=>{for(var n in t||(t={}))Qe.call(t,n)&&ue(e,n,t[n]);if(le)for(var n of le(t))Xe.call(t,n)&&ue(e,n,t[n]);return e},J=(e,t)=>Je(e,Ye(t));import{r as Ze,m as de,a as ye,n as Le,i as et,d as $,h as M,b as P,o as j,c as _,w as tt,e as u,f as p,g as d,_ as y,j as x,k as te,t as A,l as Ce,u as c,p as S,q as Se,s as Ee,v as Pe,x as I,y as F,F as H,z as ne,A as k,B as Ae,C as oe,D as nt,E as he,G as pe,H as L,I as ot,J as Z,K as st,L as O,M as rt}from"./plugin-vue_export-helper.147b70e9.js";const it="modulepreload",ve={},at="/",Te=function(t,n){return!n||n.length===0?t():Promise.all(n.map(o=>{if(o=`${at}${o}`,o in ve)return;ve[o]=!0;const s=o.endsWith(".css"),i=s?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${i}`))return;const r=document.createElement("link");if(r.rel=s?"stylesheet":it,s||(r.as="script",r.crossOrigin=""),r.href=o,document.head.appendChild(r),s)return new Promise((a,l)=>{r.addEventListener("load",a),r.addEventListener("error",()=>l(new Error(`Unable to preload CSS for ${o}`)))})})).then(()=>t())},C=typeof window!="undefined";function ct(e,t){t.sort((n,o)=>{const s=o.split("/").length-n.split("/").length;return s!==0?s:o.length-n.length});for(const n of t)if(e.startsWith(n))return n}function fe(e,t){const n=ct(t,Object.keys(e));return n?e[n]:void 0}function lt(e,t){t=ut(e,t);const n=fe(e.locales||{},t)||{},o=fe(e.themeConfig&&e.themeConfig.locales||{},t)||{};return J(D(D({},e),n),{themeConfig:J(D(D({},e.themeConfig),o),{locales:{}}),lang:o.lang||e.lang,locales:{}})}function ut(e,t){if(!C)return t;const n=e.base,o=n.endsWith("/")?n.slice(0,-1):n;return t.slice(o.length)}function Be(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Re(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t.endsWith("/")&&(t+="index"),C){const n="/";t=t.slice(n.length).replace(/\//g,"_")+".md";const o=__VP_HASH_MAP__[t.toLowerCase()];t=`${n}assets/${t}.${o}.js`}else t=`./${t.slice(1).replace(/\//g,"_")}.md.js`;return t}const Oe=Symbol(),me="http://a.com",dt=()=>({path:"/",component:null,data:null});function ht(e,t){const n=Ze(dt());function o(r=C?location.href:"/"){const a=new URL(r,me);return!a.pathname.endsWith("/")&&!a.pathname.endsWith(".html")&&(a.pathname+=".html",r=a.pathname+a.search+a.hash),C&&(history.replaceState({scrollPosition:window.scrollY},document.title),history.pushState(null,"",r)),i(r)}let s=null;async function i(r,a=0){const l=new URL(r,me),h=s=l.pathname;try{let v=e(h);if("then"in v&&typeof v.then=="function"&&(v=await v),s===h){s=null;const{default:w,__pageData:b}=v;if(!w)throw new Error(`Invalid route component: ${w}`);n.path=h,n.component=de(w),n.data=ye(JSON.parse(b)),C&&Le(()=>{if(l.hash&&!a){const m=document.querySelector(decodeURIComponent(l.hash));if(m){_e(m,l.hash);return}}window.scrollTo(0,a)})}}catch(v){v.message.match(/fetch/)||console.error(v),s===h&&(s=null,n.path=h,n.component=t?de(t):null)}}return C&&(window.addEventListener("click",r=>{const a=r.target.closest("a");if(a){const{href:l,protocol:h,hostname:v,pathname:w,hash:b,target:m}=a,f=window.location,B=w.match(/\.\w+$/);!r.ctrlKey&&!r.shiftKey&&!r.altKey&&!r.metaKey&&m!=="_blank"&&h===f.protocol&&v===f.hostname&&!(B&&B[0]!==".html")&&(r.preventDefault(),w===f.pathname?b&&b!==f.hash&&(history.pushState(null,"",b),_e(a,b,a.classList.contains("header-anchor"))):o(l))}},{capture:!0}),window.addEventListener("popstate",r=>{i(location.href,r.state&&r.state.scrollPosition||0)}),window.addEventListener("hashchange",r=>{r.preventDefault()})),{route:n,go:o}}function pt(){const e=et(Oe);if(!e)throw new Error("useRouter() is called without provider.");return e}function T(){return pt().route}function _e(e,t,n=!1){const o=document.querySelector(".nav-bar").offsetHeight,s=e.classList.contains(".header-anchor")?e:document.querySelector(decodeURIComponent(t));if(s){const i=s.offsetTop-o-15;!n||Math.abs(i-window.scrollY)>window.innerHeight?window.scrollTo(0,i):window.scrollTo({left:0,top:i,behavior:"smooth"})}}const vt=$({name:"VitePressContent",setup(){const e=T();return()=>e.component?M(e.component):null}}),ft=$({setup(e,{slots:t}){const n=P(!1);return j(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function mt(e,t,n,o){Object.defineProperties(e.config.globalProperties,{$site:{get(){return t.value}},$siteByRoute:{get(){return n.value}},$themeConfig:{get(){return n.value.themeConfig}},$page:{get(){return o.value}},$frontmatter:{get(){return o.value.frontmatter}},$lang:{get(){return n.value.lang}},$localePath:{get(){const{locales:s}=t.value,{lang:i}=n.value,r=Object.keys(s).find(a=>s[a].lang===i);return s&&r||"/"}},$title:{get(){return o.value.title?o.value.title+" | "+n.value.title:n.value.title}},$description:{get(){return o.value.description||n.value.description}},$withBase:{value(s){return Be(t.value.base,s)}}})}function _t(e){e.component("Content",vt),e.component("ClientOnly",ft),e.component("Debug",()=>null)}var gt='{"lang":"zh-CN","title":"Vben Admin","description":"\u4E00\u4E2A\u5F00\u7BB1\u5373\u7528\u7684\u524D\u7AEF\u6846\u67B6","base":"/","head":[["meta",{"name":"author","content":"Vbenjs Team"}],["meta",{"name":"keywords","content":"vben, vitejs, vite, ant-design-vue, vue"}],["link",{"rel":"icon","type":"image/svg+xml","href":"/logo.svg"}],["meta",{"name":"viewport","content":"width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"}],["meta",{"name":"keywords","content":"vue vben admin docs"}],["link",{"rel":"icon","href":"/favicon.ico"}]],"themeConfig":{"repo":"vbenjs/vue-vben-admin","docsRepo":"vbenjs/vue-vben-admin-doc","logo":"/logo.png","docsBranch":"main","editLinks":true,"editLinkText":"\u4E3A\u6B64\u9875\u63D0\u4F9B\u4FEE\u6539\u5EFA\u8BAE","nav":[{"text":"\u6307\u5357","link":"/guide/","items":[{"text":"\u6307\u5357","link":"/guide/introduction"},{"text":"\u6DF1\u5165","link":"/dep/icon"},{"text":"\u5176\u4ED6","link":"/other/faq"}]},{"text":"\u7EC4\u4EF6","link":"/components/","items":[{"text":"\u4ECB\u7ECD","link":"/components/introduction"},{"text":"\u5168\u5C40\u7EC4\u4EF6","link":"/components/glob/button"},{"text":"\u5E38\u7528\u7EC4\u4EF6","link":"/components/basic"},{"text":"\u51FD\u6570\u5F0F\u7EC4\u4EF6","link":"/components/functional/context-menu"}]},{"text":"\u76F8\u5173\u94FE\u63A5","items":[{"text":"\u5B8C\u6574\u7248\u9884\u89C8","link":"https://vben.vvbin.cn"},{"text":"\u5B8C\u6574\u7248\u6E90\u7801","link":"https://github.com/vbenjs/vue-vben-admin"},{"text":"\u7CBE\u7B80\u7248\u5206\u652F","link":"https://github.com/vbenjs/vue-vben-admin/tree/thin"},{"text":"\u6587\u6863\u6E90\u7801","link":"https://github.com/vbenjs/vue-vben-admin-doc"},{"text":"\u66F4\u65B0\u65E5\u5FD7","link":"https://github.com/vbenjs/vue-vben-admin/blob/main/CHANGELOG.md"}]},{"text":"\u793E\u533A","items":[{"text":"QQ\u9891\u9053\u3010vben admin\u3011","link":"https://pd.qq.com/s/ahgh62mni"},{"text":"KOOK(\u65B0)","link":"https://kaihei.co/6ZPFKi"},{"text":"Discord Chat","link":"https://discord.gg/VU62jTecad"}]},{"text":"vben3","items":[{"text":"\u4ED3\u5E93\uFF08beta-1\uFF09","link":"https://github.com/jinmao88/vben3"},{"text":"\u6587\u6863","link":"https://vbenjs.github.io/vben3-doc/"}]}],"sidebar":{"/components/":[{"text":"\u7EC4\u4EF6","children":[{"text":"\u524D\u8A00","link":"/components/introduction"}]},{"text":"\u5168\u5C40\u7EC4\u4EF6","children":[{"text":"Button","link":"/components/glob/button"}]},{"text":"\u5E38\u7528\u7EC4\u4EF6","children":[{"text":"Basic","link":"/components/basic"},{"text":"Page","link":"/components/page"},{"text":"Icon","link":"/components/icon"},{"text":"Authority","link":"/components/auth"},{"text":"Form","link":"/components/form"},{"text":"Table","link":"/components/table"},{"text":"PopConfirmButton","link":"/components/pop-confirm-button"},{"text":"CollapseContainer","link":"/components/collapse-container"},{"text":"ScrollContainer","link":"/components/scroll-container"},{"text":"LazyContainer","link":"/components/lazy-container"},{"text":"CodeEditor","link":"/components/code-editor"},{"text":"JsonPreview","link":"/components/json-preview"},{"text":"CountDown","link":"/components/count-down"},{"text":"ClickOutSide","link":"/components/click-out-side"},{"text":"CountTo","link":"/components/count-to"},{"text":"Cropper","link":"/components/cropper"},{"text":"Description","link":"/components/desc"},{"text":"Drawer","link":"/components/drawer"},{"text":"Modal","link":"/components/modal"},{"text":"FlowChart","link":"/components/flow-chart"},{"text":"Upload","link":"/components/upload"},{"text":"Tree","link":"/components/tree"},{"text":"Excel","link":"/components/excel"},{"text":"Qrcode","link":"/components/qrcode"},{"text":"Markdown","link":"/components/markdown"},{"text":"Loading","link":"/components/loading"},{"text":"Tinymce","link":"/components/tinymce"},{"text":"Time","link":"/components/time"},{"text":"StrengthMeter","link":"/components/strength-meter"},{"text":"Verify","link":"/components/verify"},{"text":"Transition","link":"/components/transition"},{"text":"VirtualScroll","link":"/components/virtual-scroll"}]},{"text":"\u51FD\u6570\u5F0F\u7EC4\u4EF6","children":[{"text":"ContextMenu","link":"/components/functional/context-menu"},{"text":"Loading","link":"/components/functional/loading"},{"text":"Preview","link":"/components/functional/preview"}]}],"/":[{"text":"\u6307\u5357","children":[{"text":"\u4ECB\u7ECD","link":"/guide/introduction"},{"text":"\u5F00\u59CB","link":"/guide/"},{"text":"\u9879\u76EE\u914D\u7F6E","link":"/guide/settings"},{"text":"\u8DEF\u7531","link":"/guide/router"},{"text":"\u83DC\u5355","link":"/guide/menu"},{"text":"\u6743\u9650","link":"/guide/auth"},{"text":"Mock&\u8054\u8C03","link":"/guide/mock"},{"text":"\u7EC4\u4EF6\u6CE8\u518C","link":"/guide/component"},{"text":"\u6837\u5F0F","link":"/guide/design"},{"text":"\u5916\u90E8\u6A21\u5757","link":"/guide/lib"},{"text":"\u6784\u5EFA&\u90E8\u7F72","link":"/guide/deploy"},{"text":"Electron","link":"/guide/electron"}]},{"text":"\u6DF1\u5165","children":[{"text":"\u8DE8\u57DF\u5904\u7406","link":"/dep/cors"},{"text":"\u56FE\u6807","link":"/dep/icon"},{"text":"\u56FD\u9645\u5316","link":"/dep/i18n"},{"text":"\u9879\u76EE\u89C4\u8303","link":"/dep/lint"},{"text":"\u9ED1\u6697\u4E3B\u9898","link":"/dep/dark"}]},{"text":"\u5176\u4ED6","children":[{"text":"\u5E38\u89C1\u95EE\u9898","link":"/other/faq"},{"text":"\u5E38\u89C1\u7591\u70B9","link":"/other/doubt"},{"text":"\u6D4B\u8BD5\u670D\u52A1","link":"/other/server"},{"text":"\u76F8\u5173\u9879\u76EE","link":"/other/project"}]}]}},"locales":{},"customData":{}}';const q=P(kt(gt));function K(){return q}function kt(e){return ye(JSON.parse(e))}function R(e){const t=e||T();return _(()=>lt(q.value,t.path))}function U(e){const t=e||T();return _(()=>t.data)}function bt(e,t){const n=Array.from(document.querySelectorAll("meta"));let o=!0;const s=i=>{if(o){o=!1;return}n.forEach(r=>document.head.removeChild(r)),n.length=0,i&&i.length&&i.forEach(r=>{const a=xt(r);document.head.appendChild(a),n.push(a)})};tt(()=>{const i=e.data,r=t.value,a=i&&i.title,l=i&&i.description,h=i&&i.frontmatter.head;document.title=(a?a+" | ":"")+r.title,s([["meta",{charset:"utf-8"}],["meta",{name:"viewport",content:"width=device-width,initial-scale=1"}],["meta",{name:"description",content:l||r.description}],...r.head,...h&&$t(h)||[]])})}function xt([e,t,n]){const o=document.createElement(e);for(const s in t)o.setAttribute(s,t[s]);return n&&(o.innerHTML=n),o}function wt(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function $t(e){return e.filter(t=>!wt(t))}const yt=/#.*$/,Lt=/(index)?\.(md|html)$/,W=/\/$/,Ct=/^[a-z]+:/i;function St(e){return e==null}function se(e){return Array.isArray(e)}function re(e){return Ct.test(e)}function Et(e,t){if(t===void 0)return!1;const n=ge(`/${e.data.relativePath}`),o=ge(t);return n===o}function ge(e){return decodeURI(e).replace(yt,"").replace(Lt,"")}function Pt(e,t){const n=e.endsWith("/"),o=t.startsWith("/");return n&&o?e.slice(0,-1)+t:!n&&!o?`${e}/${t}`:e+t}function ee(e){return/^\//.test(e)?e:`/${e}`}function Ie(e){return e.replace(/(index)?(\.(md|html))?$/,"")||"/"}function At(e){return e===!1||e==="auto"||se(e)}function Tt(e){return e.children!==void 0}function Bt(e){return se(e)?e.length===0:!e}function ie(e,t){if(At(e))return e;t=ee(t);for(const n in e)if(t.startsWith(ee(n)))return e[n];return"auto"}function Ne(e){return e.reduce((t,n)=>(n.link&&t.push({text:n.text,link:Ie(n.link)}),Tt(n)&&(t=[...t,...Ne(n.children)]),t),[])}const Rt={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",width:"1.2em",height:"1.2em",preserveAspectRatio:"xMidYMid meet",viewBox:"0 0 24 24"},Ot=d("path",{d:"M5.883 18.653c-.3-.2-.558-.455-.86-.816a50.32 50.32 0 0 1-.466-.579c-.463-.575-.755-.84-1.057-.949a1 1 0 0 1 .676-1.883c.752.27 1.261.735 1.947 1.588c-.094-.117.34.427.433.539c.19.227.33.365.44.438c.204.137.587.196 1.15.14c.023-.382.094-.753.202-1.095C5.38 15.31 3.7 13.396 3.7 9.64c0-1.24.37-2.356 1.058-3.292c-.218-.894-.185-1.975.302-3.192a1 1 0 0 1 .63-.582c.081-.024.127-.035.208-.047c.803-.123 1.937.17 3.415 1.096A11.731 11.731 0 0 1 12 3.315c.912 0 1.818.104 2.684.308c1.477-.933 2.613-1.226 3.422-1.096c.085.013.157.03.218.05a1 1 0 0 1 .616.58c.487 1.216.52 2.297.302 3.19c.691.936 1.058 2.045 1.058 3.293c0 3.757-1.674 5.665-4.642 6.392c.125.415.19.879.19 1.38a300.492 300.492 0 0 1-.012 2.716a1 1 0 0 1-.019 1.958c-1.139.228-1.983-.532-1.983-1.525l.002-.446l.005-.705c.005-.708.007-1.338.007-1.998c0-.697-.183-1.152-.425-1.36c-.661-.57-.326-1.655.54-1.752c2.967-.333 4.337-1.482 4.337-4.66c0-.955-.312-1.744-.913-2.404a1 1 0 0 1-.19-1.045c.166-.414.237-.957.096-1.614l-.01.003c-.491.139-1.11.44-1.858.949a1 1 0 0 1-.833.135A9.626 9.626 0 0 0 12 5.315c-.89 0-1.772.119-2.592.35a1 1 0 0 1-.83-.134c-.752-.507-1.374-.807-1.868-.947c-.144.653-.073 1.194.092 1.607a1 1 0 0 1-.189 1.045C6.016 7.89 5.7 8.694 5.7 9.64c0 3.172 1.371 4.328 4.322 4.66c.865.097 1.201 1.177.544 1.748c-.192.168-.429.732-.429 1.364v3.15c0 .986-.835 1.725-1.96 1.528a1 1 0 0 1-.04-1.962v-.99c-.91.061-1.662-.088-2.254-.485z",fill:"currentColor"},null,-1),It=[Ot];function Nt(e,t){return u(),p("svg",Rt,It)}var Dt={name:"ri-github-line",render:Nt};const Mt={},jt=["href","aria-label"],Ht=["src"];function Ut(e,t){return u(),p("a",{class:"nav-bar-title",href:e.$withBase(e.$localePath),"aria-label":`${e.$siteByRoute.title}, back to home`},[e.$themeConfig.logo?(u(),p("img",{key:0,class:"logo",src:e.$withBase(e.$themeConfig.logo),alt:"Logo"},null,8,Ht)):x("v-if",!0),te(" "+A(e.$site.title),1)],8,jt)}var zt=y(Mt,[["render",Ut],["__scopeId","data-v-3e3fd8b1"]]);function Ft(){const e=T(),t=K();return _(()=>{const o=t.value.themeConfig.locales;if(!o)return null;const s=Object.keys(o);if(s.length<=1)return null;const i=C?t.value.base:"/",r=i.endsWith("/")?i.slice(0,-1):i,a=e.path.slice(r.length),l=s.find(m=>m==="/"?!1:a.startsWith(m)),h=l?a.substring(l.length-1):a,v=s.map(m=>{const f=m.endsWith("/")?m.slice(0,-1):m;return{text:o[m].label,link:`${f}${h}`}}),w=l||"/";return{text:o[w].selectText?o[w].selectText:"Languages",items:v}})}function qt(){const e=K();function t(n){return Be(e.value.base,n)}return{withBase:t}}function De(e){const t=T(),{withBase:n}=qt(),o=re(e.value.link);return{props:_(()=>{const i=ke(`/${t.data.relativePath}`);let r=!1;if(e.value.activeMatch)r=new RegExp(e.value.activeMatch).test(i);else{const a=ke(n(e.value.link));r=a==="/"?a===i:i.startsWith(a)}return{class:{active:r,isExternal:o},href:o?e.value.link:n(e.value.link),target:e.value.target||o?"_blank":null,rel:e.value.rel||o?"noopener noreferrer":null,"aria-label":e.value.ariaLabel}}),isExternal:o}}function ke(e){return e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\.(html|md)$/,"").replace(/\/index$/,"/")}const Wt={},Gt={class:"icon outbound",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"},Kt=d("path",{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"},null,-1),Vt=d("polygon",{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"},null,-1),Jt=[Kt,Vt];function Yt(e,t){return u(),p("svg",Gt,Jt)}var ae=y(Wt,[["render",Yt]]);const Qt={class:"nav-link"},Xt=$({props:{item:null},setup(e){const n=Ce(e),{props:o,isExternal:s}=De(n.item);return(i,r)=>(u(),p("div",Qt,[d("a",Se({class:"item"},c(o)),[te(A(e.item.text)+" ",1),c(s)?(u(),S(ae,{key:0})):x("v-if",!0)],16)]))}});var Zt=y(Xt,[["__scopeId","data-v-c272f228"]]);const en=e=>(Ee("data-v-7b16fcd4"),e=e(),Pe(),e),tn={class:"nav-dropdown-link-item"},nn=en(()=>d("span",{class:"arrow"},null,-1)),on={class:"text"},sn={class:"icon"},rn=$({props:{item:null},setup(e){const n=Ce(e),{props:o,isExternal:s}=De(n.item);return(i,r)=>(u(),p("div",tn,[d("a",Se({class:"item"},c(o)),[nn,d("span",on,A(e.item.text),1),d("span",sn,[c(s)?(u(),S(ae,{key:0})):x("v-if",!0)])],16)]))}});var an=y(rn,[["__scopeId","data-v-7b16fcd4"]]);const cn=["aria-label"],ln={class:"button-text"},un={class:"dialog"},dn=$({props:{item:null},setup(e){const t=T(),n=P(!1);I(()=>t.path,()=>{n.value=!1});function o(){n.value=!n.value}return(s,i)=>(u(),p("div",{class:F(["nav-dropdown-link",{open:n.value}])},[d("button",{class:"button","aria-label":e.item.ariaLabel,onClick:o},[d("span",ln,A(e.item.text),1),d("span",{class:F(["button-arrow",n.value?"down":"right"])},null,2)],8,cn),d("ul",un,[(u(!0),p(H,null,ne(e.item.items,r=>(u(),p("li",{key:r.text,class:"dialog-item"},[k(an,{item:r},null,8,["item"])]))),128))])],2))}});var be=y(dn,[["__scopeId","data-v-312de885"]]);const hn={key:0,class:"nav-links"},pn={key:1,class:"item"},vn=$({setup(e){const t=R(),n=Ft(),o=_(()=>s.value||repo.value),s=_(()=>t.value.themeConfig.nav);return(i,r)=>c(o)?(u(),p("nav",hn,[c(s)?(u(!0),p(H,{key:0},ne(c(s),a=>(u(),p("div",{key:a.text,class:"item"},[a.items?(u(),S(be,{key:0,item:a},null,8,["item"])):(u(),S(Zt,{key:1,item:a},null,8,["item"]))]))),128)):x("v-if",!0),c(n)?(u(),p("div",pn,[k(be,{item:c(n)},null,8,["item"])])):x("v-if",!0),x(`
+ +
`)])):x("v-if",!0)}});var Me=y(vn,[["__scopeId","data-v-1e870408"]]);const fn={emits:["toggle"]},mn=d("svg",{class:"icon",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img",viewBox:"0 0 448 512"},[d("path",{fill:"currentColor",d:"M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z",class:""})],-1),_n=[mn];function gn(e,t,n,o,s,i){return u(),p("div",{class:"sidebar-button",onClick:t[0]||(t[0]=r=>e.$emit("toggle"))},_n)}var kn=y(fn,[["render",gn]]);const bn={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",width:"1.2em",height:"1.2em",preserveAspectRatio:"xMidYMid meet",viewBox:"0 0 24 24"},xn=d("path",{d:"M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938A7.999 7.999 0 0 0 4 12z",fill:"currentColor"},null,-1),wn=[xn];function $n(e,t){return u(),p("svg",bn,wn)}var yn={name:"ri-moon-line",render:$n};const Ln={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",width:"1.2em",height:"1.2em",preserveAspectRatio:"xMidYMid meet",viewBox:"0 0 24 24"},Cn=d("path",{d:"M12 18a6 6 0 1 1 0-12a6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8a4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636L5.636 7.05L3.515 4.93zM16.95 18.364l1.414-1.414l2.121 2.121l-1.414 1.414l-2.121-2.121zm2.121-14.85l1.414 1.415l-2.121 2.121l-1.414-1.414l2.121-2.121zM5.636 16.95l1.414 1.414l-2.121 2.121l-1.414-1.414l2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z",fill:"currentColor"},null,-1),Sn=[Cn];function En(e,t){return u(),p("svg",Ln,Sn)}var Pn={name:"ri-sun-line",render:En};/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */function An(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(n[o]=e[o]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var s=0,o=Object.getOwnPropertySymbols(e);stypeof e=="string",Y=()=>{};function Bn(e,t){function n(...o){e(()=>t.apply(this,o),{fn:t,thisArg:this,args:o})}return n}const Rn=e=>e();function On(e,t,n={}){const{eventFilter:o=Rn}=n,s=An(n,["eventFilter"]);return I(e,Bn(o,t),s)}function In(e,t=!0){Ae()?j(e):t?e():Le(e)}function je(e){Ae()&&oe(e)}function Nn(e=!1){if(nt(e))return t=>{e.value=typeof t=="boolean"?t:!e.value};{const t=P(e);return[t,o=>{t.value=typeof o=="boolean"?o:!t.value}]}}const E=ce?window:void 0;ce&&window.document;ce&&window.navigator;function Dn(...e){let t,n,o,s;if(Tn(e[0])?([n,o,s]=e,t=E):[t,n,o,s]=e,!t)return Y;let i=Y;const r=I(()=>c(t),l=>{i(),l&&(l.addEventListener(n,o,s),i=()=>{l.removeEventListener(n,o,s),i=Y})},{immediate:!0,flush:"post"}),a=()=>{r(),i()};return je(a),a}function Mn(e,t={}){const{window:n=E}=t;if(!n)return P(!1);const o=n.matchMedia(e),s=P(o.matches),i=r=>{s.value=r.matches};return"addEventListener"in o?o.addEventListener("change",i):o.addListener(i),je(()=>{"removeEventListener"in o?o.removeEventListener("change",i):o.removeListener(i)}),s}const jn={boolean:{read:e=>e!=null?e==="true":null,write:e=>String(e)},object:{read:e=>e?JSON.parse(e):null,write:e=>JSON.stringify(e)},number:{read:e=>e!=null?Number.parseFloat(e):null,write:e=>String(e)},any:{read:e=>e!=null&&e!=="null"?e:null,write:e=>String(e)},string:{read:e=>e!=null?e:null,write:e=>String(e)}};function Hn(e,t,n=E==null?void 0:E.localStorage,o={}){var s;const{flush:i="pre",deep:r=!0,listenToStorageChanges:a=!0,window:l=E,eventFilter:h}=o,v=P(t),w=t==null?"any":typeof t=="boolean"?"boolean":typeof t=="string"?"string":typeof t=="object"||Array.isArray(t)?"object":Number.isNaN(t)?"any":"number",b=(s=o.serializer)!==null&&s!==void 0?s:jn[w];function m(f){if(!!n&&!(f&&f.key!==e))try{const B=f?f.newValue:n.getItem(e);B==null?(v.value=t,n.setItem(e,b.write(t))):v.value=b.read(B)}catch(B){console.warn(B)}}return m(),l&&a&&Dn(l,"storage",m),On(v,()=>{if(!!n)try{v.value==null?n.removeItem(e):n.setItem(e,b.write(v.value))}catch(f){console.warn(f)}},{flush:i,deep:r,eventFilter:h}),v}function Un(e){return Mn("(prefers-color-scheme: dark)",e)}function zn(e={}){const{selector:t="html",attribute:n="class",valueDark:o="dark",valueLight:s="",window:i=E,storage:r=E==null?void 0:E.localStorage,storageKey:a="vueuse-color-scheme",listenToStorageChanges:l=!0}=e,h=Un({window:i}),v=a==null?P("auto"):Hn(a,"auto",r,{window:i,listenToStorageChanges:l}),w=_({get(){return v.value==="auto"?h.value:v.value==="dark"},set(m){m===h.value?v.value="auto":v.value=m?"dark":"light"}}),b=e.onChanged||(m=>{const f=i==null?void 0:i.document.querySelector(t);n==="class"?(f==null||f.classList.toggle(o,m),s&&(f==null||f.classList.toggle(s,!m))):f==null||f.setAttribute(n,m?o:s)});return I(w,b,{flush:"post"}),In(()=>b(w.value)),w}var xe;(function(e){e.UP="UP",e.RIGHT="RIGHT",e.DOWN="DOWN",e.LEFT="LEFT",e.NONE="NONE"})(xe||(xe={}));const Q=zn({storageKey:"vben-admin-color-scheme",valueLight:"light"}),Fn=$({setup(e){const t=Nn(Q);return(n,o)=>{const s=yn,i=Pn;return u(),p("button",{class:"nav-btn","aria-label":"Toggle Theme",onClick:o[0]||(o[0]=(...r)=>c(t)&&c(t)(...r))},[he(k(s,null,null,512),[[pe,c(Q)]]),he(k(i,null,null,512),[[pe,!c(Q)]])])}}}),qn=["GitHub","GitLab","Bitbucket"].map(e=>[e,new RegExp(e,"i")]);function Wn(){const e=R();return _(()=>{const t=e.value.themeConfig,n=t.docsRepo||t.repo;if(!n)return null;const o=Gn(n);return{text:Kn(o,t.repoLabel),link:o}})}function Gn(e){return/^https?:/.test(e)?e:`https://github.com/${e}`}function Kn(e,t){if(t)return t;const n=e.match(/^https?:\/\/[^/]+/);if(!n)return"Source";const o=qn.find(([s,i])=>i.test(n[0]));return o&&o[0]?o[0]:"Source"}const Vn=e=>(Ee("data-v-e81c9962"),e=e(),Pe(),e),Jn={class:"nav-bar"},Yn=Vn(()=>d("div",{class:"flex-grow"},null,-1)),Qn={class:"nav"},Xn={class:"nav-icons"},Zn={class:"item"},eo={key:0,class:"item"},to={class:"nav-btn",href:"https://github.com/vbenjs/vue-vben-admin",target:"_blank","aria-label":"View GitHub Repo"},no=$({emits:["toggle"],setup(e){const t=Wn();return(n,o)=>{const s=Dt;return u(),p("header",Jn,[k(kn,{onToggle:o[0]||(o[0]=i=>n.$emit("toggle"))}),k(zt),Yn,d("div",Qn,[k(Me)]),d("div",Xn,[d("div",Zn,[k(Fn)]),c(t)?(u(),p("div",eo,[d("a",to,[k(s)])])):x("v-if",!0)]),L(n.$slots,"search",{},void 0,!0)])}}});var oo=y(no,[["__scopeId","data-v-e81c9962"]]);function so(){let e=null,t=null;const n=lo(o,300);function o(){const r=ro(),a=io(r);for(let l=0;l ul > li");a&&a!==t.parentElement?(e=a.querySelector("a"),e&&e.classList.add("active")):e=null}function i(r){r&&r.classList.remove("active")}j(()=>{o(),window.addEventListener("scroll",n)}),ot(()=>{s(decodeURIComponent(location.hash))}),oe(()=>{window.removeEventListener("scroll",n)})}function ro(){return[].slice.call(document.querySelectorAll(".sidebar a.sidebar-link-item"))}function io(e){return[].slice.call(document.querySelectorAll(".header-anchor")).filter(t=>e.some(n=>n.hash===t.hash))}function ao(){return document.querySelector(".nav-bar").offsetHeight}function we(e){const t=ao();return e.parentElement.offsetTop-t-15}function co(e,t,n){const o=window.scrollY;return e===0&&o===0?[!0,null]:o{n&&clearTimeout(n),o?n=setTimeout(e,t):(e(),o=!0,setTimeout(()=>{o=!1},t))}}function uo(){const e=T(),t=R();return so(),_(()=>{const n=e.data.headers,o=e.data.frontmatter.sidebar,s=e.data.frontmatter.sidebarDepth;if(o===!1)return[];if(o==="auto")return $e(n,s);const i=ie(t.value.themeConfig.sidebar,e.data.relativePath);return i===!1?[]:i==="auto"?$e(n,s):i})}function $e(e,t){const n=[];if(e===void 0)return[];let o;return e.forEach(({level:s,title:i,slug:r})=>{if(s-1>t)return;const a={text:i,link:`#${r}`};s===2?(o=a,n.push(a)):o&&(o.children||(o.children=[])).push(a)}),n}const He=e=>{const t=T(),n=K(),o=t.data.headers,s=e.item.text,i=ho(n.value.base,e.item.link),r=e.item.children,a=Et(t,e.item.link),l=Ue(a,r,o);return M("li",{class:"sidebar-link"},[M(i?"a":"p",{class:{"sidebar-link-item":!0,active:a},href:i},s),l])};function ho(e,t){return t===void 0||t.startsWith("#")?t:Pt(e,t)}function Ue(e,t,n){return t&&t.length>0?M("ul",{class:"sidebar-links"},t.map(o=>M(He,{item:o}))):e&&n?Ue(!1,po(n)):null}function po(e){return ze(vo(e))}function vo(e){e=e.map(n=>Object.assign({},n));let t;return e.forEach(n=>{n.level===2?t=n:t&&(t.children||(t.children=[])).push(n)}),e.filter(n=>n.level===2)}function ze(e){return e.map(t=>({text:t.title,link:`#${t.slug}`,children:t.children?ze(t.children):void 0}))}const fo={key:0,class:"sidebar-links"},mo=$({setup(e){const t=uo();return(n,o)=>c(t).length>0?(u(),p("ul",fo,[(u(!0),p(H,null,ne(c(t),s=>(u(),S(c(He),{key:s.text,item:s},null,8,["item"]))),128))])):x("v-if",!0)}});const _o=$({props:{open:{type:Boolean,required:!0}},setup(e){return(t,n)=>(u(),p(H,null,[d("aside",{class:F(["sidebar",{open:e.open}])},[k(Me,{class:"nav"}),L(t.$slots,"sidebar-top",{},void 0,!0),k(mo),L(t.$slots,"sidebar-bottom",{},void 0,!0)],2),x(" ")],2112))}});var go=y(_o,[["__scopeId","data-v-4668b452"]]);const ko=/bitbucket.org/;function bo(){const e=R(),t=U(),n=_(()=>{const s=St(t.value.frontmatter.editLink)?e.value.themeConfig.editLinks:t.value.frontmatter.editLink,{repo:i,docsDir:r="",docsBranch:a="master",docsRepo:l=i}=e.value.themeConfig,{relativePath:h}=t.value;return!s||!h||!i?null:xo(i,l,r,a,h)}),o=_(()=>e.value.themeConfig.editLinkText||"Edit this page");return{url:n,text:o}}function xo(e,t,n,o,s){return ko.test(e)?$o(e,t,n,o,s):wo(e,t,n,o,s)}function wo(e,t,n,o,s){return(re(t)?t:`https://github.com/${t}`).replace(W,"")+`/edit/${o}/`+(n?n.replace(W,"")+"/":"")+s}function $o(e,t,n,o,s){return(re(t)?t:e).replace(W,"")+`/src/${o}/`+(n?n.replace(W,"")+"/":"")+s+`?mode=edit&spa=0&at=${o}&fileviewer=file-view-default`}const yo={class:"edit-link"},Lo=["href"],Co=$({setup(e){const{url:t,text:n}=bo();return(o,s)=>(u(),p("div",yo,[c(t)?(u(),p("a",{key:0,class:"link",href:c(t),target:"_blank",rel:"noopener noreferrer"},[te(A(c(n))+" ",1),k(ae,{class:"icon"})],8,Lo)):x("v-if",!0)]))}});var So=y(Co,[["__scopeId","data-v-045573c2"]]);const Eo={key:0,class:"last-updated"},Po={class:"prefix"},Ao={class:"datetime"},To=$({setup(e){const t=R(),n=U(),o=_(()=>{const r=t.value.themeConfig.lastUpdated;return r!==void 0&&r!==!1}),s=_(()=>{const r=t.value.themeConfig.lastUpdated;return r===!0?"Last Updated":r}),i=P("");return j(()=>{i.value=new Date(n.value.lastUpdated).toLocaleString("en-US")}),(r,a)=>c(o)?(u(),p("p",Eo,[d("span",Po,A(c(s))+":",1),d("span",Ao,A(i.value),1)])):x("v-if",!0)}});var Bo=y(To,[["__scopeId","data-v-03e55a27"]]);const Ro={class:"page-footer"},Oo={class:"edit"},Io={class:"updated"},No=$({setup(e){return(t,n)=>(u(),p("footer",Ro,[d("div",Oo,[k(So)]),d("div",Io,[k(Bo)])]))}});var Do=y(No,[["__scopeId","data-v-22e60b1a"]]);function Mo(){const e=R(),t=U(),n=_(()=>Ie(ee(t.value.relativePath))),o=_(()=>{const l=ie(e.value.themeConfig.sidebar,n.value);return se(l)?Ne(l):[]}),s=_(()=>o.value.findIndex(l=>l.link===n.value)),i=_(()=>{if(e.value.themeConfig.nextLinks!==!1&&s.value>-1&&s.value{if(e.value.themeConfig.prevLinks!==!1&&s.value>0)return o.value[s.value-1]}),a=_(()=>!!i.value||!!r.value);return{next:i,prev:r,hasLinks:a}}const jo={},Ho={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Uo=d("path",{d:"M19,11H7.4l5.3-5.3c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0l-7,7c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.2-0.1,0.5,0,0.8c0.1,0.1,0.1,0.2,0.2,0.3l7,7c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L7.4,13H19c0.6,0,1-0.4,1-1S19.6,11,19,11z"},null,-1),zo=[Uo];function Fo(e,t){return u(),p("svg",Ho,zo)}var qo=y(jo,[["render",Fo]]);const Wo={},Go={xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Ko=d("path",{d:"M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z"},null,-1),Vo=[Ko];function Jo(e,t){return u(),p("svg",Go,Vo)}var Yo=y(Wo,[["render",Jo]]);const Qo={key:0,class:"next-and-prev-link"},Xo={class:"container"},Zo={class:"prev"},es=["href"],ts={class:"text"},ns={class:"next"},os=["href"],ss={class:"text"},rs=$({setup(e){const{hasLinks:t,prev:n,next:o}=Mo();return(s,i)=>c(t)?(u(),p("div",Qo,[d("div",Xo,[d("div",Zo,[c(n)?(u(),p("a",{key:0,class:"link",href:s.$withBase(c(n).link)},[k(qo,{class:"icon icon-prev"}),d("span",ts,A(c(n).text),1)],8,es)):x("v-if",!0)]),d("div",ns,[c(o)?(u(),p("a",{key:0,class:"link",href:s.$withBase(c(o).link)},[d("span",ss,A(c(o).text),1),k(Yo,{class:"icon icon-next"})],8,os)):x("v-if",!0)])])])):x("v-if",!0)}});var is=y(rs,[["__scopeId","data-v-0facf926"]]);const as={class:"page"},cs={class:"container"},ls={class:"content"},us=$({setup(e){return(t,n)=>{const o=Z("Content");return u(),p("main",as,[d("div",cs,[L(t.$slots,"top",{},void 0,!0),d("div",ls,[k(o)]),k(Do),k(is),L(t.$slots,"bottom",{},void 0,!0)])])}}});var ds=y(us,[["__scopeId","data-v-7abc59e6"]]);const hs={key:0,id:"ads-container"},ps=$({setup(e){const t=st(()=>Te(()=>import("./Home.559a09dc.js"),["assets/Home.559a09dc.js","assets/plugin-vue_export-helper.147b70e9.js"])),n=()=>null,o=n,s=n,i=n,r=T(),a=K(),l=R(),h=_(()=>a.value.themeConfig),v=U(),w=_(()=>!!r.data.frontmatter.customLayout),b=_(()=>!!r.data.frontmatter.home),m=_(()=>{const{themeConfig:g}=l.value,{frontmatter:N}=r.data;return N.navbar===!1||g.navbar===!1?!1:a.value.title||g.logo||g.repo||g.nav}),f=P(!1),B=_(()=>{const{frontmatter:g}=r.data;if(g.home||g.sidebar===!1)return!1;const{themeConfig:N}=l.value;return!Bt(ie(N.sidebar,r.data.relativePath))}),V=g=>{f.value=typeof g=="boolean"?g:!f.value},qe=V.bind(null,!1);I(r,qe);const We=_(()=>[{"no-navbar":!m.value,"sidebar-open":f.value,"no-sidebar":!B.value}]);return(g,N)=>{const Ge=Z("Content"),Ke=Z("Debug");return u(),p(H,null,[d("div",{class:F(["theme",c(We)])},[c(m)?(u(),S(oo,{key:0,onToggle:V},{search:O(()=>[L(g.$slots,"navbar-search",{},()=>[c(h).algolia?(u(),S(c(i),{options:c(h).algolia,multilang:!!c(h).locales,key:c(l).lang},null,8,["options","multilang"])):x("v-if",!0)])]),_:3})):x("v-if",!0),k(go,{open:f.value},{"sidebar-top":O(()=>[L(g.$slots,"sidebar-top")]),"sidebar-bottom":O(()=>[L(g.$slots,"sidebar-bottom")]),_:3},8,["open"]),x(" TODO: make this button accessible "),d("div",{class:"sidebar-mask",onClick:N[0]||(N[0]=Es=>V(!1))}),c(w)?(u(),S(Ge,{key:1})):c(b)?(u(),S(c(t),{key:2},{hero:O(()=>[L(g.$slots,"home-hero")]),features:O(()=>[L(g.$slots,"home-features")]),footer:O(()=>[L(g.$slots,"home-footer")]),_:3})):(u(),S(ds,{key:3},{top:O(()=>[L(g.$slots,"page-top-ads",{},()=>[c(h).carbonAds&&c(h).carbonAds.carbon?(u(),p("div",hs,[(u(),S(c(o),{key:"carbon"+c(v).relativePath,code:c(h).carbonAds.carbon,placement:c(h).carbonAds.placement},null,8,["code","placement"]))])):x("v-if",!0)]),L(g.$slots,"page-top")]),bottom:O(()=>[L(g.$slots,"page-bottom"),L(g.$slots,"page-bottom-ads",{},()=>[c(h).carbonAds&&c(h).carbonAds.custom?(u(),S(c(s),{key:"custom"+c(v).relativePath,code:c(h).carbonAds.custom,placement:c(h).carbonAds.placement},null,8,["code","placement"])):x("v-if",!0)])]),_:3}))],2),k(Ke)],64)}}}),vs={class:"theme"},fs=d("h1",null,"404",-1),ms=["href"],_s=$({setup(e){const t=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."];function n(){return t[Math.floor(Math.random()*t.length)]}return(o,s)=>(u(),p("div",vs,[fs,d("blockquote",null,A(n()),1),d("a",{href:o.$site.base,"aria-label":"go to home"},"Take me home.",8,ms)]))}}),gs={Layout:ps,NotFound:_s};var G=D({},gs);const X=new Set,Fe=()=>document.createElement("link"),ks=e=>{const t=Fe();t.rel="prefetch",t.href=e,document.head.appendChild(t)},bs=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let z;const xs=C&&(z=Fe())&&z.relList&&z.relList.supports&&z.relList.supports("prefetch")?ks:bs;function ws(){if(!C||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const o=()=>{n&&n.disconnect(),n=new IntersectionObserver(i=>{i.forEach(r=>{if(r.isIntersecting){const a=r.target;n.unobserve(a);const{pathname:l}=a;if(!X.has(l)){X.add(l);const h=Re(l);xs(h)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(i=>{const{target:r,hostname:a,pathname:l}=i,h=l.match(/\.\w+$/);h&&h[0]!==".html"||r!=="_blank"&&a===location.hostname&&(l!==location.pathname?n.observe(i):X.add(l))})})};j(o);const s=T();I(()=>s.path,o),oe(()=>{n&&n.disconnect()})}const $s=G.NotFound||(()=>"404 Not Found"),ys={name:"VitePressApp",setup(){const e=R();return j(()=>{I(()=>e.value.lang,t=>{document.documentElement.lang=t},{immediate:!0})}),ws(),()=>M(G.Layout)}};function Ls(){const e=Ss(),t=Cs();t.provide(Oe,e);const n=R(e.route),o=U(e.route);return C&&bt(e.route,n),mt(t,q,n,o),_t(t),G.enhanceApp&&G.enhanceApp({app:t,router:e,siteData:q}),{app:t,router:e}}function Cs(){return rt(ys)}function Ss(){let e=C,t;return ht(n=>{let o=Re(n);return e&&(t=o),(e||t===o)&&(o=o.replace(/\.js$/,".lean.js")),C?(e=!1,Te(()=>import(o),[])):require(o)},$s)}if(C){const{app:e,router:t}=Ls();t.go().then(()=>{e.mount("#app")})}export{Zt as N,R as a,Ls as createApp,U as u}; diff --git a/assets/components_auth.md.07cfe3e2.js b/assets/components_auth.md.07cfe3e2.js new file mode 100644 index 00000000..e443e0dc --- /dev/null +++ b/assets/components_auth.md.07cfe3e2.js @@ -0,0 +1,15 @@ +import{_ as a,f as n,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Authority","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/auth.md","lastUpdated":1694442156381}',p={},o=t(`

Authority

\u7528\u4E8E\u9879\u76EE\u6743\u9650\u7684\u7EC4\u4EF6\uFF0C\u4E00\u822C\u7528\u4E8E\u6309\u94AE\u7EA7\u7B49\u7EC6\u7C92\u5EA6\u6743\u9650\u7BA1\u7406

Usage

<template>
+  <div>
+    <Authority :value="RoleEnum.ADMIN">
+      <a-button type="primary" block> \u53EA\u6709admin\u89D2\u8272\u53EF\u89C1 </a-button>
+    </Authority>
+  </div>
+</template>
+<script>
+  import { Authority } from '/@/components/Authority';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { Authority },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
valueRoleEnum,RoleEnum[],string,string[]-\u89D2\u8272\u4FE1\u606F\u6216\u8005\u6743\u9650\u7F16\u7801\u3002\u4F1A\u81EA\u52A8\u533A\u5206\u6743\u9650\u6A21\u5F0F
`,6),e=[o];function c(l,u,i,r,k,d){return s(),n("div",null,e)}var _=a(p,[["render",c]]);export{h as __pageData,_ as default}; diff --git a/assets/components_auth.md.07cfe3e2.lean.js b/assets/components_auth.md.07cfe3e2.lean.js new file mode 100644 index 00000000..3ce22ecf --- /dev/null +++ b/assets/components_auth.md.07cfe3e2.lean.js @@ -0,0 +1,15 @@ +import{_ as a,f as n,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Authority","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/auth.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Authority

\u7528\u4E8E\u9879\u76EE\u6743\u9650\u7684\u7EC4\u4EF6\uFF0C\u4E00\u822C\u7528\u4E8E\u6309\u94AE\u7EA7\u7B49\u7EC6\u7C92\u5EA6\u6743\u9650\u7BA1\u7406

Usage

<template>
+  <div>
+    <Authority :value="RoleEnum.ADMIN">
+      <a-button type="primary" block> \u53EA\u6709admin\u89D2\u8272\u53EF\u89C1 </a-button>
+    </Authority>
+  </div>
+</template>
+<script>
+  import { Authority } from '/@/components/Authority';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { Authority },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
valueRoleEnum,RoleEnum[],string,string[]-\u89D2\u8272\u4FE1\u606F\u6216\u8005\u6743\u9650\u7F16\u7801\u3002\u4F1A\u81EA\u52A8\u533A\u5206\u6743\u9650\u6A21\u5F0F
__VP_STATIC_END__`,6),e=[o];function c(l,u,i,r,k,d){return s(),n("div",null,e)}var _=a(p,[["render",c]]);export{h as __pageData,_ as default}; diff --git a/assets/components_basic.md.3f569d5b.js b/assets/components_basic.md.3f569d5b.js new file mode 100644 index 00000000..6132a7c9 --- /dev/null +++ b/assets/components_basic.md.3f569d5b.js @@ -0,0 +1,39 @@ +import{_ as a,f as s,e as n,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Basic \u57FA\u7840\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"BasicTitle","slug":"basictitle"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":3,"title":"Slots","slug":"slots"},{"level":2,"title":"BasicArrow","slug":"basicarrow"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"},{"level":2,"title":"BasicHelp","slug":"basichelp"},{"level":3,"title":"Usage","slug":"usage-2"},{"level":3,"title":"Props","slug":"props-2"},{"level":3,"title":"Slots","slug":"slots-1"}],"relativePath":"components/basic.md","lastUpdated":1694442156381}',p={},e=t(`

Basic \u57FA\u7840\u7EC4\u4EF6

\u4E00\u4E9B\u6BD4\u8F83\u57FA\u7840\u7684\u901A\u7528\u7EC4\u4EF6\u4F7F\u7528\u65B9\u5F0F

BasicTitle

\u7528\u4E8E\u663E\u793A\u6807\u9898\uFF0C\u53EF\u4EE5\u663E\u793A\u5E2E\u52A9\u6309\u94AE\u53CA\u6587\u672C

Usage

<template>
+  <div>
+    <BasicTitle helpMessage="\u63D0\u793A1">\u6807\u9898</BasicTitle>
+    <BasicTitle :helpMessage="['\u63D0\u793A1', '\u63D0\u793A2']">\u6807\u9898</BasicTitle>
+  </div>
+</template>
+<script>
+  import { BasicTitle } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicTitle },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
helpMessagestring\uFF5Cstring[]-\u6807\u9898\u53F3\u4FA7\u5E2E\u52A9\u6309\u94AE\u4FE1\u606F
spanbooleanfalse\u662F\u5426\u663E\u793A\u6807\u9898\u5DE6\u4FA7\u84DD\u8272\u8272\u5757
normalbooleanfalse\u5C06\u6587\u5B57\u9ED8\u8BA4\u5316\uFF0C\u4E0D\u52A0\u7C97

Slots

\u540D\u79F0\u8BF4\u660E
default\u6807\u9898\u6587\u672C

BasicArrow

\u5E26\u52A8\u753B\u7684\u7BAD\u5934\u7EC4\u4EF6

Usage

<template>
+  <div>
+    <BasicArrow :expand="false" />
+  </div>
+</template>
+<script>
+  import { BasicArrow } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicArrow },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
expandbooleanfalse\u7BAD\u5934\u5C55\u5F00\u72B6\u6001
topbooleanfalse\u7BAD\u5934\u9ED8\u8BA4\u5411\u4E0A
bottombooleanfalse\u7BAD\u5934\u9ED8\u8BA4\u5411\u4E0B
insetbooleanfalse\u53D6\u6D88 padding/margin\uFF0C\u7528\u4E8E\u5185\u5D4C

BasicHelp

\u5E2E\u52A9\u6309\u94AE\u7EC4\u4EF6

Usage

<template>
+  <div>
+    <BasicHelp :text="['\u63D0\u793A1', '\u63D0\u793A2']" />
+    <BasicHelp text="\u63D0\u793A" />
+  </div>
+</template>
+<script>
+  import { BasicHelp } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicHelp },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
fontSizestring14px-\u5B57\u4F53\u5927\u5C0F
colorstring#fff-\u989C\u8272
textstring\uFF5Cstring[]--\u6587\u672C\u5217\u8868
showIndexbooleantrue-\u662F\u5426\u663E\u793A\u5E8F\u53F7,\u5728 text \u4E3A string[]\u60C5\u51B5\u4E0B\u751F\u6548
maxWidthstring600px-\u6700\u5927\u5BBD\u5EA6
placementstringright-\u663E\u793A\u65B9\u5411\uFF0C\u53C2\u8003 Tooltip \u7EC4\u4EF6

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4\u56FE\u6807
`,24),o=[e];function c(l,u,d,i,r,k){return n(),s("div",null,o)}var f=a(p,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/components_basic.md.3f569d5b.lean.js b/assets/components_basic.md.3f569d5b.lean.js new file mode 100644 index 00000000..3449f896 --- /dev/null +++ b/assets/components_basic.md.3f569d5b.lean.js @@ -0,0 +1,39 @@ +import{_ as a,f as s,e as n,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Basic \u57FA\u7840\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"BasicTitle","slug":"basictitle"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":3,"title":"Slots","slug":"slots"},{"level":2,"title":"BasicArrow","slug":"basicarrow"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"},{"level":2,"title":"BasicHelp","slug":"basichelp"},{"level":3,"title":"Usage","slug":"usage-2"},{"level":3,"title":"Props","slug":"props-2"},{"level":3,"title":"Slots","slug":"slots-1"}],"relativePath":"components/basic.md","lastUpdated":1694442156381}',p={},e=t(`__VP_STATIC_START__

Basic \u57FA\u7840\u7EC4\u4EF6

\u4E00\u4E9B\u6BD4\u8F83\u57FA\u7840\u7684\u901A\u7528\u7EC4\u4EF6\u4F7F\u7528\u65B9\u5F0F

BasicTitle

\u7528\u4E8E\u663E\u793A\u6807\u9898\uFF0C\u53EF\u4EE5\u663E\u793A\u5E2E\u52A9\u6309\u94AE\u53CA\u6587\u672C

Usage

<template>
+  <div>
+    <BasicTitle helpMessage="\u63D0\u793A1">\u6807\u9898</BasicTitle>
+    <BasicTitle :helpMessage="['\u63D0\u793A1', '\u63D0\u793A2']">\u6807\u9898</BasicTitle>
+  </div>
+</template>
+<script>
+  import { BasicTitle } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicTitle },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
helpMessagestring\uFF5Cstring[]-\u6807\u9898\u53F3\u4FA7\u5E2E\u52A9\u6309\u94AE\u4FE1\u606F
spanbooleanfalse\u662F\u5426\u663E\u793A\u6807\u9898\u5DE6\u4FA7\u84DD\u8272\u8272\u5757
normalbooleanfalse\u5C06\u6587\u5B57\u9ED8\u8BA4\u5316\uFF0C\u4E0D\u52A0\u7C97

Slots

\u540D\u79F0\u8BF4\u660E
default\u6807\u9898\u6587\u672C

BasicArrow

\u5E26\u52A8\u753B\u7684\u7BAD\u5934\u7EC4\u4EF6

Usage

<template>
+  <div>
+    <BasicArrow :expand="false" />
+  </div>
+</template>
+<script>
+  import { BasicArrow } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicArrow },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
expandbooleanfalse\u7BAD\u5934\u5C55\u5F00\u72B6\u6001
topbooleanfalse\u7BAD\u5934\u9ED8\u8BA4\u5411\u4E0A
bottombooleanfalse\u7BAD\u5934\u9ED8\u8BA4\u5411\u4E0B
insetbooleanfalse\u53D6\u6D88 padding/margin\uFF0C\u7528\u4E8E\u5185\u5D4C

BasicHelp

\u5E2E\u52A9\u6309\u94AE\u7EC4\u4EF6

Usage

<template>
+  <div>
+    <BasicHelp :text="['\u63D0\u793A1', '\u63D0\u793A2']" />
+    <BasicHelp text="\u63D0\u793A" />
+  </div>
+</template>
+<script>
+  import { BasicHelp } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicHelp },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
fontSizestring14px-\u5B57\u4F53\u5927\u5C0F
colorstring#fff-\u989C\u8272
textstring\uFF5Cstring[]--\u6587\u672C\u5217\u8868
showIndexbooleantrue-\u662F\u5426\u663E\u793A\u5E8F\u53F7,\u5728 text \u4E3A string[]\u60C5\u51B5\u4E0B\u751F\u6548
maxWidthstring600px-\u6700\u5927\u5BBD\u5EA6
placementstringright-\u663E\u793A\u65B9\u5411\uFF0C\u53C2\u8003 Tooltip \u7EC4\u4EF6

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4\u56FE\u6807
__VP_STATIC_END__`,24),o=[e];function c(l,u,d,i,r,k){return n(),s("div",null,o)}var f=a(p,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/components_click-out-side.md.cb80a16e.js b/assets/components_click-out-side.md.cb80a16e.js new file mode 100644 index 00000000..41aa91f6 --- /dev/null +++ b/assets/components_click-out-side.md.cb80a16e.js @@ -0,0 +1,23 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"ClickOutSide","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Events","slug":"events"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/click-out-side.md","lastUpdated":1694442156381}',p={},e=t(`

ClickOutSide

\u7528\u4E8E\u76D1\u542C\u5305\u88F9\u7684\u5143\u7D20\u70B9\u51FB\u5916\u90E8\u89E6\u53D1\u4E8B\u4EF6

Usage

<template>
+  <div>
+    <ClickOutSide @clickOutside="() => (showRef = false)">
+      <div @click="() => (showRef = true)">
+        {{ showRef ? '\u9F20\u6807\u70B9\u51FB\u90A3\u90E8\uFF08\u70B9\u51FB\u8FB9\u6846\u5916\u53EF\u4EE5\u6062\u590D\uFF09' : '\u70B9\u51FB\u8BE5\u533A\u57DF\u72B6\u6001(\u521D\u59CB\u72B6\u6001)' }}
+      </div>
+    </ClickOutSide>
+  </div>
+</template>
+<script>
+  import { defineComponent, ref } from 'vue';
+  import { ClickOutSide } from '/@/components/ClickOutSide/';
+  export default defineComponent({
+    components: { ClickOutSide },
+    setup() {
+      const showRef = ref(false);
+      return {
+        showRef,
+      };
+    },
+  });
+</script>
+

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
clickOutside()=>void\u70B9\u51FB\u5305\u88F9\u5143\u7D20\u5916\u90E8\u533A\u57DF\u89E6\u53D1

Slots

\u540D\u79F0\u8BF4\u660E
default\u88AB\u5305\u88F9\u7684\u5143\u7D20
`,8),o=[e];function c(l,u,i,k,r,d){return a(),s("div",null,o)}var f=n(p,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/components_click-out-side.md.cb80a16e.lean.js b/assets/components_click-out-side.md.cb80a16e.lean.js new file mode 100644 index 00000000..99ef04b5 --- /dev/null +++ b/assets/components_click-out-side.md.cb80a16e.lean.js @@ -0,0 +1,23 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"ClickOutSide","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Events","slug":"events"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/click-out-side.md","lastUpdated":1694442156381}',p={},e=t(`__VP_STATIC_START__

ClickOutSide

\u7528\u4E8E\u76D1\u542C\u5305\u88F9\u7684\u5143\u7D20\u70B9\u51FB\u5916\u90E8\u89E6\u53D1\u4E8B\u4EF6

Usage

<template>
+  <div>
+    <ClickOutSide @clickOutside="() => (showRef = false)">
+      <div @click="() => (showRef = true)">
+        {{ showRef ? '\u9F20\u6807\u70B9\u51FB\u90A3\u90E8\uFF08\u70B9\u51FB\u8FB9\u6846\u5916\u53EF\u4EE5\u6062\u590D\uFF09' : '\u70B9\u51FB\u8BE5\u533A\u57DF\u72B6\u6001(\u521D\u59CB\u72B6\u6001)' }}
+      </div>
+    </ClickOutSide>
+  </div>
+</template>
+<script>
+  import { defineComponent, ref } from 'vue';
+  import { ClickOutSide } from '/@/components/ClickOutSide/';
+  export default defineComponent({
+    components: { ClickOutSide },
+    setup() {
+      const showRef = ref(false);
+      return {
+        showRef,
+      };
+    },
+  });
+</script>
+

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
clickOutside()=>void\u70B9\u51FB\u5305\u88F9\u5143\u7D20\u5916\u90E8\u533A\u57DF\u89E6\u53D1

Slots

\u540D\u79F0\u8BF4\u660E
default\u88AB\u5305\u88F9\u7684\u5143\u7D20
__VP_STATIC_END__`,8),o=[e];function c(l,u,i,k,r,d){return a(),s("div",null,o)}var f=n(p,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/components_code-editor.md.ff3c8cbd.js b/assets/components_code-editor.md.ff3c8cbd.js new file mode 100644 index 00000000..2ae475de --- /dev/null +++ b/assets/components_code-editor.md.ff3c8cbd.js @@ -0,0 +1,14 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"CodeEditor","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/code-editor.md","lastUpdated":1694442156381}',p={},o=t(`

CodeEditor

\u4EE3\u7801\u7F16\u8F91\u5668

Usage

<template>
+  <CodeEditor v-model:value="value" :mode="modeValue" />
+</template>
+<script>
+  import { defineComponent, ref } from 'vue';
+  export default defineComponent({
+    components: { CodeEditor },
+    setup() {
+      const modeValue = ref('application/json');
+      return { value, modeValue };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
value(v-model:value)any--\u7ED1\u5B9A\u503C
modestringapplication/json'application/json','htmlmixed','javascript'\u4EE3\u7801\u7C7B\u578B
readonlyboolean--\u662F\u5426\u53EA\u8BFB
`,6),e=[o];function c(l,u,d,i,r,k){return s(),a("div",null,e)}var _=n(p,[["render",c]]);export{g as __pageData,_ as default}; diff --git a/assets/components_code-editor.md.ff3c8cbd.lean.js b/assets/components_code-editor.md.ff3c8cbd.lean.js new file mode 100644 index 00000000..b6dd1e84 --- /dev/null +++ b/assets/components_code-editor.md.ff3c8cbd.lean.js @@ -0,0 +1,14 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"CodeEditor","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/code-editor.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

CodeEditor

\u4EE3\u7801\u7F16\u8F91\u5668

Usage

<template>
+  <CodeEditor v-model:value="value" :mode="modeValue" />
+</template>
+<script>
+  import { defineComponent, ref } from 'vue';
+  export default defineComponent({
+    components: { CodeEditor },
+    setup() {
+      const modeValue = ref('application/json');
+      return { value, modeValue };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
value(v-model:value)any--\u7ED1\u5B9A\u503C
modestringapplication/json'application/json','htmlmixed','javascript'\u4EE3\u7801\u7C7B\u578B
readonlyboolean--\u662F\u5426\u53EA\u8BFB
__VP_STATIC_END__`,6),e=[o];function c(l,u,d,i,r,k){return s(),a("div",null,e)}var _=n(p,[["render",c]]);export{g as __pageData,_ as default}; diff --git a/assets/components_collapse-container.md.74719c99.js b/assets/components_collapse-container.md.74719c99.js new file mode 100644 index 00000000..c277c30c --- /dev/null +++ b/assets/components_collapse-container.md.74719c99.js @@ -0,0 +1,16 @@ +import{_ as t,f as a,e as n,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"CollapseContainer","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/collapse-container.md","lastUpdated":1694442156381}',e={},p=s(`

CollapseContainer

\u533A\u57DF\u6298\u53E0\u5361\u7247\u5BB9\u5668

Usage

<template>
+  <div>
+    <CollapseContainer> content </CollapseContainer>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CollapseContainer } from '/@/components/Container/index';
+
+  export default defineComponent({
+    components: {
+      CollapseContainer,
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
titlestring--\u6807\u9898
canExpanbooleantrue-\u662F\u5426\u53EF\u4EE5\u5C55\u5F00\uFF0C\u4E3Atrue\u663E\u793A\u6298\u53E0\u6309\u94AE
helpMessagestring[],string--\u6807\u9898\u53F3\u4FA7\u6E29\u99A8\u63D0\u9192
triggerWindowResizebooleanfalse-\u5C55\u5F00\u6536\u7F29\u7684\u65F6\u5019\u662F\u5426\u89E6\u53D1 window.resize
loadingbooleanfalse-\u663E\u793A\u52A0\u8F7D\u9AA8\u67B6\u5C4F
lazyTimenumber0-\u5EF6\u8FDF\u52A0\u8F7D\u65F6\u95F4

Slots

\u540D\u79F0\u8BF4\u660E
title\u81EA\u5B9A\u4E49\u6807\u9898
action\u81EA\u5B9A\u4E49\u53F3\u4FA7\u64CD\u4F5C\u6309\u94AE
default\u9ED8\u8BA4\u533A\u57DF
footer\u81EA\u5B9A\u4E49\u5E95\u90E8\u533A\u57DF
`,8),o=[p];function c(l,d,r,i,u,k){return n(),a("div",null,o)}var _=t(e,[["render",c]]);export{g as __pageData,_ as default}; diff --git a/assets/components_collapse-container.md.74719c99.lean.js b/assets/components_collapse-container.md.74719c99.lean.js new file mode 100644 index 00000000..c10fcb9d --- /dev/null +++ b/assets/components_collapse-container.md.74719c99.lean.js @@ -0,0 +1,16 @@ +import{_ as t,f as a,e as n,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"CollapseContainer","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/collapse-container.md","lastUpdated":1694442156381}',e={},p=s(`__VP_STATIC_START__

CollapseContainer

\u533A\u57DF\u6298\u53E0\u5361\u7247\u5BB9\u5668

Usage

<template>
+  <div>
+    <CollapseContainer> content </CollapseContainer>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CollapseContainer } from '/@/components/Container/index';
+
+  export default defineComponent({
+    components: {
+      CollapseContainer,
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
titlestring--\u6807\u9898
canExpanbooleantrue-\u662F\u5426\u53EF\u4EE5\u5C55\u5F00\uFF0C\u4E3Atrue\u663E\u793A\u6298\u53E0\u6309\u94AE
helpMessagestring[],string--\u6807\u9898\u53F3\u4FA7\u6E29\u99A8\u63D0\u9192
triggerWindowResizebooleanfalse-\u5C55\u5F00\u6536\u7F29\u7684\u65F6\u5019\u662F\u5426\u89E6\u53D1 window.resize
loadingbooleanfalse-\u663E\u793A\u52A0\u8F7D\u9AA8\u67B6\u5C4F
lazyTimenumber0-\u5EF6\u8FDF\u52A0\u8F7D\u65F6\u95F4

Slots

\u540D\u79F0\u8BF4\u660E
title\u81EA\u5B9A\u4E49\u6807\u9898
action\u81EA\u5B9A\u4E49\u53F3\u4FA7\u64CD\u4F5C\u6309\u94AE
default\u9ED8\u8BA4\u533A\u57DF
footer\u81EA\u5B9A\u4E49\u5E95\u90E8\u533A\u57DF
__VP_STATIC_END__`,8),o=[p];function c(l,d,r,i,u,k){return n(),a("div",null,o)}var _=t(e,[["render",c]]);export{g as __pageData,_ as default}; diff --git a/assets/components_count-down.md.754844e3.js b/assets/components_count-down.md.754844e3.js new file mode 100644 index 00000000..54c6ff36 --- /dev/null +++ b/assets/components_count-down.md.754844e3.js @@ -0,0 +1,23 @@ +import{_ as n,f as t,e as a,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"CountDown","description":"","frontmatter":{},"headers":[{"level":2,"title":"CountButton","slug":"countbutton"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":2,"title":"CountDownInput","slug":"countdowninput"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"}],"relativePath":"components/count-down.md","lastUpdated":1694442156381}',p={},o=s(`

CountDown

\u5012\u8BA1\u65F6\u7EC4\u4EF6

CountButton

\u5012\u8BA1\u65F6\u6309\u94AE\u7EC4\u4EF6

Usage

<template>
+  <CountButton />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountButton } from '/@/components/CountDown';
+
+  export default defineComponent({
+    components: { CountButton },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valueany--\u7ED1\u5B9A\u503C
countnumber60-\u5012\u8BA1\u65F6\u65F6\u95F4
beforeStartFunc()=>promise--\u5012\u8BA1\u65F6\u4E4B\u524D\u6267\u884C\u7684\u51FD\u6570\uFF0C\u8FD4\u56DE true \u624D\u4F1A\u5F00\u59CB\u6267\u884C

CountDownInput

\u5012\u8BA1\u65F6\u8F93\u5165\u6846\u6309\u94AE\u7EC4\u4EF6

Usage

<template>
+  <CountdownInput />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountdownInput } from '/@/components/CountDown';
+
+  export default defineComponent({
+    components: { CountdownInput },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valueany--\u7ED1\u5B9A\u503C
sizestring'default', 'large', 'small'-\u8F93\u5165\u6846\u5373\u6309\u94AE\u5927\u5C0F
countnumber60-\u5012\u8BA1\u65F6\u65F6\u95F4
sendCodeApi()=>promise--\u5012\u8BA1\u65F6\u4E4B\u524D\u6267\u884C\u7684\u51FD\u6570\uFF0C\u8FD4\u56DE true \u624D\u4F1A\u5F00\u59CB\u6267\u884C
`,14),e=[o];function c(u,l,d,r,i,k){return a(),t("div",null,e)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_count-down.md.754844e3.lean.js b/assets/components_count-down.md.754844e3.lean.js new file mode 100644 index 00000000..099748b7 --- /dev/null +++ b/assets/components_count-down.md.754844e3.lean.js @@ -0,0 +1,23 @@ +import{_ as n,f as t,e as a,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"CountDown","description":"","frontmatter":{},"headers":[{"level":2,"title":"CountButton","slug":"countbutton"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":2,"title":"CountDownInput","slug":"countdowninput"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"}],"relativePath":"components/count-down.md","lastUpdated":1694442156381}',p={},o=s(`__VP_STATIC_START__

CountDown

\u5012\u8BA1\u65F6\u7EC4\u4EF6

CountButton

\u5012\u8BA1\u65F6\u6309\u94AE\u7EC4\u4EF6

Usage

<template>
+  <CountButton />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountButton } from '/@/components/CountDown';
+
+  export default defineComponent({
+    components: { CountButton },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valueany--\u7ED1\u5B9A\u503C
countnumber60-\u5012\u8BA1\u65F6\u65F6\u95F4
beforeStartFunc()=>promise--\u5012\u8BA1\u65F6\u4E4B\u524D\u6267\u884C\u7684\u51FD\u6570\uFF0C\u8FD4\u56DE true \u624D\u4F1A\u5F00\u59CB\u6267\u884C

CountDownInput

\u5012\u8BA1\u65F6\u8F93\u5165\u6846\u6309\u94AE\u7EC4\u4EF6

Usage

<template>
+  <CountdownInput />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountdownInput } from '/@/components/CountDown';
+
+  export default defineComponent({
+    components: { CountdownInput },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valueany--\u7ED1\u5B9A\u503C
sizestring'default', 'large', 'small'-\u8F93\u5165\u6846\u5373\u6309\u94AE\u5927\u5C0F
countnumber60-\u5012\u8BA1\u65F6\u65F6\u95F4
sendCodeApi()=>promise--\u5012\u8BA1\u65F6\u4E4B\u524D\u6267\u884C\u7684\u51FD\u6570\uFF0C\u8FD4\u56DE true \u624D\u4F1A\u5F00\u59CB\u6267\u884C
__VP_STATIC_END__`,14),e=[o];function c(u,l,d,r,i,k){return a(),t("div",null,e)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_count-to.md.0bf9d55c.js b/assets/components_count-to.md.0bf9d55c.js new file mode 100644 index 00000000..49621a27 --- /dev/null +++ b/assets/components_count-to.md.0bf9d55c.js @@ -0,0 +1,14 @@ +import{_ as t,f as a,e as n,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"CountTo","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Methods","slug":"methods"}],"relativePath":"components/count-to.md","lastUpdated":1694442156381}',o={},e=s(`

CountTo

\u6570\u5B57\u52A8\u753B\u7EC4\u4EF6

\u8BE5\u7EC4\u4EF6\u5BF9 vue-countTo \u8FDB\u884C\u4E86\u91CD\u6784\uFF0C\u6539\u9020\u6210\u9002\u914D vue3 \u8BED\u6CD5\u7684\u7EC4\u4EF6\u3002

Usage

<template>
+  <CountTo prefix="$" :color="'#409EFF'" :startVal="1" :endVal="200000" :duration="8000" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountTo } from '/@/components/CountTo/index';
+
+  export default defineComponent({
+    components: {
+      CountTo,
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
startValnumber0\u8D77\u59CB\u503C
endValnumber2021\u7ED3\u675F\u503C
durationnumber1500\u52A8\u753B\u6301\u7EED\u65F6\u95F4
autoplaybooleantrue\u81EA\u52A8\u6267\u884C
prefixstring-\u524D\u7F00
suffixstring-\u540E\u7F00
separatorstring,\u5206\u9694\u7B26
colorstring-\u5B57\u4F53\u989C\u8272
useEasingbooleantrue\u662F\u5426\u5F00\u542F\u52A8\u753B
transitionstringlinear\u52A8\u753B\u6548\u679C
decimalsnumber0\u4FDD\u7559\u5C0F\u6570\u70B9\u4F4D\u6570

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
start()=>void\u5F00\u59CB\u6267\u884C\u52A8\u753B
reset()=>void\u91CD\u7F6E
`,9),p=[e];function c(d,u,r,l,i,k){return n(),a("div",null,p)}var m=t(o,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_count-to.md.0bf9d55c.lean.js b/assets/components_count-to.md.0bf9d55c.lean.js new file mode 100644 index 00000000..b8495d17 --- /dev/null +++ b/assets/components_count-to.md.0bf9d55c.lean.js @@ -0,0 +1,14 @@ +import{_ as t,f as a,e as n,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"CountTo","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Methods","slug":"methods"}],"relativePath":"components/count-to.md","lastUpdated":1694442156381}',o={},e=s(`__VP_STATIC_START__

CountTo

\u6570\u5B57\u52A8\u753B\u7EC4\u4EF6

\u8BE5\u7EC4\u4EF6\u5BF9 vue-countTo \u8FDB\u884C\u4E86\u91CD\u6784\uFF0C\u6539\u9020\u6210\u9002\u914D vue3 \u8BED\u6CD5\u7684\u7EC4\u4EF6\u3002

Usage

<template>
+  <CountTo prefix="$" :color="'#409EFF'" :startVal="1" :endVal="200000" :duration="8000" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountTo } from '/@/components/CountTo/index';
+
+  export default defineComponent({
+    components: {
+      CountTo,
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
startValnumber0\u8D77\u59CB\u503C
endValnumber2021\u7ED3\u675F\u503C
durationnumber1500\u52A8\u753B\u6301\u7EED\u65F6\u95F4
autoplaybooleantrue\u81EA\u52A8\u6267\u884C
prefixstring-\u524D\u7F00
suffixstring-\u540E\u7F00
separatorstring,\u5206\u9694\u7B26
colorstring-\u5B57\u4F53\u989C\u8272
useEasingbooleantrue\u662F\u5426\u5F00\u542F\u52A8\u753B
transitionstringlinear\u52A8\u753B\u6548\u679C
decimalsnumber0\u4FDD\u7559\u5C0F\u6570\u70B9\u4F4D\u6570

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
start()=>void\u5F00\u59CB\u6267\u884C\u52A8\u753B
reset()=>void\u91CD\u7F6E
__VP_STATIC_END__`,9),p=[e];function c(d,u,r,l,i,k){return n(),a("div",null,p)}var m=t(o,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_cropper.md.3c79f232.js b/assets/components_cropper.md.3c79f232.js new file mode 100644 index 00000000..c648eac6 --- /dev/null +++ b/assets/components_cropper.md.3c79f232.js @@ -0,0 +1,67 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Cropper","description":"","frontmatter":{},"headers":[{"level":2,"title":"CropperImage","slug":"cropperimage"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":2,"title":"CropperAvatar","slug":"cropperavatar"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"},{"level":3,"title":"Events","slug":"events"},{"level":3,"title":"Methods","slug":"methods"}],"relativePath":"components/cropper.md","lastUpdated":1694442156381}',p={},o=t(`

Cropper

\u56FE\u7247\u88C1\u526A\u7EC4\u4EF6

CropperImage

\u56FE\u7247\u88C1\u526A\u7EC4\u4EF6

Usage

<template>
+  <CropperImage ref="refCropper" :src="img" @cropend="handleCropend" style="width: 40vw" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { CropperImage } from '/@/components/Cropper';
+  import img from '/@/assets/images/header.jpg';
+
+  export default defineComponent({
+    components: {
+      CropperImage,
+    },
+    setup() {
+      const info = ref('');
+      const cropperImg = ref('');
+
+      function handleCropend({ imgBase64, imgInfo }) {
+        info.value = imgInfo;
+        cropperImg.value = imgBase64;
+      }
+
+      return {
+        img,
+        info,
+        cropperImg,
+        handleCropend,
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
srcstring-\u56FE\u7247\u6E90
altstring-\u56FE\u7247 alt
circledbooleanfalse\u5706\u5F62\u88C1\u526A\u6846
realTimePreviewbooleantrue\u5B9E\u65F6\u89E6\u53D1\u9884\u89C8
heightstring360px\u9AD8\u5EA6
crossoriginstring-crossorigin
imageStyleobject\`\`\u56FE\u7247\u6837\u5F0F
optionsobjectDefaultOptionscorpperjs \u914D\u7F6E\u9879

DefaultOptions

{
+  aspectRatio: 1,
+  zoomable: true,
+  zoomOnTouch: true,
+  zoomOnWheel: true,
+  cropBoxMovable: true,
+  cropBoxResizable: true,
+  toggleDragModeOnDblclick: true,
+  autoCrop: true,
+  background: true,
+  highlight: true,
+  center: true,
+  responsive: true,
+  restore: true,
+  checkCrossOrigin: true,
+  checkOrientation: true,
+  scalable: true,
+  modal: true,
+  guides: true,
+  movable: true,
+  rotatable: true,
+}
+

CropperAvatar

\u5934\u50CF\u88C1\u526A\u7EC4\u4EF6

Usage

<template>
+  <CropperAvatar :uploadApi="uploadApi" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { CropperAvatar } from '/@/components/Cropper';
+  import { uploadApi } from '/@/api/sys/upload';
+
+  export default defineComponent({
+    components: {
+      CropperAvatar,
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E\u7248\u672C
widthstring,number200px\u56FE\u7247\u6E90
uploadApi({ file: Blob, name: string }) => Promise<void>-\u56FE\u7247\u4E0A\u4F20\u63A5\u53E3
valueString-\u5F53\u524D\u5934\u50CF\u5730\u5740(v-model)2.5.3
showBtnBooleantrue\u662F\u5426\u663E\u793A\u6309\u94AE2.5.3
btnTextString-\u6309\u94AE\u6587\u68482.5.3
btnPropsButtonProps-\u6309\u94AE\u7684\u5176\u5B83\u5C5E\u60272.5.3

Events

\u540D\u79F0\u53C2\u6570\u8BF4\u660E\u7248\u672C
changevalue: String\u5F53\u5934\u50CF\u4E0A\u4F20\u5B8C\u6210\u65F6\u89E6\u53D12.5.3

Methods

\u540D\u79F0\u5B9A\u4E49\u8BF4\u660E\u7248\u672C
openModal()=>void\u6253\u5F00\u4E0A\u4F20Modal2.5.3
closeModal()=>void\u5173\u95ED\u4E0A\u4F20Modal2.5.3
`,20),e=[o];function c(l,r,u,d,i,k){return s(),a("div",null,e)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_cropper.md.3c79f232.lean.js b/assets/components_cropper.md.3c79f232.lean.js new file mode 100644 index 00000000..1faf88bf --- /dev/null +++ b/assets/components_cropper.md.3c79f232.lean.js @@ -0,0 +1,67 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Cropper","description":"","frontmatter":{},"headers":[{"level":2,"title":"CropperImage","slug":"cropperimage"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":2,"title":"CropperAvatar","slug":"cropperavatar"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"},{"level":3,"title":"Events","slug":"events"},{"level":3,"title":"Methods","slug":"methods"}],"relativePath":"components/cropper.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Cropper

\u56FE\u7247\u88C1\u526A\u7EC4\u4EF6

CropperImage

\u56FE\u7247\u88C1\u526A\u7EC4\u4EF6

Usage

<template>
+  <CropperImage ref="refCropper" :src="img" @cropend="handleCropend" style="width: 40vw" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { CropperImage } from '/@/components/Cropper';
+  import img from '/@/assets/images/header.jpg';
+
+  export default defineComponent({
+    components: {
+      CropperImage,
+    },
+    setup() {
+      const info = ref('');
+      const cropperImg = ref('');
+
+      function handleCropend({ imgBase64, imgInfo }) {
+        info.value = imgInfo;
+        cropperImg.value = imgBase64;
+      }
+
+      return {
+        img,
+        info,
+        cropperImg,
+        handleCropend,
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
srcstring-\u56FE\u7247\u6E90
altstring-\u56FE\u7247 alt
circledbooleanfalse\u5706\u5F62\u88C1\u526A\u6846
realTimePreviewbooleantrue\u5B9E\u65F6\u89E6\u53D1\u9884\u89C8
heightstring360px\u9AD8\u5EA6
crossoriginstring-crossorigin
imageStyleobject\`\`\u56FE\u7247\u6837\u5F0F
optionsobjectDefaultOptionscorpperjs \u914D\u7F6E\u9879

DefaultOptions

{
+  aspectRatio: 1,
+  zoomable: true,
+  zoomOnTouch: true,
+  zoomOnWheel: true,
+  cropBoxMovable: true,
+  cropBoxResizable: true,
+  toggleDragModeOnDblclick: true,
+  autoCrop: true,
+  background: true,
+  highlight: true,
+  center: true,
+  responsive: true,
+  restore: true,
+  checkCrossOrigin: true,
+  checkOrientation: true,
+  scalable: true,
+  modal: true,
+  guides: true,
+  movable: true,
+  rotatable: true,
+}
+

CropperAvatar

\u5934\u50CF\u88C1\u526A\u7EC4\u4EF6

Usage

<template>
+  <CropperAvatar :uploadApi="uploadApi" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { CropperAvatar } from '/@/components/Cropper';
+  import { uploadApi } from '/@/api/sys/upload';
+
+  export default defineComponent({
+    components: {
+      CropperAvatar,
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E\u7248\u672C
widthstring,number200px\u56FE\u7247\u6E90
uploadApi({ file: Blob, name: string }) => Promise<void>-\u56FE\u7247\u4E0A\u4F20\u63A5\u53E3
valueString-\u5F53\u524D\u5934\u50CF\u5730\u5740(v-model)2.5.3
showBtnBooleantrue\u662F\u5426\u663E\u793A\u6309\u94AE2.5.3
btnTextString-\u6309\u94AE\u6587\u68482.5.3
btnPropsButtonProps-\u6309\u94AE\u7684\u5176\u5B83\u5C5E\u60272.5.3

Events

\u540D\u79F0\u53C2\u6570\u8BF4\u660E\u7248\u672C
changevalue: String\u5F53\u5934\u50CF\u4E0A\u4F20\u5B8C\u6210\u65F6\u89E6\u53D12.5.3

Methods

\u540D\u79F0\u5B9A\u4E49\u8BF4\u660E\u7248\u672C
openModal()=>void\u6253\u5F00\u4E0A\u4F20Modal2.5.3
closeModal()=>void\u5173\u95ED\u4E0A\u4F20Modal2.5.3
__VP_STATIC_END__`,20),e=[o];function c(l,r,u,d,i,k){return s(),a("div",null,e)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_desc.md.0b35ac35.js b/assets/components_desc.md.0b35ac35.js new file mode 100644 index 00000000..876edce0 --- /dev/null +++ b/assets/components_desc.md.0b35ac35.js @@ -0,0 +1,66 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Description \u8BE6\u60C5\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"useDescription","slug":"usedescription"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"DescItem","slug":"descitem"}],"relativePath":"components/desc.md","lastUpdated":1694442156381}',p={},o=t(`

Description \u8BE6\u60C5\u7EC4\u4EF6

\u5BF9 antv \u7684 Descriptions \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5

Usage

<template>
+  <div class="p-4">
+    <Description
+      title="\u57FA\u7840\u793A\u4F8B"
+      :collapseOptions="{ canExpand: true, helpMessage: 'help me' }"
+      :column="3"
+      :data="mockData"
+      :schema="schema"
+    />
+    <Description @register="register" class="mt-4" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { Description, DescItem, useDescription } from '/@/components/Description/index';
+  const mockData: any = {
+    username: 'test',
+    nickName: 'VB',
+    age: 123,
+    phone: '15695909xxx',
+    email: '190848757@qq.com',
+    addr: '\u53A6\u95E8\u5E02\u601D\u660E\u533A',
+    sex: '\u7537',
+    certy: '3504256199xxxxxxxxx',
+    tag: 'orange',
+  };
+  const schema: DescItem[] = [
+    {
+      field: 'username',
+      label: '\u7528\u6237\u540D',
+    },
+    {
+      field: 'nickName',
+      label: '\u6635\u79F0',
+      render: (curVal, data) => {
+        return \`\${data.username}-\${curVal}\`;
+      },
+    },
+    {
+      field: 'phone',
+      label: '\u8054\u7CFB\u7535\u8BDD',
+    },
+    {
+      field: 'email',
+      label: '\u90AE\u7BB1',
+    },
+    {
+      field: 'addr',
+      label: '\u5730\u5740',
+    },
+  ];
+  export default defineComponent({
+    components: { Description, Alert },
+    setup() {
+      const [register] = useDescription({
+        title: 'useDescription',
+        data: mockData,
+        schema: schema,
+      });
+      return { mockData, schema, register };
+    },
+  });
+</script>
+

useDescription

\u53C2\u8003\u4EE5\u4E0A\u793A\u4F8B

const [register] = useDescription(Props);
+

Props

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv Description

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
titlestring--\u6807\u9898
sizestringsmall-\u5927\u5C0F
borderedbooleantrue-\u662F\u5426\u5C55\u793A\u8FB9\u6846
columnNumber, Object{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }-\u4E00\u884C\u7684 DescriptionItems \u6570\u91CF
useCollapseboolean--\u662F\u5426\u5305\u88F9 CollapseContainer \u7EC4\u4EF6
collapseOptionsObject--CollapseContainer \u7EC4\u4EF6\u5C5E\u6027
schemaDescItem[]--\u8BE6\u60C5\u9879\u914D\u7F6E\uFF0C\u89C1\u4E0B\u65B9 DescItem \u914D\u7F6E
dataobject--\u6570\u636E\u6E90

DescItem

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
fieldstring--\u5B57\u6BB5\u540D
labelstring--\u6807\u7B7E\u540D
labelMinWidthnumber--label \u6700\u5C0F\u5BBD\u5EA6
contentMinWidthnumber--content \u6700\u5C0F\u5BBD\u5EA6
labelStyleany--label \u6837\u5F0F
spannumber--\u548C\u5E76\u5217\u6570\u91CF
show(data)=>boolean--\u52A8\u6001\u5224\u65AD\u5F53\u524D\u7EC4\u4EF6\u662F\u5426\u663E\u793A
render(val: string, data: any)=>VNode,undefined,Element,string,number--\u81EA\u5B9A\u4E49\u6E32\u67D3 content
`,12),e=[o];function c(l,r,u,i,d,k){return a(),s("div",null,e)}var h=n(p,[["render",c]]);export{m as __pageData,h as default}; diff --git a/assets/components_desc.md.0b35ac35.lean.js b/assets/components_desc.md.0b35ac35.lean.js new file mode 100644 index 00000000..c07ae7f1 --- /dev/null +++ b/assets/components_desc.md.0b35ac35.lean.js @@ -0,0 +1,66 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Description \u8BE6\u60C5\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"useDescription","slug":"usedescription"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"DescItem","slug":"descitem"}],"relativePath":"components/desc.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Description \u8BE6\u60C5\u7EC4\u4EF6

\u5BF9 antv \u7684 Descriptions \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5

Usage

<template>
+  <div class="p-4">
+    <Description
+      title="\u57FA\u7840\u793A\u4F8B"
+      :collapseOptions="{ canExpand: true, helpMessage: 'help me' }"
+      :column="3"
+      :data="mockData"
+      :schema="schema"
+    />
+    <Description @register="register" class="mt-4" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { Description, DescItem, useDescription } from '/@/components/Description/index';
+  const mockData: any = {
+    username: 'test',
+    nickName: 'VB',
+    age: 123,
+    phone: '15695909xxx',
+    email: '190848757@qq.com',
+    addr: '\u53A6\u95E8\u5E02\u601D\u660E\u533A',
+    sex: '\u7537',
+    certy: '3504256199xxxxxxxxx',
+    tag: 'orange',
+  };
+  const schema: DescItem[] = [
+    {
+      field: 'username',
+      label: '\u7528\u6237\u540D',
+    },
+    {
+      field: 'nickName',
+      label: '\u6635\u79F0',
+      render: (curVal, data) => {
+        return \`\${data.username}-\${curVal}\`;
+      },
+    },
+    {
+      field: 'phone',
+      label: '\u8054\u7CFB\u7535\u8BDD',
+    },
+    {
+      field: 'email',
+      label: '\u90AE\u7BB1',
+    },
+    {
+      field: 'addr',
+      label: '\u5730\u5740',
+    },
+  ];
+  export default defineComponent({
+    components: { Description, Alert },
+    setup() {
+      const [register] = useDescription({
+        title: 'useDescription',
+        data: mockData,
+        schema: schema,
+      });
+      return { mockData, schema, register };
+    },
+  });
+</script>
+

useDescription

\u53C2\u8003\u4EE5\u4E0A\u793A\u4F8B

const [register] = useDescription(Props);
+

Props

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv Description

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
titlestring--\u6807\u9898
sizestringsmall-\u5927\u5C0F
borderedbooleantrue-\u662F\u5426\u5C55\u793A\u8FB9\u6846
columnNumber, Object{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }-\u4E00\u884C\u7684 DescriptionItems \u6570\u91CF
useCollapseboolean--\u662F\u5426\u5305\u88F9 CollapseContainer \u7EC4\u4EF6
collapseOptionsObject--CollapseContainer \u7EC4\u4EF6\u5C5E\u6027
schemaDescItem[]--\u8BE6\u60C5\u9879\u914D\u7F6E\uFF0C\u89C1\u4E0B\u65B9 DescItem \u914D\u7F6E
dataobject--\u6570\u636E\u6E90

DescItem

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
fieldstring--\u5B57\u6BB5\u540D
labelstring--\u6807\u7B7E\u540D
labelMinWidthnumber--label \u6700\u5C0F\u5BBD\u5EA6
contentMinWidthnumber--content \u6700\u5C0F\u5BBD\u5EA6
labelStyleany--label \u6837\u5F0F
spannumber--\u548C\u5E76\u5217\u6570\u91CF
show(data)=>boolean--\u52A8\u6001\u5224\u65AD\u5F53\u524D\u7EC4\u4EF6\u662F\u5426\u663E\u793A
render(val: string, data: any)=>VNode,undefined,Element,string,number--\u81EA\u5B9A\u4E49\u6E32\u67D3 content
__VP_STATIC_END__`,12),e=[o];function c(l,r,u,i,d,k){return a(),s("div",null,e)}var h=n(p,[["render",c]]);export{m as __pageData,h as default}; diff --git a/assets/components_drawer.md.cdd81599.js b/assets/components_drawer.md.cdd81599.js new file mode 100644 index 00000000..e0fcf067 --- /dev/null +++ b/assets/components_drawer.md.cdd81599.js @@ -0,0 +1,66 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const w='{"title":"Drawer \u62BD\u5C49\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"useDrawer","slug":"usedrawer"},{"level":2,"title":"useDrawerInner","slug":"usedrawerinner"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"}],"relativePath":"components/drawer.md","lastUpdated":1694442156381}',p={},o=t(`

Drawer \u62BD\u5C49\u7EC4\u4EF6

\u5BF9 antv \u7684 drawer \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5\uFF0C\u6269\u5C55\u62D6\u62FD\uFF0C\u5168\u5C4F\uFF0C\u81EA\u9002\u5E94\u9AD8\u5EA6\u7B49\u529F\u80FD\u3002

Usage

\u7531\u4E8E drawer \u5185\u90E8\u4EE3\u7801\u4E00\u822C\u72EC\u7ACB\u6210\u5355\u72EC\u6587\u4EF6\uFF0C\u63A8\u8350\u72EC\u7ACB\u6210\u7EC4\u4EF6\u6765\u8FDB\u884C\u5F00\u53D1\uFF0C\u6240\u4EE5\u793A\u4F8B\u90FD\u662F\u4EE5\u72EC\u7ACB\u7684\u6587\u4EF6\u6765\u8FDB\u884C\u8BF4\u660E

\u72EC\u7ACB\u7EC4\u4EF6\u4EE3\u7801\uFF0C\u7528\u4E8E\u5199\u7EC4\u4EF6\u5185\u90E8\u7684\u5185\u5BB9

<template>
+  <BasicDrawer v-bind="$attrs" title="Drawer Title" width="50%"> Drawer Info. </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicDrawer } from '/@/components/Drawer';
+  export default defineComponent({
+    components: { BasicDrawer },
+  });
+</script>
+

\u9875\u9762\u5F15\u7528\u5F39\u7A97

<template>
+  <div>
+    <Drawer @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { useDrawer } from '/@/components/Drawer';
+  import Drawer from './Drawer.vue';
+
+  export default defineComponent({
+    components: { Drawer },
+    setup() {
+      const [register, { openDrawer }] = useDrawer();
+      return {
+        register,
+        openDrawer,
+      };
+    },
+  });
+</script>
+

useDrawer

useDrawer \u7528\u4E8E\u64CD\u4F5C\u7EC4\u4EF6

const [register, { openDrawer, setDrawerProps }] = useDrawer();
+

register

register \u7528\u4E8E\u6CE8\u518C useDrawer\uFF0C\u5982\u679C\u9700\u8981\u4F7F\u7528 useDrawer \u63D0\u4F9B\u7684 api\uFF0C\u5FC5\u987B\u5C06 register \u4F20\u5165\u7EC4\u4EF6\u7684 onRegister\u3002

\u539F\u7406\u5176\u5B9E\u5F88\u7B80\u5355\uFF0C\u5C31\u662F vue \u7684\u7EC4\u4EF6\u5B50\u4F20\u7236\u901A\u4FE1\uFF0C\u5185\u90E8\u901A\u8FC7 emit("register"\uFF0Cinstance) \u5B9E\u73B0\u3002

\u540C\u65F6\uFF0C\u72EC\u7ACB\u51FA\u53BB\u7684\u7EC4\u4EF6\u9700\u8981\u5C06 attrs \u7ED1\u5B9A\u5230 Drawer \u7684\u4E0A\u9762\u3002

<BasicDrawer v-bind="$attrs"> Drawer Info. </BasicDrawer>
+

openDrawer

\u7528\u4E8E\u6253\u5F00/\u5173\u95ED\u5F39\u7A97

// true/false: \u6253\u5F00\u5173\u95ED\u5F39\u7A97
+// data: \u4F20\u9012\u5230\u5B50\u7EC4\u4EF6\u7684\u6570\u636E
+openDrawer(true, data);
+

closeDrawer

\u7528\u4E8E\u5173\u95ED\u5F39\u7A97

closeDrawer();
+

setDrawerProps

\u7528\u4E8E\u66F4\u6539 drawer \u7684 props \u53C2\u6570\u56E0\u4E3A drawer \u5185\u5BB9\u72EC\u7ACB\u6210\u7EC4\u4EF6\uFF0C\u5982\u679C\u5728\u5916\u90E8\u9875\u9762\u9700\u8981\u66F4\u6539 props \u53EF\u80FD\u6BD4\u8F83\u9EBB\u70E6\uFF0C\u6240\u4EE5\u63D0\u4F9B setDrawerProps \u65B9\u4FBF\u66F4\u6539\u5185\u90E8 drawer \u7684 props

Props \u5185\u5BB9\u53EF\u4EE5\u89C1\u4E0B\u65B9

setDrawerProps(props);
+

useDrawerInner

\u7528\u4E8E\u72EC\u7ACB\u7684 Drawer \u5185\u90E8\u8C03\u7528

<template>
+  <BasicDrawer v-bind="$attrs" @register="register" title="Drawer Title" width="50%">
+    Drawer Info.
+    <a-button type="primary" @click="closeDrawer">\u5185\u90E8\u5173\u95EDdrawer</a-button>
+  </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
+  export default defineComponent({
+    components: { BasicDrawer },
+    setup() {
+      const [register, { closeDrawer }] = useDrawerInner();
+      return { register, closeDrawer };
+    },
+  });
+</script>
+

useModalInner\u7528\u4E8E\u64CD\u4F5C\u72EC\u7ACB\u7EC4\u4EF6

const [register, { closeModal, setModalProps }] = useModalInner(callback);
+

callback

type: (data:any)=>void

\u56DE\u8C03\u51FD\u6570\u7528\u4E8E\u63A5\u6536 openDrawer \u7B2C\u4E8C\u4E2A\u53C2\u6570\u4F20\u9012\u7684\u503C

openDrawer((data: any) => {
+  console.log(data);
+});
+

closeDrawer

\u7528\u4E8E\u5173\u95ED\u62BD\u5C49

closeDrawer();
+

changeOkLoading

\u7528\u4E8E\u4FEE\u6539\u786E\u8BA4\u6309\u94AE\u7684 loading \u72B6\u6001

// true or false
+changeOkLoading(true);
+

changeLoading

\u7528\u4E8E\u4FEE\u6539 modal \u7684 loading \u72B6\u6001

// true or false
+changeLoading(true);
+

setDrawerProps

\u7528\u4E8E\u66F4\u6539 drawer \u7684 props \u53C2\u6570\u56E0\u4E3A modal \u5185\u5BB9\u72EC\u7ACB\u6210\u7EC4\u4EF6\uFF0C\u5982\u679C\u5728\u5916\u90E8\u9875\u9762\u9700\u8981\u66F4\u6539 props \u53EF\u80FD\u6BD4\u8F83\u9EBB\u70E6\uFF0C\u6240\u4EE5\u63D0\u4F9BsetDrawerProps \u65B9\u4FBF\u66F4\u6539\u5185\u90E8 drawer \u7684 props

Props \u5185\u5BB9\u53EF\u4EE5\u89C1\u4E0B\u65B9

Props

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv drawer

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
isDetailbooleanfalse-\u662F\u5426\u4E3A\u8BE6\u60C5\u6A21\u5F0F
loadingbooleanfalse-loading \u72B6\u6001
loadingTextstring\`\`-loading \u6587\u672C s
showDetailBackbooleantrue-isDetail=true \u72B6\u6001\u4E0B\u662F\u5426\u663E\u793A\u8FD4\u56DE\u6309\u94AE
closeFunc() => Promise<boolean>--\u81EA\u5B9A\u4E49\u5173\u95ED\u51FD\u6570\uFF0C\u8FD4\u56DEtrue\u5173\u95ED\uFF0C\u5426\u5219\u4E0D\u5173\u95ED
showFooterboolean--\u662F\u5426\u663E\u793A\u5E95\u90E8
footerHeightnumber60-\u5E95\u90E8\u533A\u57DF\u9AD8\u5EA6

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
close(e)=>void\u70B9\u51FB\u5173\u95ED\u56DE\u8C03
visible-change(visible:boolean)=>void\u5F39\u7A97\u6253\u5F00\u5173\u95ED\u65F6\u89E6\u53D1
ok(e)=>void\u70B9\u51FB\u786E\u5B9A\u56DE\u8C03
`,52),e=[o];function c(u,l,r,k,i,d){return s(),a("div",null,e)}var v=n(p,[["render",c]]);export{w as __pageData,v as default}; diff --git a/assets/components_drawer.md.cdd81599.lean.js b/assets/components_drawer.md.cdd81599.lean.js new file mode 100644 index 00000000..86c02e16 --- /dev/null +++ b/assets/components_drawer.md.cdd81599.lean.js @@ -0,0 +1,66 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const w='{"title":"Drawer \u62BD\u5C49\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"useDrawer","slug":"usedrawer"},{"level":2,"title":"useDrawerInner","slug":"usedrawerinner"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"}],"relativePath":"components/drawer.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Drawer \u62BD\u5C49\u7EC4\u4EF6

\u5BF9 antv \u7684 drawer \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5\uFF0C\u6269\u5C55\u62D6\u62FD\uFF0C\u5168\u5C4F\uFF0C\u81EA\u9002\u5E94\u9AD8\u5EA6\u7B49\u529F\u80FD\u3002

Usage

\u7531\u4E8E drawer \u5185\u90E8\u4EE3\u7801\u4E00\u822C\u72EC\u7ACB\u6210\u5355\u72EC\u6587\u4EF6\uFF0C\u63A8\u8350\u72EC\u7ACB\u6210\u7EC4\u4EF6\u6765\u8FDB\u884C\u5F00\u53D1\uFF0C\u6240\u4EE5\u793A\u4F8B\u90FD\u662F\u4EE5\u72EC\u7ACB\u7684\u6587\u4EF6\u6765\u8FDB\u884C\u8BF4\u660E

\u72EC\u7ACB\u7EC4\u4EF6\u4EE3\u7801\uFF0C\u7528\u4E8E\u5199\u7EC4\u4EF6\u5185\u90E8\u7684\u5185\u5BB9

<template>
+  <BasicDrawer v-bind="$attrs" title="Drawer Title" width="50%"> Drawer Info. </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicDrawer } from '/@/components/Drawer';
+  export default defineComponent({
+    components: { BasicDrawer },
+  });
+</script>
+

\u9875\u9762\u5F15\u7528\u5F39\u7A97

<template>
+  <div>
+    <Drawer @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { useDrawer } from '/@/components/Drawer';
+  import Drawer from './Drawer.vue';
+
+  export default defineComponent({
+    components: { Drawer },
+    setup() {
+      const [register, { openDrawer }] = useDrawer();
+      return {
+        register,
+        openDrawer,
+      };
+    },
+  });
+</script>
+

useDrawer

useDrawer \u7528\u4E8E\u64CD\u4F5C\u7EC4\u4EF6

const [register, { openDrawer, setDrawerProps }] = useDrawer();
+

register

register \u7528\u4E8E\u6CE8\u518C useDrawer\uFF0C\u5982\u679C\u9700\u8981\u4F7F\u7528 useDrawer \u63D0\u4F9B\u7684 api\uFF0C\u5FC5\u987B\u5C06 register \u4F20\u5165\u7EC4\u4EF6\u7684 onRegister\u3002

\u539F\u7406\u5176\u5B9E\u5F88\u7B80\u5355\uFF0C\u5C31\u662F vue \u7684\u7EC4\u4EF6\u5B50\u4F20\u7236\u901A\u4FE1\uFF0C\u5185\u90E8\u901A\u8FC7 emit("register"\uFF0Cinstance) \u5B9E\u73B0\u3002

\u540C\u65F6\uFF0C\u72EC\u7ACB\u51FA\u53BB\u7684\u7EC4\u4EF6\u9700\u8981\u5C06 attrs \u7ED1\u5B9A\u5230 Drawer \u7684\u4E0A\u9762\u3002

<BasicDrawer v-bind="$attrs"> Drawer Info. </BasicDrawer>
+

openDrawer

\u7528\u4E8E\u6253\u5F00/\u5173\u95ED\u5F39\u7A97

// true/false: \u6253\u5F00\u5173\u95ED\u5F39\u7A97
+// data: \u4F20\u9012\u5230\u5B50\u7EC4\u4EF6\u7684\u6570\u636E
+openDrawer(true, data);
+

closeDrawer

\u7528\u4E8E\u5173\u95ED\u5F39\u7A97

closeDrawer();
+

setDrawerProps

\u7528\u4E8E\u66F4\u6539 drawer \u7684 props \u53C2\u6570\u56E0\u4E3A drawer \u5185\u5BB9\u72EC\u7ACB\u6210\u7EC4\u4EF6\uFF0C\u5982\u679C\u5728\u5916\u90E8\u9875\u9762\u9700\u8981\u66F4\u6539 props \u53EF\u80FD\u6BD4\u8F83\u9EBB\u70E6\uFF0C\u6240\u4EE5\u63D0\u4F9B setDrawerProps \u65B9\u4FBF\u66F4\u6539\u5185\u90E8 drawer \u7684 props

Props \u5185\u5BB9\u53EF\u4EE5\u89C1\u4E0B\u65B9

setDrawerProps(props);
+

useDrawerInner

\u7528\u4E8E\u72EC\u7ACB\u7684 Drawer \u5185\u90E8\u8C03\u7528

<template>
+  <BasicDrawer v-bind="$attrs" @register="register" title="Drawer Title" width="50%">
+    Drawer Info.
+    <a-button type="primary" @click="closeDrawer">\u5185\u90E8\u5173\u95EDdrawer</a-button>
+  </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
+  export default defineComponent({
+    components: { BasicDrawer },
+    setup() {
+      const [register, { closeDrawer }] = useDrawerInner();
+      return { register, closeDrawer };
+    },
+  });
+</script>
+

useModalInner\u7528\u4E8E\u64CD\u4F5C\u72EC\u7ACB\u7EC4\u4EF6

const [register, { closeModal, setModalProps }] = useModalInner(callback);
+

callback

type: (data:any)=>void

\u56DE\u8C03\u51FD\u6570\u7528\u4E8E\u63A5\u6536 openDrawer \u7B2C\u4E8C\u4E2A\u53C2\u6570\u4F20\u9012\u7684\u503C

openDrawer((data: any) => {
+  console.log(data);
+});
+

closeDrawer

\u7528\u4E8E\u5173\u95ED\u62BD\u5C49

closeDrawer();
+

changeOkLoading

\u7528\u4E8E\u4FEE\u6539\u786E\u8BA4\u6309\u94AE\u7684 loading \u72B6\u6001

// true or false
+changeOkLoading(true);
+

changeLoading

\u7528\u4E8E\u4FEE\u6539 modal \u7684 loading \u72B6\u6001

// true or false
+changeLoading(true);
+

setDrawerProps

\u7528\u4E8E\u66F4\u6539 drawer \u7684 props \u53C2\u6570\u56E0\u4E3A modal \u5185\u5BB9\u72EC\u7ACB\u6210\u7EC4\u4EF6\uFF0C\u5982\u679C\u5728\u5916\u90E8\u9875\u9762\u9700\u8981\u66F4\u6539 props \u53EF\u80FD\u6BD4\u8F83\u9EBB\u70E6\uFF0C\u6240\u4EE5\u63D0\u4F9BsetDrawerProps \u65B9\u4FBF\u66F4\u6539\u5185\u90E8 drawer \u7684 props

Props \u5185\u5BB9\u53EF\u4EE5\u89C1\u4E0B\u65B9

Props

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv drawer

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
isDetailbooleanfalse-\u662F\u5426\u4E3A\u8BE6\u60C5\u6A21\u5F0F
loadingbooleanfalse-loading \u72B6\u6001
loadingTextstring\`\`-loading \u6587\u672C s
showDetailBackbooleantrue-isDetail=true \u72B6\u6001\u4E0B\u662F\u5426\u663E\u793A\u8FD4\u56DE\u6309\u94AE
closeFunc() => Promise<boolean>--\u81EA\u5B9A\u4E49\u5173\u95ED\u51FD\u6570\uFF0C\u8FD4\u56DEtrue\u5173\u95ED\uFF0C\u5426\u5219\u4E0D\u5173\u95ED
showFooterboolean--\u662F\u5426\u663E\u793A\u5E95\u90E8
footerHeightnumber60-\u5E95\u90E8\u533A\u57DF\u9AD8\u5EA6

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
close(e)=>void\u70B9\u51FB\u5173\u95ED\u56DE\u8C03
visible-change(visible:boolean)=>void\u5F39\u7A97\u6253\u5F00\u5173\u95ED\u65F6\u89E6\u53D1
ok(e)=>void\u70B9\u51FB\u786E\u5B9A\u56DE\u8C03
__VP_STATIC_END__`,52),e=[o];function c(u,l,r,k,i,d){return s(),a("div",null,e)}var v=n(p,[["render",c]]);export{w as __pageData,v as default}; diff --git a/assets/components_excel.md.967fd223.js b/assets/components_excel.md.967fd223.js new file mode 100644 index 00000000..de0f96e7 --- /dev/null +++ b/assets/components_excel.md.967fd223.js @@ -0,0 +1,76 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Excel \u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Import","slug":"import"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Events","slug":"events"},{"level":3,"title":"ExcelData","slug":"exceldata"},{"level":2,"title":"Export","slug":"export"},{"level":3,"title":"\u6570\u7EC4\u683C\u5F0F\u6570\u636E\u5BFC\u51FA","slug":"\u6570\u7EC4\u683C\u5F0F\u6570\u636E\u5BFC\u51FA"},{"level":3,"title":"\u81EA\u5B9A\u4E49\u5BFC\u51FA\u683C\u5F0F","slug":"\u81EA\u5B9A\u4E49\u5BFC\u51FA\u683C\u5F0F"},{"level":3,"title":"json \u683C\u5F0F\u5BFC\u51FA","slug":"json-\u683C\u5F0F\u5BFC\u51FA"},{"level":2,"title":"Function","slug":"function"},{"level":3,"title":"JsonToSheet Type","slug":"jsontosheet-type"},{"level":3,"title":"AoAToSheet Type","slug":"aoatosheet-type"}],"relativePath":"components/excel.md","lastUpdated":1694442156381}',p={},e=t(`

Excel \u7EC4\u4EF6

excel \u5BFC\u5165\u5BFC\u51FA\u64CD\u4F5C

\u9879\u76EE\u4E2D\u4F7F\u7528\u5230\u7684\u662F XLSX\uFF0C\u5177\u4F53\u6587\u6863\u53EF\u4EE5\u53C2\u8003XLSX \u6587\u6863

Import

Usage

<template>
+  <ImpExcel @success="loadDataSuccess">
+    <a-button class="m-3">\u5BFC\u5165Excel</a-button>
+  </ImpExcel>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { ImpExcel, ExcelData } from '/@/components/Excel';
+  export default defineComponent({
+    components: { ImpExcel },
+    setup() {
+      function loadDataSuccess(excelDataList: ExcelData[]) {
+        tableListRef.value = [];
+        console.log(excelDataList);
+        for (const excelData of excelDataList) {
+          const {
+            header,
+            results,
+            meta: { sheetName },
+          } = excelData;
+          const columns: BasicColumn[] = [];
+          for (const title of header) {
+            columns.push({ title, dataIndex: title });
+          }
+          tableListRef.value.push({ title: sheetName, dataSource: results, columns });
+        }
+      }
+      return {
+        loadDataSuccess,
+      };
+    },
+  });
+</script>
+

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
success(res:ExcelData)=>void\u5BFC\u5165\u6210\u529F\u56DE\u8C03
error()=>void\u5BFC\u51FA\u9519\u8BEF

ExcelData

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
header:string[];table \u8868\u5934
results:T[];table \u6570\u636E
meta:{ sheetName: string };table title

Export

\u5177\u4F53\u8BE6\u60C5\u53EF\u4EE5\u53C2\u8003\u5B8C\u6574\u7248\u793A\u4F8B

import { jsonToSheetXlsx, aoaToSheetXlsx } from '/@/components/Excel';
+

\u6570\u7EC4\u683C\u5F0F\u6570\u636E\u5BFC\u51FA

import { aoaToSheetXlsx } from '/@/components/Excel';
+// \u4FDD\u8BC1data\u987A\u5E8F\u4E0Eheader\u4E00\u81F4
+aoaToSheetXlsx({
+  data: [],
+  header: [],
+  filename: '\u4E8C\u7EF4\u6570\u7EC4\u65B9\u5F0F\u5BFC\u51FAexcel.xlsx',
+});
+

\u81EA\u5B9A\u4E49\u5BFC\u51FA\u683C\u5F0F

import { jsonToSheetXlsx } from '/@/components/Excel';
+
+jsonToSheetXlsx({
+  data,
+  filename,
+  write2excelOpts: {
+    // \u53EF\u4EE5\u662F xlsx/html/csv/txt
+    bookType,
+  },
+});
+

json \u683C\u5F0F\u5BFC\u51FA

import { jsonToSheetXlsx } from '/@/components/Excel';
+
+jsonToSheetXlsx({
+  data,
+  filename: '\u4F7F\u7528key\u4F5C\u4E3A\u9ED8\u8BA4\u5934\u90E8.xlsx',
+});
+
+jsonToSheetXlsx({
+  data,
+  header: {
+    id: 'ID',
+    name: '\u59D3\u540D',
+    age: '\u5E74\u9F84',
+    no: '\u7F16\u53F7',
+    address: '\u5730\u5740',
+    beginTime: '\u5F00\u59CB\u65F6\u95F4',
+    endTime: '\u7ED3\u675F\u65F6\u95F4',
+  },
+  filename: '\u81EA\u5B9A\u4E49\u5934\u90E8.xlsx',
+  json2sheetOpts: {
+    // \u6307\u5B9A\u987A\u5E8F
+    header: ['name', 'id'],
+  },
+});
+

Function

\u65B9\u6CD5\u56DE\u8C03\u53C2\u6570\u8FD4\u56DE\u503C\u8BF4\u660E
jsonToSheetXlsxFunction(JsonToSheet)json \u683C\u5F0F\u6570\u636E\uFF0C\u5BFC\u51FA\u5230 excel
aoaToSheetXlsxFunction(AoAToSheet)\u6570\u7EC4\u683C\u5F0F\uFF0C\u5BFC\u51FA\u5230 excel

JsonToSheet Type

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
dataT[]JSON \u5BF9\u8C61\u6570\u7EC4
header?:T;\u8868\u5934\u672A\u8BBE\u7F6E\u5219\u53D6 JSON \u5BF9\u8C61\u7684 key \u4F5C\u4E3A header
filename?:stringexcel-list.xlsx\u5BFC\u51FA\u7684\u6587\u4EF6\u540D
json2sheetOpts?:JSON2SheetOpts\u8C03\u7528 XLSX.utils.json_to_sheet \u7684\u53EF\u9009\u53C2\u6570
write2excelOpts?:WritingOptions{ bookType: 'xlsx' }\u8C03\u7528 XLSX.writeFile \u7684\u53EF\u9009\u53C2\u6570\uFF0C\u5177\u4F53\u53C2 XLSX \u6587\u6863

AoAToSheet Type

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
dataT[][];\u4E8C\u7EF4\u6570\u7EC4
header?:T;\u8868\u5934 \uFF1B\u672A\u8BBE\u7F6E\u5219\u6CA1\u6709\u8868\u5934
filename?:string;excel-list.xlsx\u5BFC\u51FA\u7684\u6587\u4EF6\u540D
write2excelOpts?:WritingOptions;{ bookType: 'xlsx' }\u8C03\u7528 XLSX.writeFile \u7684\u53EF\u9009\u53C2\u6570
`,25),o=[e];function c(l,u,r,i,d,k){return a(),s("div",null,o)}var x=n(p,[["render",c]]);export{g as __pageData,x as default}; diff --git a/assets/components_excel.md.967fd223.lean.js b/assets/components_excel.md.967fd223.lean.js new file mode 100644 index 00000000..d2ec3c0d --- /dev/null +++ b/assets/components_excel.md.967fd223.lean.js @@ -0,0 +1,76 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Excel \u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Import","slug":"import"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Events","slug":"events"},{"level":3,"title":"ExcelData","slug":"exceldata"},{"level":2,"title":"Export","slug":"export"},{"level":3,"title":"\u6570\u7EC4\u683C\u5F0F\u6570\u636E\u5BFC\u51FA","slug":"\u6570\u7EC4\u683C\u5F0F\u6570\u636E\u5BFC\u51FA"},{"level":3,"title":"\u81EA\u5B9A\u4E49\u5BFC\u51FA\u683C\u5F0F","slug":"\u81EA\u5B9A\u4E49\u5BFC\u51FA\u683C\u5F0F"},{"level":3,"title":"json \u683C\u5F0F\u5BFC\u51FA","slug":"json-\u683C\u5F0F\u5BFC\u51FA"},{"level":2,"title":"Function","slug":"function"},{"level":3,"title":"JsonToSheet Type","slug":"jsontosheet-type"},{"level":3,"title":"AoAToSheet Type","slug":"aoatosheet-type"}],"relativePath":"components/excel.md","lastUpdated":1694442156381}',p={},e=t(`__VP_STATIC_START__

Excel \u7EC4\u4EF6

excel \u5BFC\u5165\u5BFC\u51FA\u64CD\u4F5C

\u9879\u76EE\u4E2D\u4F7F\u7528\u5230\u7684\u662F XLSX\uFF0C\u5177\u4F53\u6587\u6863\u53EF\u4EE5\u53C2\u8003XLSX \u6587\u6863

Import

Usage

<template>
+  <ImpExcel @success="loadDataSuccess">
+    <a-button class="m-3">\u5BFC\u5165Excel</a-button>
+  </ImpExcel>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { ImpExcel, ExcelData } from '/@/components/Excel';
+  export default defineComponent({
+    components: { ImpExcel },
+    setup() {
+      function loadDataSuccess(excelDataList: ExcelData[]) {
+        tableListRef.value = [];
+        console.log(excelDataList);
+        for (const excelData of excelDataList) {
+          const {
+            header,
+            results,
+            meta: { sheetName },
+          } = excelData;
+          const columns: BasicColumn[] = [];
+          for (const title of header) {
+            columns.push({ title, dataIndex: title });
+          }
+          tableListRef.value.push({ title: sheetName, dataSource: results, columns });
+        }
+      }
+      return {
+        loadDataSuccess,
+      };
+    },
+  });
+</script>
+

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
success(res:ExcelData)=>void\u5BFC\u5165\u6210\u529F\u56DE\u8C03
error()=>void\u5BFC\u51FA\u9519\u8BEF

ExcelData

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
header:string[];table \u8868\u5934
results:T[];table \u6570\u636E
meta:{ sheetName: string };table title

Export

\u5177\u4F53\u8BE6\u60C5\u53EF\u4EE5\u53C2\u8003\u5B8C\u6574\u7248\u793A\u4F8B

import { jsonToSheetXlsx, aoaToSheetXlsx } from '/@/components/Excel';
+

\u6570\u7EC4\u683C\u5F0F\u6570\u636E\u5BFC\u51FA

import { aoaToSheetXlsx } from '/@/components/Excel';
+// \u4FDD\u8BC1data\u987A\u5E8F\u4E0Eheader\u4E00\u81F4
+aoaToSheetXlsx({
+  data: [],
+  header: [],
+  filename: '\u4E8C\u7EF4\u6570\u7EC4\u65B9\u5F0F\u5BFC\u51FAexcel.xlsx',
+});
+

\u81EA\u5B9A\u4E49\u5BFC\u51FA\u683C\u5F0F

import { jsonToSheetXlsx } from '/@/components/Excel';
+
+jsonToSheetXlsx({
+  data,
+  filename,
+  write2excelOpts: {
+    // \u53EF\u4EE5\u662F xlsx/html/csv/txt
+    bookType,
+  },
+});
+

json \u683C\u5F0F\u5BFC\u51FA

import { jsonToSheetXlsx } from '/@/components/Excel';
+
+jsonToSheetXlsx({
+  data,
+  filename: '\u4F7F\u7528key\u4F5C\u4E3A\u9ED8\u8BA4\u5934\u90E8.xlsx',
+});
+
+jsonToSheetXlsx({
+  data,
+  header: {
+    id: 'ID',
+    name: '\u59D3\u540D',
+    age: '\u5E74\u9F84',
+    no: '\u7F16\u53F7',
+    address: '\u5730\u5740',
+    beginTime: '\u5F00\u59CB\u65F6\u95F4',
+    endTime: '\u7ED3\u675F\u65F6\u95F4',
+  },
+  filename: '\u81EA\u5B9A\u4E49\u5934\u90E8.xlsx',
+  json2sheetOpts: {
+    // \u6307\u5B9A\u987A\u5E8F
+    header: ['name', 'id'],
+  },
+});
+

Function

\u65B9\u6CD5\u56DE\u8C03\u53C2\u6570\u8FD4\u56DE\u503C\u8BF4\u660E
jsonToSheetXlsxFunction(JsonToSheet)json \u683C\u5F0F\u6570\u636E\uFF0C\u5BFC\u51FA\u5230 excel
aoaToSheetXlsxFunction(AoAToSheet)\u6570\u7EC4\u683C\u5F0F\uFF0C\u5BFC\u51FA\u5230 excel

JsonToSheet Type

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
dataT[]JSON \u5BF9\u8C61\u6570\u7EC4
header?:T;\u8868\u5934\u672A\u8BBE\u7F6E\u5219\u53D6 JSON \u5BF9\u8C61\u7684 key \u4F5C\u4E3A header
filename?:stringexcel-list.xlsx\u5BFC\u51FA\u7684\u6587\u4EF6\u540D
json2sheetOpts?:JSON2SheetOpts\u8C03\u7528 XLSX.utils.json_to_sheet \u7684\u53EF\u9009\u53C2\u6570
write2excelOpts?:WritingOptions{ bookType: 'xlsx' }\u8C03\u7528 XLSX.writeFile \u7684\u53EF\u9009\u53C2\u6570\uFF0C\u5177\u4F53\u53C2 XLSX \u6587\u6863

AoAToSheet Type

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
dataT[][];\u4E8C\u7EF4\u6570\u7EC4
header?:T;\u8868\u5934 \uFF1B\u672A\u8BBE\u7F6E\u5219\u6CA1\u6709\u8868\u5934
filename?:string;excel-list.xlsx\u5BFC\u51FA\u7684\u6587\u4EF6\u540D
write2excelOpts?:WritingOptions;{ bookType: 'xlsx' }\u8C03\u7528 XLSX.writeFile \u7684\u53EF\u9009\u53C2\u6570
__VP_STATIC_END__`,25),o=[e];function c(l,u,r,i,d,k){return a(),s("div",null,o)}var x=n(p,[["render",c]]);export{g as __pageData,x as default}; diff --git a/assets/components_flow-chart.md.af35503d.js b/assets/components_flow-chart.md.af35503d.js new file mode 100644 index 00000000..e8d5f6a7 --- /dev/null +++ b/assets/components_flow-chart.md.af35503d.js @@ -0,0 +1,17 @@ +import{_ as a,f as n,e as t,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"FlowChart","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/flow-chart.md","lastUpdated":1694442156381}',p={},o=s(`

FlowChart

\u6D41\u7A0B\u56FE\u7EC4\u4EF6\uFF0C\u57FA\u4E8E didi/LogicFlow \u7684\u7B80\u5355\u5C01\u88C5\u3002\u8BE6\u7EC6\u914D\u7F6E\u8BF7\u53C2\u8003\u6587\u6863 FlowChart

Usage

<template>
+  <FlowChart :data="demoData" />
+</template>
+
+<script lang="ts">
+  import { FlowChart } from '/@/components/FlowChart';
+  import { PageWrapper } from '/@/components/Page';
+
+  import demoData from './dataTurbo.json';
+  export default {
+    components: { FlowChart, PageWrapper },
+    setup() {
+      return { demoData };
+    },
+  };
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
flowOptionsobject--FlowCharts \u914D\u7F6E\u9879
dataobject--\u6D41\u7A0B\u6570\u636E
toolbarbooleantrue-\u662F\u5426\u663E\u793A\u5DE5\u5177\u680F
patternItems[]--\u5DE6\u4FA7\u62D6\u62FD\u5217\u8868\u6570\u636E
`,6),e=[o];function c(l,r,u,d,i,k){return t(),n("div",null,e)}var _=a(p,[["render",c]]);export{g as __pageData,_ as default}; diff --git a/assets/components_flow-chart.md.af35503d.lean.js b/assets/components_flow-chart.md.af35503d.lean.js new file mode 100644 index 00000000..05d09d86 --- /dev/null +++ b/assets/components_flow-chart.md.af35503d.lean.js @@ -0,0 +1,17 @@ +import{_ as a,f as n,e as t,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"FlowChart","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/flow-chart.md","lastUpdated":1694442156381}',p={},o=s(`__VP_STATIC_START__

FlowChart

\u6D41\u7A0B\u56FE\u7EC4\u4EF6\uFF0C\u57FA\u4E8E didi/LogicFlow \u7684\u7B80\u5355\u5C01\u88C5\u3002\u8BE6\u7EC6\u914D\u7F6E\u8BF7\u53C2\u8003\u6587\u6863 FlowChart

Usage

<template>
+  <FlowChart :data="demoData" />
+</template>
+
+<script lang="ts">
+  import { FlowChart } from '/@/components/FlowChart';
+  import { PageWrapper } from '/@/components/Page';
+
+  import demoData from './dataTurbo.json';
+  export default {
+    components: { FlowChart, PageWrapper },
+    setup() {
+      return { demoData };
+    },
+  };
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
flowOptionsobject--FlowCharts \u914D\u7F6E\u9879
dataobject--\u6D41\u7A0B\u6570\u636E
toolbarbooleantrue-\u662F\u5426\u663E\u793A\u5DE5\u5177\u680F
patternItems[]--\u5DE6\u4FA7\u62D6\u62FD\u5217\u8868\u6570\u636E
__VP_STATIC_END__`,6),e=[o];function c(l,r,u,d,i,k){return t(),n("div",null,e)}var _=a(p,[["render",c]]);export{g as __pageData,_ as default}; diff --git a/assets/components_form.md.8ee9e1a7.js b/assets/components_form.md.8ee9e1a7.js new file mode 100644 index 00000000..d05732d8 --- /dev/null +++ b/assets/components_form.md.8ee9e1a7.js @@ -0,0 +1,433 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Form \u8868\u5355\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":3,"title":"useForm \u65B9\u5F0F","slug":"useform-\u65B9\u5F0F"},{"level":3,"title":"template \u65B9\u5F0F","slug":"template-\u65B9\u5F0F"},{"level":2,"title":"useForm","slug":"useform"},{"level":3,"title":"\u793A\u4F8B","slug":"\u793A\u4F8B"},{"level":3,"title":"\u53C2\u6570\u4ECB\u7ECD","slug":"\u53C2\u6570\u4ECB\u7ECD"},{"level":3,"title":"Methods","slug":"methods"},{"level":2,"title":"Props","slug":"props"},{"level":3,"title":"ColEx","slug":"colex"},{"level":3,"title":"ActionButtonOption","slug":"actionbuttonoption"},{"level":3,"title":"fieldMapToTime","slug":"fieldmaptotime"},{"level":3,"title":"FormSchema","slug":"formschema"},{"level":3,"title":"Divider schema \u8BF4\u660E","slug":"divider-schema-\u8BF4\u660E"},{"level":2,"title":"\u81EA\u884C\u6DFB\u52A0\u9700\u8981\u7684\u7EC4\u4EF6\u7C7B\u578B","slug":"\u81EA\u884C\u6DFB\u52A0\u9700\u8981\u7684\u7EC4\u4EF6\u7C7B\u578B"},{"level":3,"title":"\u65B9\u5F0F 1","slug":"\u65B9\u5F0F-1"},{"level":3,"title":"\u65B9\u5F0F 2","slug":"\u65B9\u5F0F-2"},{"level":3,"title":"render","slug":"render"},{"level":3,"title":"slot","slug":"slot"},{"level":3,"title":"ifShow/show/dynamicDisabled","slug":"ifshow-show-dynamicdisabled"},{"level":2,"title":"Slots","slug":"slots"},{"level":2,"title":"ApiSelect","slug":"apiselect"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"},{"level":2,"title":"ApiTreeSelect","slug":"apitreeselect"},{"level":3,"title":"Props","slug":"props-2"},{"level":2,"title":"RadioButtonGroup","slug":"radiobuttongroup"},{"level":3,"title":"Usage","slug":"usage-2"},{"level":3,"title":"Props","slug":"props-3"}],"relativePath":"components/form.md","lastUpdated":1694442156381}',p={},o=t(`

Form \u8868\u5355\u7EC4\u4EF6

\u5BF9 antv \u7684 form \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5\uFF0C\u6269\u5C55\u4E00\u4E9B\u5E38\u7528\u7684\u529F\u80FD

\u5982\u679C\u6587\u6863\u5185\u6CA1\u6709\uFF0C\u53EF\u4EE5\u5C1D\u8BD5\u5728\u5728\u7EBF\u793A\u4F8B\u5185\u5BFB\u627E

Usage

useForm \u65B9\u5F0F

\u4E0B\u9762\u662F\u4E00\u4E2A\u4F7F\u7528\u7B80\u5355\u8868\u5355\u7684\u793A\u4F8B\uFF0C\u53EA\u6709\u4E00\u4E2A\u8F93\u5165\u6846

<template>
+  <div class="m-4">
+    <BasicForm
+      :labelWidth="100"
+      :schemas="schemas"
+      :actionColOptions="{ span: 24 }"
+      @submit="handleSubmit"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema } from '/@/components/Form';
+  import { CollapseContainer } from '/@/components/Container';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field',
+      component: 'Input',
+      label: '\u5B57\u6BB51',
+      colProps: {
+        span: 8,
+      },
+      defaultValue: '1',
+      componentProps: {
+        placeholder: '\u81EA\u5B9A\u4E49placeholder',
+        onChange: (e) => {
+          console.log(e);
+        },
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const { createMessage } = useMessage();
+      return {
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+      };
+    },
+  });
+</script>
+

template \u65B9\u5F0F

\u6240\u6709\u53EF\u8C03\u7528\u51FD\u6570\u89C1\u4E0B\u65B9 Methods \u8BF4\u660E

<template>
+  <div class="m-4">
+    <BasicForm
+      :schemas="schemas"
+      ref="formElRef"
+      :labelWidth="100"
+      @submit="handleSubmit"
+      :actionColOptions="{ span: 24 }"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicForm, FormSchema, FormActionType, FormProps } from '/@/components/Form';
+  import { CollapseContainer } from '/@/components/Container';
+  const schemas: FormSchema[] = [];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const formElRef = ref<Nullable<FormActionType>>(null);
+      return {
+        formElRef,
+        schemas,
+        setProps(props: FormProps) {
+          const formEl = formElRef.value;
+          if (!formEl) return;
+          formEl.setProps(props);
+        },
+      };
+    },
+  });
+</script>
+

useForm

form \u7EC4\u4EF6\u8FD8\u63D0\u4F9B\u4E86 useForm\uFF0C\u65B9\u4FBF\u8C03\u7528\u51FD\u6570\u5185\u90E8\u65B9\u6CD5

\u793A\u4F8B

<template>
+  <BasicForm @register="register" @submit="handleSubmit" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '\u5B57\u6BB51',
+      colProps: {
+        span: 8,
+      },
+      componentProps: {
+        placeholder: '\u81EA\u5B9A\u4E49placeholder',
+        onChange: (e: any) => {
+          console.log(e);
+        },
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const { createMessage } = useMessage();
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+        setProps,
+      };
+    },
+  });
+</script>
+

\u53C2\u6570\u4ECB\u7ECD

const [register, methods] = useForm(props);
+

\u53C2\u6570 props \u5185\u7684\u503C\u53EF\u4EE5\u662F computed \u6216\u8005 ref \u7C7B\u578B

register

register \u7528\u4E8E\u6CE8\u518C useForm\uFF0C\u5982\u679C\u9700\u8981\u4F7F\u7528 useForm \u63D0\u4F9B\u7684 api\uFF0C\u5FC5\u987B\u5C06 register \u4F20\u5165\u7EC4\u4EF6\u7684 onRegister

<template>
+  <BasicForm @register="register" @submit="handleSubmit" />
+</template>
+<script>
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register] = useForm();
+      return {
+        register,
+      };
+    },
+  });
+</script>
+

Methods\u89C1\u4E0B\u65B9\u8BF4\u660E

Methods

getFieldsValue

\u7C7B\u578B: () => Recordable;

\u8BF4\u660E: \u83B7\u53D6\u8868\u5355\u503C

setFieldsValue

\u7C7B\u578B: <T>(values: T) => Promise<void>

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u5355\u5B57\u6BB5\u503C

resetFields

\u7C7B\u578B: ()=> Promise<void>

\u8BF4\u660E: \u91CD\u7F6E\u8868\u5355\u503C

validateFields

\u7C7B\u578B: (nameList?: NamePath[]) => Promise<any>

\u8BF4\u660E: \u6821\u9A8C\u6307\u5B9A\u8868\u5355\u9879

validate

\u7C7B\u578B: (nameList?: NamePath[]) => Promise<any>

\u8BF4\u660E: \u6821\u9A8C\u6574\u4E2A\u8868\u5355

submit

\u7C7B\u578B: () => Promise<void>

\u8BF4\u660E: \u63D0\u4EA4\u8868\u5355

scrollToField

\u7C7B\u578B: (name: NamePath, options?: ScrollOptions) => Promise<void>

\u8BF4\u660E: \u6EDA\u52A8\u5230\u5BF9\u5E94\u5B57\u6BB5\u4F4D\u7F6E

clearValidate

\u7C7B\u578B: (name?: string | string[]) => Promise<void>

\u8BF4\u660E: \u6E05\u7A7A\u6821\u9A8C

setProps

TIP

\u8BBE\u7F6E\u8868\u5355\u7684 props \u53EF\u4EE5\u76F4\u63A5\u5728\u6807\u7B7E\u4E0A\u4F20\u9012\uFF0C\u4E5F\u53EF\u4EE5\u4F7F\u7528 setProps\uFF0C\u6216\u8005\u521D\u59CB\u5316\u76F4\u63A5\u5199 useForm(props)

\u7C7B\u578B: (formProps: Partial<FormProps>) => Promise<void>

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u5355 Props

removeSchemaByFiled

\u7C7B\u578B: (field: string | string[]) => Promise<void>

\u8BF4\u660E: \u6839\u636E field \u5220\u9664 Schema

appendSchemaByField

\u7C7B\u578B: ( schema: FormSchema, prefixField: string | undefined, first?: boolean | undefined ) => Promise<void>

\u8BF4\u660E: \u63D2\u5165\u5230\u6307\u5B9A filed \u540E\u9762\uFF0C\u5982\u679C\u6CA1\u4F20\u6307\u5B9A field\uFF0C\u5219\u63D2\u5165\u5230\u6700\u540E,\u5F53 first = true \u65F6\u63D2\u5165\u5230\u7B2C\u4E00\u4E2A\u4F4D\u7F6E

updateSchema

\u7C7B\u578B: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>

\u8BF4\u660E: \u66F4\u65B0\u8868\u5355\u7684 schema, \u53EA\u66F4\u65B0\u51FD\u6570\u6240\u4F20\u7684\u53C2\u6570

e.g

updateSchema({ field: 'filed', componentProps: { disabled: true } });
+updateSchema([
+  { field: 'filed', componentProps: { disabled: true } },
+  { field: 'filed1', componentProps: { disabled: false } },
+]);
+

Props

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv form

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
schemasSchema[]--\u8868\u5355\u914D\u7F6E\uFF0C\u89C1\u4E0B\u65B9 FormSchema \u914D\u7F6E
submitOnResetbooleanfalse-\u91CD\u7F6E\u65F6\u662F\u5426\u63D0\u4EA4\u8868\u5355
labelColPartial<ColEx>--\u6574\u4E2A\u8868\u5355\u901A\u7528 LabelCol \u914D\u7F6E
wrapperColPartial<ColEx>--\u6574\u4E2A\u8868\u5355\u901A\u7528 wrapperCol \u914D\u7F6E
baseColPropsPartial<ColEx>--\u914D\u7F6E\u6240\u6709\u9009\u5B50\u9879\u7684 ColProps\uFF0C\u4E0D\u9700\u8981\u9010\u4E2A\u914D\u7F6E\uFF0C\u5B50\u9879\u4E5F\u53EF\u5355\u72EC\u914D\u7F6E\u4F18\u5148\u4E0E\u5168\u5C40
baseRowStyleobject--\u914D\u7F6E\u6240\u6709 Row \u7684 style \u6837\u5F0F
labelWidthnumber , string--\u6269\u5C55 form \u7EC4\u4EF6\uFF0C\u589E\u52A0 label \u5BBD\u5EA6\uFF0C\u8868\u5355\u5185\u6240\u6709\u7EC4\u4EF6\u9002\u7528\uFF0C\u53EF\u4EE5\u5355\u72EC\u5728\u67D0\u4E2A\u9879\u8986\u76D6\u6216\u8005\u7981\u7528
labelAlignstring-left,rightlabel \u5E03\u5C40
mergeDynamicDataobject--\u989D\u5916\u4F20\u9012\u5230\u5B50\u7EC4\u4EF6\u7684\u53C2\u6570 values
autoFocusFirstItembooleanfalse-\u662F\u5426\u805A\u7126\u7B2C\u4E00\u4E2A\u8F93\u5165\u6846\uFF0C\u53EA\u5728\u7B2C\u4E00\u4E2A\u8868\u5355\u9879\u4E3A input \u7684\u65F6\u5019\u4F5C\u7528
compactbooleanfalsetrue/false\u7D27\u51D1\u7C7B\u578B\u8868\u5355\uFF0C\u51CF\u5C11 margin-bottom
sizestringdefault'default' , 'small' , 'large'\u5411\u8868\u5355\u5185\u6240\u6709\u7EC4\u4EF6\u4F20\u9012 size \u53C2\u6570,\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u9700\u81EA\u884C\u5B9E\u73B0 size \u63A5\u6536
disabledbooleanfalsetrue/false\u5411\u8868\u5355\u5185\u6240\u6709\u7EC4\u4EF6\u4F20\u9012 disabled \u5C5E\u6027\uFF0C\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u9700\u81EA\u884C\u5B9E\u73B0 disabled \u63A5\u6536
autoSetPlaceHolderbooleantrue true/false\u81EA\u52A8\u8BBE\u7F6E\u8868\u5355\u5185\u7EC4\u4EF6\u7684 placeholder\uFF0C\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u9700\u81EA\u884C\u5B9E\u73B0
autoSubmitOnEnterbooleanfalse true/false\u5728 input \u4E2D\u8F93\u5165\u65F6\u6309\u56DE\u8F66\u81EA\u52A8\u63D0\u4EA42.4.0
rulesMessageJoinLabelbooleanfalsetrue/false\u5982\u679C\u8868\u5355\u9879\u6709\u6821\u9A8C\uFF0C\u4F1A\u81EA\u52A8\u751F\u6210\u6821\u9A8C\u4FE1\u606F\uFF0C\u8BE5\u53C2\u6570\u63A7\u5236\u662F\u5426\u5C06\u5B57\u6BB5\u4E2D\u6587\u540D\u5B57\u62FC\u63A5\u5230\u81EA\u52A8\u751F\u6210\u7684\u4FE1\u606F\u540E\u65B9
showAdvancedButtonbooleanfalsetrue/false\u662F\u5426\u663E\u793A\u6536\u8D77\u5C55\u5F00\u6309\u94AE
emptySpannumber , Partial<ColEx>0-\u7A7A\u767D\u884C\u683C,\u53EF\u4EE5\u662F\u6570\u503C\u6216\u8005 col \u5BF9\u8C61 \u6570
autoAdvancedLinenumber3-\u5982\u679C showAdvancedButton \u4E3A true\uFF0C\u8D85\u8FC7\u6307\u5B9A\u884C\u6570\u884C\u9ED8\u8BA4\u6298\u53E0
alwaysShowLinesnumber1-\u6298\u53E0\u65F6\u59CB\u7EC8\u4FDD\u6301\u663E\u793A\u7684\u884C\u65702.7.1
showActionButtonGroupbooleantruetrue/false\u662F\u5426\u663E\u793A\u64CD\u4F5C\u6309\u94AE(\u91CD\u7F6E/\u63D0\u4EA4)
actionColOptionsPartial<ColEx>--\u64CD\u4F5C\u6309\u94AE\u5916\u5C42 Col \u7EC4\u4EF6\u914D\u7F6E\uFF0C\u5982\u679C\u5F00\u542F showAdvancedButton\uFF0C\u5219\u4E0D\u7528\u8BBE\u7F6E\uFF0C\u5177\u4F53\u89C1\u4E0B\u65B9 actionColOptions
showResetButtonbooleantrue-\u662F\u5426\u663E\u793A\u91CD\u7F6E\u6309\u94AE
resetButtonOptionsobject-\u91CD\u7F6E\u6309\u94AE\u914D\u7F6E\u89C1\u4E0B\u65B9 ActionButtonOption
showSubmitButtonbooleantrue-\u662F\u5426\u663E\u793A\u63D0\u4EA4\u6309\u94AE
submitButtonOptionsobject-\u786E\u8BA4\u6309\u94AE\u914D\u7F6E\u89C1\u4E0B\u65B9 ActionButtonOption
resetFunc () => Promise<void>-\u81EA\u5B9A\u4E49\u91CD\u7F6E\u6309\u94AE\u903B\u8F91() => Promise<void>;
submitFunc () => Promise<void>-\u81EA\u5B9A\u4E49\u63D0\u4EA4\u6309\u94AE\u903B\u8F91() => Promise<void>;
fieldMapToTime[string, [string, string], string?][]'timestamp' ,'timestampStartDay' ,momentjs \u65F6\u95F4\u683C\u5F0F\u7528\u4E8E\u5C06\u8868\u5355\u5185\u65F6\u95F4\u533A\u57DF\u7684\u5E94\u8BBE\u6210 2 \u4E2A\u5B57\u6BB5,\u89C1\u4E0B\u65B9\u8BF4\u660E

ColEx

\u89C1src/components/Form/src/types/index.ts

ActionButtonOption

BasicButtonProps

export interface ButtonProps extends BasicButtonProps {
+  text?: string;
+}
+

fieldMapToTime

\u5C06\u8868\u5355\u5185\u65F6\u95F4\u533A\u57DF\u7684\u503C\u6620\u5C04\u6210 2 \u4E2A\u5B57\u6BB5

\u5982\u679C\u8868\u5355\u5185\u6709\u65F6\u95F4\u533A\u95F4\u7EC4\u4EF6\uFF0C\u83B7\u53D6\u5230\u7684\u503C\u662F\u4E00\u4E2A\u6570\u7EC4\uFF0C\u4F46\u662F\u5F80\u5F80\u6211\u4EEC\u4F20\u9012\u5230\u540E\u53F0\u9700\u8981\u662F 2 \u4E2A\u5B57\u6BB5

useForm({
+  fieldMapToTime: [
+    // data\u4E3A\u65F6\u95F4\u7EC4\u4EF6\u5728\u8868\u5355\u5185\u7684\u5B57\u6BB5\uFF0CstartTime\uFF0CendTime\u4E3A\u8F6C\u5316\u540E\u7684\u5F00\u59CB\u65F6\u95F4\u4E0E\u7ED3\u675F\u65F6\u95F4
+    // 'YYYY-MM-DD'\u4E3A\u65F6\u95F4\u683C\u5F0F\uFF0C\u53C2\u8003moment
+    ['datetime', ['startTime', 'endTime'], 'YYYY-MM-DD'],
+    // \u652F\u6301\u591A\u4E2A\u5B57\u6BB5
+    ['datetime1', ['startTime1', 'endTime1'], 'YYYY-MM-DD HH:mm:ss'],
+  ],
+});
+
+// fieldMapToTime\u6CA1\u5199\u7684\u65F6\u5019\u8868\u5355\u83B7\u53D6\u5230\u7684\u503C
+{
+  datetime: [Date(),Date()]
+}
+//  ['datetime', ['startTime', 'endTime'], 'YYYY-MM-DD'],\u7B49\u540C\u4E8E dayjs(Date()).format('YYYY-MM-DD'). \u4E4B\u540E
+{
+    startTime: '2020-08-12',
+    endTime: '2020-08-15',
+}
+
+// ['datetime', ['startTime', 'endTime'], 'timestamp'],\u7B49\u540C\u4E8E dayjs(Date()).unix(). \u4E4B\u540E
+{
+    startTime: 1597190400,
+    endTime: 1597449600,
+}
+
+// ['datetime', ['startTime', 'endTime'], 'timestampStartDay'],\u7B49\u540C\u4E8E dayjs(Date()).startOf('day').unix(). \u4E4B\u540E
+{
+    startTime: 1597190400,
+    endTime: 1597449600,
+}
+

FormSchema

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
fieldstring--\u5B57\u6BB5\u540D
labelstring--\u6807\u7B7E\u540D
subLabelstring--\u4E8C\u7EA7\u6807\u7B7E\u540D\u7070\u8272
suffixstring , number , ((values: RenderCallbackParams) => string / number);--\u7EC4\u4EF6\u540E\u9762\u7684\u5185\u5BB9
changeEventstring--\u8868\u5355\u66F4\u65B0\u4E8B\u4EF6\u540D\u79F0
helpMessagestring , string[]--\u6807\u7B7E\u540D\u53F3\u4FA7\u6E29\u99A8\u63D0\u793A
helpComponentPropsHelpComponentProps--\u6807\u7B7E\u540D\u53F3\u4FA7\u6E29\u99A8\u63D0\u793A\u7EC4\u4EF6 props,\u89C1\u4E0B\u65B9 HelpComponentProps
labelWidthstring , number--\u8986\u76D6\u7EDF\u4E00\u8BBE\u7F6E\u7684 labelWidth
disabledLabelWidthbooleanfalsetrue/false\u7981\u7528 form \u5168\u5C40\u8BBE\u7F6E\u7684 labelWidth,\u81EA\u5DF1\u624B\u52A8\u8BBE\u7F6E labelCol \u548C wrapperCol
componentstring--\u7EC4\u4EF6\u7C7B\u578B\uFF0C\u89C1\u4E0B\u65B9 ComponentType
componentPropsany,()=>{}--\u6240\u6E32\u67D3\u7684\u7EC4\u4EF6\u7684 props
rulesValidationRule[]--\u6821\u9A8C\u89C4\u5219,\u89C1\u4E0B\u65B9 ValidationRule
requiredboolean--\u7B80\u5316 rules \u914D\u7F6E\uFF0C\u4E3A true \u5219\u8F6C\u5316\u6210 [{required:true}]\u30022.4.0\u4E4B\u524D\u7684\u7248\u672C\u53EA\u652F\u6301 string \u7C7B\u578B\u7684\u503C
rulesMessageJoinLabelbooleanfalse-\u6821\u9A8C\u4FE1\u606F\u662F\u5426\u52A0\u5165 label
itemPropsany--\u53C2\u8003\u4E0B\u65B9 FormItem
colPropsColEx--\u53C2\u8003\u4E0A\u65B9 actionColOptions
defaultValueobject--\u6240\u6E32\u6E32\u67D3\u7EC4\u4EF6\u7684\u521D\u59CB\u503C
render(renderCallbackParams: RenderCallbackParams) => VNode / VNode[] / string--\u81EA\u5B9A\u4E49\u6E32\u67D3\u7EC4\u4EF6
renderColContent(renderCallbackParams: RenderCallbackParams) => VNode / VNode[] / string--\u81EA\u5B9A\u4E49\u6E32\u67D3\u7EC4\u4EF6\uFF08\u9700\u8981\u81EA\u884C\u5305\u542B formItem\uFF09
renderComponentContent(renderCallbackParams: RenderCallbackParams) => any / string--\u81EA\u5B9A\u4E49\u6E32\u67D3\u7EC4\u5185\u90E8\u7684 slot
slotstring--\u81EA\u5B9A\u4E49 slot\uFF0C\u6E32\u67D3\u7EC4\u4EF6
colSlotstring--\u81EA\u5B9A\u4E49 slot\uFF0C\u6E32\u67D3\u7EC4\u4EF6 \uFF08\u9700\u8981\u81EA\u884C\u5305\u542B formItem\uFF09
show boolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--\u52A8\u6001\u5224\u65AD\u5F53\u524D\u7EC4\u4EF6\u662F\u5426\u663E\u793A\uFF0Ccss \u63A7\u5236\uFF0C\u4E0D\u4F1A\u5220\u9664 dom
ifShow boolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--\u52A8\u6001\u5224\u65AD\u5F53\u524D\u7EC4\u4EF6\u662F\u5426\u663E\u793A\uFF0Cjs \u63A7\u5236\uFF0C\u4F1A\u5220\u9664 dom
dynamicDisabledboolean / ((renderCallbackParams: RenderCallbackParams) => boolean) --\u52A8\u6001\u5224\u65AD\u5F53\u524D\u7EC4\u4EF6\u662F\u5426\u7981\u7528
dynamicRulesboolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--\u52A8\u6001\u5224\u8FD4\u5F53\u524D\u7EC4\u4EF6\u4F60\u6821\u9A8C\u89C4\u5219

RenderCallbackParams

export interface RenderCallbackParams {
+  schema: FormSchema;
+  values: any;
+  model: any;
+  field: string;
+}
+

componentProps

  • \u5F53\u503C\u4E3A\u5BF9\u8C61\u7C7B\u578B\u65F6,\u8BE5\u5BF9\u8C61\u5C06\u4F5C\u4E3Acomponent\u6240\u5BF9\u5E94\u7EC4\u4EF6\u7684\u7684 props \u4F20\u5165\u7EC4\u4EF6

  • \u5F53\u503C\u4E3A\u4E00\u4E2A\u51FD\u6570\u65F6\u5019

\u53C2\u6570\u6709 4 \u4E2A

schema: \u8868\u5355\u7684\u6574\u4E2A schemas

formActionType: \u64CD\u4F5C\u8868\u5355\u7684\u51FD\u6570\u3002\u4E0E useForm \u8FD4\u56DE\u7684\u64CD\u4F5C\u51FD\u6570\u4E00\u81F4

formModel: \u8868\u5355\u7684\u53CC\u5411\u7ED1\u5B9A\u5BF9\u8C61\uFF0C\u8FD9\u4E2A\u503C\u662F\u54CD\u5E94\u5F0F\u7684\u3002\u6240\u4EE5\u53EF\u4EE5\u65B9\u4FBF\u5904\u7406\u5F88\u591A\u64CD\u4F5C

tableAction: \u64CD\u4F5C\u8868\u683C\u7684\u51FD\u6570\uFF0C\u4E0E useTable \u8FD4\u56DE\u7684\u64CD\u4F5C\u51FD\u6570\u4E00\u81F4\u3002\u6CE8\u610F\u8BE5\u53C2\u6570\u53EA\u5728\u8868\u683C\u5185\u5F00\u542F\u641C\u7D22\u8868\u5355\u7684\u65F6\u5019\u6709\u503C\uFF0C\u5176\u4F59\u60C5\u51B5\u4E3Anull,

{
+  // \u7B80\u5355\u4F8B\u5B50\uFF0C\u503C\u6539\u53D8\u7684\u65F6\u5019\u64CD\u4F5C\u8868\u683C\u6216\u8005\u4FEE\u6539\u8868\u5355\u5185\u5176\u4ED6\u5143\u7D20\u7684\u503C
+  component:'Input',
+  componentProps: ({ schema, tableAction, formActionType, formModel }) => {
+    return {
+      // xxxx props
+      onChange:e=>{
+        const {reload}=tableAction
+        reload()
+        // or
+        formModel.xxx='123'
+      }
+    };
+  };
+}
+

HelpComponentProps

export interface HelpComponentProps {
+  maxWidth: string;
+  // \u662F\u5426\u663E\u793A\u5E8F\u53F7
+  showIndex: boolean;
+  // \u6587\u672C\u5217\u8868
+  text: any;
+  // \u989C\u8272
+  color: string;
+  // \u5B57\u4F53\u5927\u5C0F
+  fontSize: string;
+  icon: string;
+  absolute: boolean;
+  // \u5B9A\u4F4D
+  position: any;
+}
+

ComponentType

schema \u5185\u7EC4\u4EF6\u7684\u53EF\u9009\u7C7B\u578B

export type ComponentType =
+  | 'Input'
+  | 'InputGroup'
+  | 'InputPassword'
+  | 'InputSearch'
+  | 'InputTextArea'
+  | 'InputNumber'
+  | 'InputCountDown'
+  | 'Select'
+  | 'ApiSelect'
+  | 'TreeSelect'
+  | 'RadioButtonGroup'
+  | 'RadioGroup'
+  | 'Checkbox'
+  | 'CheckboxGroup'
+  | 'AutoComplete'
+  | 'Cascader'
+  | 'DatePicker'
+  | 'MonthPicker'
+  | 'RangePicker'
+  | 'WeekPicker'
+  | 'TimePicker'
+  | 'Switch'
+  | 'StrengthMeter'
+  | 'Upload'
+  | 'IconPicker'
+  | 'Render'
+  | 'Slider'
+  | 'Rate'
+  | 'Divider'; // v2.7.2\u65B0\u589E
+

Divider schema \u8BF4\u660E

Divider\u7C7B\u578B\u7528\u4E8E\u5728schemas\u4E2D\u5360\u4F4D\uFF0C\u5C06\u4F1A\u6E32\u67D3\u6210\u4E00\u4E2A\u5206\u5272\u7EBF\uFF08\u59CB\u7EC8\u5360\u4E00\u6574\u884C\u7684\u7248\u9762\uFF09\uFF0C\u53EF\u4EE5\u7528\u4E8E\u8F83\u957F\u8868\u5355\u7684\u7248\u9762\u5206\u9694\u3002\u8BF7\u53EA\u5C06 Divider \u7C7B\u578B\u7684 schema \u5F53\u4F5C\u4E00\u4E2A\u5206\u5272\u7EBF\uFF0C\u800C\u4E0D\u662F\u4E00\u4E2A\u5E38\u89C4\u7684\u8868\u5355\u5B57\u6BB5\u3002

  • Divider\u4EC5\u5728showAdvancedButton\u4E3A false \u65F6\u624D\u4F1A\u663E\u793A\uFF08\u4E5F\u5C31\u662F\u8BF4\u5982\u679C\u542F\u7528\u4E86\u8868\u5355\u6536\u8D77\u548C\u5C55\u5F00\u529F\u80FD\uFF0CDivider\u5C06\u4E0D\u4F1A\u663E\u793A\uFF09
  • Divider \u4F7F\u7528schema\u4E2D\u7684label\u4EE5\u53CAhelpMessage\u6765\u6E32\u67D3\u5206\u5272\u7EBF\u4E2D\u7684\u63D0\u793A\u5185\u5BB9
  • Divider \u53EF\u4EE5\u4F7F\u7528componentProps\u6765\u8BBE\u7F6E\u9664type\u4E4B\u5916\u7684 props
  • Divider \u4E0D\u4F1A\u6E32\u67D3AFormItem\uFF0C\u56E0\u6B64schema\u4E2D\u9664label\u3001componentProps\u3001helpMessage\u3001helpComponentProps\u4EE5\u5916\u7684\u5C5E\u6027\u4E0D\u4F1A\u88AB\u7528\u5230

\u81EA\u884C\u6DFB\u52A0\u9700\u8981\u7684\u7EC4\u4EF6\u7C7B\u578B

\u5728 src/components/Form/src/componentMap.ts \u5185\uFF0C\u6DFB\u52A0\u9700\u8981\u7684\u7EC4\u4EF6\uFF0C\u5E76\u5728\u4E0A\u65B9 ComponentType \u6DFB\u52A0\u76F8\u5E94\u7684\u7C7B\u578B key

\u65B9\u5F0F 1

\u8FD9\u79CD\u5199\u6CD5\u9002\u7528\u4E0E\u9002\u7528\u9891\u7387\u8F83\u9AD8\u7684\u7EC4\u4EF6

componentMap.set('componentName', \u7EC4\u4EF6);
+
+// ComponentType
+export type ComponentType = xxxx | 'componentName';
+

\u65B9\u5F0F 2

\u4F7F\u7528 useComponentRegister \u8FDB\u884C\u6CE8\u518C

\u8FD9\u79CD\u5199\u6CD5\u53EA\u80FD\u5728\u5F53\u524D\u9875\u4F7F\u7528\uFF0C\u9875\u9762\u9500\u6BC1\u4E4B\u540E\u4F1A\u4ECE componentMap \u5220\u9664\u76F8\u5E94\u7684\u7EC4\u4EF6

import { useComponentRegister } from '@/components/form/index';
+
+import { StrengthMeter } from '@/components/strength-meter/index';
+
+useComponentRegister('StrengthMeter', StrengthMeter);
+

\u63D0\u793A

\u65B9\u5F0F 2 \u51FA\u73B0\u7684\u539F\u56E0\u662F\u4E3A\u4E86\u51CF\u5C11\u6253\u5305\u4F53\u79EF\uFF0C\u5982\u679C\u67D0\u4E2A\u7EC4\u4EF6\u4F53\u79EF\u5F88\u5927\uFF0C\u7528\u65B9\u5F0F 1 \u7684\u8BDD\u53EF\u80FD\u4F1A\u4F7F\u9996\u5C4F\u4F53\u79EF\u589E\u52A0

render

\u81EA\u5B9A\u4E49\u6E32\u67D3\u5185\u5BB9

<template>
+  <div class="m-4">
+    <BasicForm @register="register" @submit="handleSubmit" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, h } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { Input } from 'ant-design-vue';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '\u5B57\u6BB51',
+      colProps: {
+        span: 8,
+      },
+      rules: [{ required: true }],
+      render: ({ model, field }) => {
+        return h(Input, {
+          placeholder: '\u8BF7\u8F93\u5165',
+          value: model[field],
+          onChange: (e: ChangeEvent) => {
+            model[field] = e.target.value;
+          },
+        });
+      },
+    },
+    {
+      field: 'field2',
+      component: 'Input',
+      label: '\u5B57\u6BB52',
+      colProps: {
+        span: 8,
+      },
+      rules: [{ required: true }],
+      renderComponentContent: () => {
+        return {
+          suffix: () => 'suffix',
+        };
+      },
+    },
+  ];
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const { createMessage } = useMessage();
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+        setProps,
+      };
+    },
+  });
+</script>
+

slot

\u81EA\u5B9A\u4E49\u6E32\u67D3\u5185\u5BB9

\u63D0\u793A

\u4F7F\u7528\u63D2\u69FD\u81EA\u5B9A\u4E49\u8868\u5355\u57DF\u65F6\uFF0C\u8BF7\u6CE8\u610F antdv \u6709\u5173 FormItem \u7684\u76F8\u5173\u8BF4\u660E\u3002

<template>
+  <div class="m-4">
+    <BasicForm @register="register">
+      <template #customSlot="{ model, field }">
+        <a-input v-model:value="model[field]" />
+      </template>
+    </BasicForm>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'compatible-vue';
+  import { BasicForm, useForm } from '@/components/Form/index';
+  import { BasicModal } from '@/components/modal/index';
+  export default defineComponent({
+    name: 'FormDemo',
+    setup(props) {
+      const [register] = useForm({
+        labelWidth: 100,
+        actionColOptions: {
+          span: 24,
+        },
+        schemas: [
+          {
+            field: 'field1',
+            label: '\u5B57\u6BB51',
+            slot: 'customSlot',
+          },
+        ],
+      });
+      return {
+        register,
+      };
+    },
+  });
+</script>
+

ifShow/show/dynamicDisabled

\u81EA\u5B9A\u4E49\u663E\u793A/\u7981\u7528

<template>
+  <div class="m-4">
+    <BasicForm @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '\u5B57\u6BB51',
+      colProps: {
+        span: 8,
+      },
+      show: ({ values }) => {
+        return !!values.field5;
+      },
+    },
+    {
+      field: 'field2',
+      component: 'Input',
+      label: '\u5B57\u6BB52',
+      colProps: {
+        span: 8,
+      },
+      ifShow: ({ values }) => {
+        return !!values.field6;
+      },
+    },
+    {
+      field: 'field3',
+      component: 'DatePicker',
+      label: '\u5B57\u6BB53',
+      colProps: {
+        span: 8,
+      },
+      dynamicDisabled: ({ values }) => {
+        return !!values.field7;
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        setProps,
+      };
+    },
+  });
+</script>
+

\u89C1 antv form

Slots

\u540D\u79F0\u8BF4\u660E
formFooter\u8868\u5355\u5E95\u90E8\u533A\u57DF
formHeader\u8868\u5355\u9876\u90E8\u533A\u57DF
resetBefore\u91CD\u7F6E\u6309\u94AE\u524D
submitBefore\u63D0\u4EA4\u6309\u94AE\u524D
advanceBefore\u5C55\u5F00\u6309\u94AE\u524D
advanceAfter\u5C55\u5F00\u6309\u94AE\u540E

ApiSelect

\u8FDC\u7A0B\u4E0B\u62C9\u52A0\u8F7D\u7EC4\u4EF6\uFF0C\u8BE5\u7EC4\u4EF6\u53EF\u4EE5\u7528\u4E8E\u5B66\u4E60\u53C2\u8003\u5982\u4F55\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u96C6\u6210\u5230 Form \u7EC4\u4EF6\u5185\uFF0C\u5C06\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u4EA4\u7531 Form \u53BB\u7BA1\u7406

Usage

const schemas: FormSchema[] = [
+  {
+    field: 'field',
+    component: 'ApiSelect',
+    label: '\u5B57\u6BB5',
+  },
+];
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
numberToStringbooleanfalse\u662F\u5426\u5C06number\u503C\u8F6C\u5316\u4E3Astring
api()=>Promise<{ label: string; value: string; disabled?: boolean }[]>-\u6570\u636E\u63A5\u53E3\uFF0C\u63A5\u53D7\u4E00\u4E2A Promise \u5BF9\u8C61
paramsobject-\u63A5\u53E3\u53C2\u6570\u3002\u6B64\u5C5E\u6027\u6539\u53D8\u65F6\u4F1A\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u63A5\u53E3\u6570\u636E
resultFieldstring-\u63A5\u53E3\u8FD4\u56DE\u7684\u5B57\u6BB5\uFF0C\u5982\u679C\u63A5\u53E3\u8FD4\u56DE\u6570\u7EC4\uFF0C\u53EF\u4EE5\u4E0D\u586B\u3002\u652F\u6301x.x.x\u683C\u5F0F
labelFieldstringlabel\u4E0B\u62C9\u6570\u7EC4\u9879\u5185label\u663E\u793A\u6587\u672C\u7684\u5B57\u6BB5\uFF0C\u652F\u6301x.x.x\u683C\u5F0F
valueFieldstringvalue\u4E0B\u62C9\u6570\u7EC4\u9879\u5185value\u5B9E\u9645\u503C\u7684\u5B57\u6BB5\uFF0C\u652F\u6301x.x.x\u683C\u5F0F
immediatebooleantrue\u662F\u5426\u7ACB\u5373\u8BF7\u6C42\u63A5\u53E3\uFF0C\u5426\u5219\u5C06\u5728\u7B2C\u4E00\u6B21\u70B9\u51FB\u65F6\u5019\u89E6\u53D1\u8BF7\u6C42

ApiTreeSelect

\u8FDC\u7A0B\u4E0B\u62C9\u6811\u52A0\u8F7D\u7EC4\u4EF6\uFF0C\u548CApiSelect\u7C7B\u4F3C\uFF0C2.6.1 \u4EE5\u4E0A\u7248\u672C

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
api()=>Promise<{ label: string; value: string; children?: any[] }[]>-\u6570\u636E\u63A5\u53E3\uFF0C\u63A5\u53D7\u4E00\u4E2A Promise \u5BF9\u8C61
paramsobject-\u63A5\u53E3\u53C2\u6570\u3002\u6B64\u5C5E\u6027\u6539\u53D8\u65F6\u4F1A\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u63A5\u53E3\u6570\u636E
resultFieldstring-\u63A5\u53E3\u8FD4\u56DE\u7684\u5B57\u6BB5\uFF0C\u5982\u679C\u63A5\u53E3\u8FD4\u56DE\u6570\u7EC4\uFF0C\u53EF\u4EE5\u4E0D\u586B\u3002\u652F\u6301x.x.x\u683C\u5F0F
immediatebooleantrue\u662F\u5426\u7ACB\u5373\u8BF7\u6C42\u63A5\u53E3\u3002

RadioButtonGroup

Radio Button \u98CE\u683C\u7684\u9009\u62E9\u6309\u94AE

Usage

const schemas: FormSchema[] = [
+  {
+    field: 'field',
+    component: 'RadioButtonGroup',
+    label: '\u5B57\u6BB5',
+  },
+];
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
options{ label: string; value: string; disabled?: boolean }[]-\u6570\u636E\u5B57\u6BB5
`,133),e=[o];function c(l,u,r,i,k,d){return a(),s("div",null,e)}var h=n(p,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/components_form.md.8ee9e1a7.lean.js b/assets/components_form.md.8ee9e1a7.lean.js new file mode 100644 index 00000000..b03816ba --- /dev/null +++ b/assets/components_form.md.8ee9e1a7.lean.js @@ -0,0 +1,433 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Form \u8868\u5355\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":3,"title":"useForm \u65B9\u5F0F","slug":"useform-\u65B9\u5F0F"},{"level":3,"title":"template \u65B9\u5F0F","slug":"template-\u65B9\u5F0F"},{"level":2,"title":"useForm","slug":"useform"},{"level":3,"title":"\u793A\u4F8B","slug":"\u793A\u4F8B"},{"level":3,"title":"\u53C2\u6570\u4ECB\u7ECD","slug":"\u53C2\u6570\u4ECB\u7ECD"},{"level":3,"title":"Methods","slug":"methods"},{"level":2,"title":"Props","slug":"props"},{"level":3,"title":"ColEx","slug":"colex"},{"level":3,"title":"ActionButtonOption","slug":"actionbuttonoption"},{"level":3,"title":"fieldMapToTime","slug":"fieldmaptotime"},{"level":3,"title":"FormSchema","slug":"formschema"},{"level":3,"title":"Divider schema \u8BF4\u660E","slug":"divider-schema-\u8BF4\u660E"},{"level":2,"title":"\u81EA\u884C\u6DFB\u52A0\u9700\u8981\u7684\u7EC4\u4EF6\u7C7B\u578B","slug":"\u81EA\u884C\u6DFB\u52A0\u9700\u8981\u7684\u7EC4\u4EF6\u7C7B\u578B"},{"level":3,"title":"\u65B9\u5F0F 1","slug":"\u65B9\u5F0F-1"},{"level":3,"title":"\u65B9\u5F0F 2","slug":"\u65B9\u5F0F-2"},{"level":3,"title":"render","slug":"render"},{"level":3,"title":"slot","slug":"slot"},{"level":3,"title":"ifShow/show/dynamicDisabled","slug":"ifshow-show-dynamicdisabled"},{"level":2,"title":"Slots","slug":"slots"},{"level":2,"title":"ApiSelect","slug":"apiselect"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"},{"level":2,"title":"ApiTreeSelect","slug":"apitreeselect"},{"level":3,"title":"Props","slug":"props-2"},{"level":2,"title":"RadioButtonGroup","slug":"radiobuttongroup"},{"level":3,"title":"Usage","slug":"usage-2"},{"level":3,"title":"Props","slug":"props-3"}],"relativePath":"components/form.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Form \u8868\u5355\u7EC4\u4EF6

\u5BF9 antv \u7684 form \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5\uFF0C\u6269\u5C55\u4E00\u4E9B\u5E38\u7528\u7684\u529F\u80FD

\u5982\u679C\u6587\u6863\u5185\u6CA1\u6709\uFF0C\u53EF\u4EE5\u5C1D\u8BD5\u5728\u5728\u7EBF\u793A\u4F8B\u5185\u5BFB\u627E

Usage

useForm \u65B9\u5F0F

\u4E0B\u9762\u662F\u4E00\u4E2A\u4F7F\u7528\u7B80\u5355\u8868\u5355\u7684\u793A\u4F8B\uFF0C\u53EA\u6709\u4E00\u4E2A\u8F93\u5165\u6846

<template>
+  <div class="m-4">
+    <BasicForm
+      :labelWidth="100"
+      :schemas="schemas"
+      :actionColOptions="{ span: 24 }"
+      @submit="handleSubmit"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema } from '/@/components/Form';
+  import { CollapseContainer } from '/@/components/Container';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field',
+      component: 'Input',
+      label: '\u5B57\u6BB51',
+      colProps: {
+        span: 8,
+      },
+      defaultValue: '1',
+      componentProps: {
+        placeholder: '\u81EA\u5B9A\u4E49placeholder',
+        onChange: (e) => {
+          console.log(e);
+        },
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const { createMessage } = useMessage();
+      return {
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+      };
+    },
+  });
+</script>
+

template \u65B9\u5F0F

\u6240\u6709\u53EF\u8C03\u7528\u51FD\u6570\u89C1\u4E0B\u65B9 Methods \u8BF4\u660E

<template>
+  <div class="m-4">
+    <BasicForm
+      :schemas="schemas"
+      ref="formElRef"
+      :labelWidth="100"
+      @submit="handleSubmit"
+      :actionColOptions="{ span: 24 }"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicForm, FormSchema, FormActionType, FormProps } from '/@/components/Form';
+  import { CollapseContainer } from '/@/components/Container';
+  const schemas: FormSchema[] = [];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const formElRef = ref<Nullable<FormActionType>>(null);
+      return {
+        formElRef,
+        schemas,
+        setProps(props: FormProps) {
+          const formEl = formElRef.value;
+          if (!formEl) return;
+          formEl.setProps(props);
+        },
+      };
+    },
+  });
+</script>
+

useForm

form \u7EC4\u4EF6\u8FD8\u63D0\u4F9B\u4E86 useForm\uFF0C\u65B9\u4FBF\u8C03\u7528\u51FD\u6570\u5185\u90E8\u65B9\u6CD5

\u793A\u4F8B

<template>
+  <BasicForm @register="register" @submit="handleSubmit" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '\u5B57\u6BB51',
+      colProps: {
+        span: 8,
+      },
+      componentProps: {
+        placeholder: '\u81EA\u5B9A\u4E49placeholder',
+        onChange: (e: any) => {
+          console.log(e);
+        },
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const { createMessage } = useMessage();
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+        setProps,
+      };
+    },
+  });
+</script>
+

\u53C2\u6570\u4ECB\u7ECD

const [register, methods] = useForm(props);
+

\u53C2\u6570 props \u5185\u7684\u503C\u53EF\u4EE5\u662F computed \u6216\u8005 ref \u7C7B\u578B

register

register \u7528\u4E8E\u6CE8\u518C useForm\uFF0C\u5982\u679C\u9700\u8981\u4F7F\u7528 useForm \u63D0\u4F9B\u7684 api\uFF0C\u5FC5\u987B\u5C06 register \u4F20\u5165\u7EC4\u4EF6\u7684 onRegister

<template>
+  <BasicForm @register="register" @submit="handleSubmit" />
+</template>
+<script>
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register] = useForm();
+      return {
+        register,
+      };
+    },
+  });
+</script>
+

Methods\u89C1\u4E0B\u65B9\u8BF4\u660E

Methods

getFieldsValue

\u7C7B\u578B: () => Recordable;

\u8BF4\u660E: \u83B7\u53D6\u8868\u5355\u503C

setFieldsValue

\u7C7B\u578B: <T>(values: T) => Promise<void>

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u5355\u5B57\u6BB5\u503C

resetFields

\u7C7B\u578B: ()=> Promise<void>

\u8BF4\u660E: \u91CD\u7F6E\u8868\u5355\u503C

validateFields

\u7C7B\u578B: (nameList?: NamePath[]) => Promise<any>

\u8BF4\u660E: \u6821\u9A8C\u6307\u5B9A\u8868\u5355\u9879

validate

\u7C7B\u578B: (nameList?: NamePath[]) => Promise<any>

\u8BF4\u660E: \u6821\u9A8C\u6574\u4E2A\u8868\u5355

submit

\u7C7B\u578B: () => Promise<void>

\u8BF4\u660E: \u63D0\u4EA4\u8868\u5355

scrollToField

\u7C7B\u578B: (name: NamePath, options?: ScrollOptions) => Promise<void>

\u8BF4\u660E: \u6EDA\u52A8\u5230\u5BF9\u5E94\u5B57\u6BB5\u4F4D\u7F6E

clearValidate

\u7C7B\u578B: (name?: string | string[]) => Promise<void>

\u8BF4\u660E: \u6E05\u7A7A\u6821\u9A8C

setProps

TIP

\u8BBE\u7F6E\u8868\u5355\u7684 props \u53EF\u4EE5\u76F4\u63A5\u5728\u6807\u7B7E\u4E0A\u4F20\u9012\uFF0C\u4E5F\u53EF\u4EE5\u4F7F\u7528 setProps\uFF0C\u6216\u8005\u521D\u59CB\u5316\u76F4\u63A5\u5199 useForm(props)

\u7C7B\u578B: (formProps: Partial<FormProps>) => Promise<void>

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u5355 Props

removeSchemaByFiled

\u7C7B\u578B: (field: string | string[]) => Promise<void>

\u8BF4\u660E: \u6839\u636E field \u5220\u9664 Schema

appendSchemaByField

\u7C7B\u578B: ( schema: FormSchema, prefixField: string | undefined, first?: boolean | undefined ) => Promise<void>

\u8BF4\u660E: \u63D2\u5165\u5230\u6307\u5B9A filed \u540E\u9762\uFF0C\u5982\u679C\u6CA1\u4F20\u6307\u5B9A field\uFF0C\u5219\u63D2\u5165\u5230\u6700\u540E,\u5F53 first = true \u65F6\u63D2\u5165\u5230\u7B2C\u4E00\u4E2A\u4F4D\u7F6E

updateSchema

\u7C7B\u578B: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>

\u8BF4\u660E: \u66F4\u65B0\u8868\u5355\u7684 schema, \u53EA\u66F4\u65B0\u51FD\u6570\u6240\u4F20\u7684\u53C2\u6570

e.g

updateSchema({ field: 'filed', componentProps: { disabled: true } });
+updateSchema([
+  { field: 'filed', componentProps: { disabled: true } },
+  { field: 'filed1', componentProps: { disabled: false } },
+]);
+

Props

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv form

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
schemasSchema[]--\u8868\u5355\u914D\u7F6E\uFF0C\u89C1\u4E0B\u65B9 FormSchema \u914D\u7F6E
submitOnResetbooleanfalse-\u91CD\u7F6E\u65F6\u662F\u5426\u63D0\u4EA4\u8868\u5355
labelColPartial<ColEx>--\u6574\u4E2A\u8868\u5355\u901A\u7528 LabelCol \u914D\u7F6E
wrapperColPartial<ColEx>--\u6574\u4E2A\u8868\u5355\u901A\u7528 wrapperCol \u914D\u7F6E
baseColPropsPartial<ColEx>--\u914D\u7F6E\u6240\u6709\u9009\u5B50\u9879\u7684 ColProps\uFF0C\u4E0D\u9700\u8981\u9010\u4E2A\u914D\u7F6E\uFF0C\u5B50\u9879\u4E5F\u53EF\u5355\u72EC\u914D\u7F6E\u4F18\u5148\u4E0E\u5168\u5C40
baseRowStyleobject--\u914D\u7F6E\u6240\u6709 Row \u7684 style \u6837\u5F0F
labelWidthnumber , string--\u6269\u5C55 form \u7EC4\u4EF6\uFF0C\u589E\u52A0 label \u5BBD\u5EA6\uFF0C\u8868\u5355\u5185\u6240\u6709\u7EC4\u4EF6\u9002\u7528\uFF0C\u53EF\u4EE5\u5355\u72EC\u5728\u67D0\u4E2A\u9879\u8986\u76D6\u6216\u8005\u7981\u7528
labelAlignstring-left,rightlabel \u5E03\u5C40
mergeDynamicDataobject--\u989D\u5916\u4F20\u9012\u5230\u5B50\u7EC4\u4EF6\u7684\u53C2\u6570 values
autoFocusFirstItembooleanfalse-\u662F\u5426\u805A\u7126\u7B2C\u4E00\u4E2A\u8F93\u5165\u6846\uFF0C\u53EA\u5728\u7B2C\u4E00\u4E2A\u8868\u5355\u9879\u4E3A input \u7684\u65F6\u5019\u4F5C\u7528
compactbooleanfalsetrue/false\u7D27\u51D1\u7C7B\u578B\u8868\u5355\uFF0C\u51CF\u5C11 margin-bottom
sizestringdefault'default' , 'small' , 'large'\u5411\u8868\u5355\u5185\u6240\u6709\u7EC4\u4EF6\u4F20\u9012 size \u53C2\u6570,\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u9700\u81EA\u884C\u5B9E\u73B0 size \u63A5\u6536
disabledbooleanfalsetrue/false\u5411\u8868\u5355\u5185\u6240\u6709\u7EC4\u4EF6\u4F20\u9012 disabled \u5C5E\u6027\uFF0C\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u9700\u81EA\u884C\u5B9E\u73B0 disabled \u63A5\u6536
autoSetPlaceHolderbooleantrue true/false\u81EA\u52A8\u8BBE\u7F6E\u8868\u5355\u5185\u7EC4\u4EF6\u7684 placeholder\uFF0C\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u9700\u81EA\u884C\u5B9E\u73B0
autoSubmitOnEnterbooleanfalse true/false\u5728 input \u4E2D\u8F93\u5165\u65F6\u6309\u56DE\u8F66\u81EA\u52A8\u63D0\u4EA42.4.0
rulesMessageJoinLabelbooleanfalsetrue/false\u5982\u679C\u8868\u5355\u9879\u6709\u6821\u9A8C\uFF0C\u4F1A\u81EA\u52A8\u751F\u6210\u6821\u9A8C\u4FE1\u606F\uFF0C\u8BE5\u53C2\u6570\u63A7\u5236\u662F\u5426\u5C06\u5B57\u6BB5\u4E2D\u6587\u540D\u5B57\u62FC\u63A5\u5230\u81EA\u52A8\u751F\u6210\u7684\u4FE1\u606F\u540E\u65B9
showAdvancedButtonbooleanfalsetrue/false\u662F\u5426\u663E\u793A\u6536\u8D77\u5C55\u5F00\u6309\u94AE
emptySpannumber , Partial<ColEx>0-\u7A7A\u767D\u884C\u683C,\u53EF\u4EE5\u662F\u6570\u503C\u6216\u8005 col \u5BF9\u8C61 \u6570
autoAdvancedLinenumber3-\u5982\u679C showAdvancedButton \u4E3A true\uFF0C\u8D85\u8FC7\u6307\u5B9A\u884C\u6570\u884C\u9ED8\u8BA4\u6298\u53E0
alwaysShowLinesnumber1-\u6298\u53E0\u65F6\u59CB\u7EC8\u4FDD\u6301\u663E\u793A\u7684\u884C\u65702.7.1
showActionButtonGroupbooleantruetrue/false\u662F\u5426\u663E\u793A\u64CD\u4F5C\u6309\u94AE(\u91CD\u7F6E/\u63D0\u4EA4)
actionColOptionsPartial<ColEx>--\u64CD\u4F5C\u6309\u94AE\u5916\u5C42 Col \u7EC4\u4EF6\u914D\u7F6E\uFF0C\u5982\u679C\u5F00\u542F showAdvancedButton\uFF0C\u5219\u4E0D\u7528\u8BBE\u7F6E\uFF0C\u5177\u4F53\u89C1\u4E0B\u65B9 actionColOptions
showResetButtonbooleantrue-\u662F\u5426\u663E\u793A\u91CD\u7F6E\u6309\u94AE
resetButtonOptionsobject-\u91CD\u7F6E\u6309\u94AE\u914D\u7F6E\u89C1\u4E0B\u65B9 ActionButtonOption
showSubmitButtonbooleantrue-\u662F\u5426\u663E\u793A\u63D0\u4EA4\u6309\u94AE
submitButtonOptionsobject-\u786E\u8BA4\u6309\u94AE\u914D\u7F6E\u89C1\u4E0B\u65B9 ActionButtonOption
resetFunc () => Promise<void>-\u81EA\u5B9A\u4E49\u91CD\u7F6E\u6309\u94AE\u903B\u8F91() => Promise<void>;
submitFunc () => Promise<void>-\u81EA\u5B9A\u4E49\u63D0\u4EA4\u6309\u94AE\u903B\u8F91() => Promise<void>;
fieldMapToTime[string, [string, string], string?][]'timestamp' ,'timestampStartDay' ,momentjs \u65F6\u95F4\u683C\u5F0F\u7528\u4E8E\u5C06\u8868\u5355\u5185\u65F6\u95F4\u533A\u57DF\u7684\u5E94\u8BBE\u6210 2 \u4E2A\u5B57\u6BB5,\u89C1\u4E0B\u65B9\u8BF4\u660E

ColEx

\u89C1src/components/Form/src/types/index.ts

ActionButtonOption

BasicButtonProps

export interface ButtonProps extends BasicButtonProps {
+  text?: string;
+}
+

fieldMapToTime

\u5C06\u8868\u5355\u5185\u65F6\u95F4\u533A\u57DF\u7684\u503C\u6620\u5C04\u6210 2 \u4E2A\u5B57\u6BB5

\u5982\u679C\u8868\u5355\u5185\u6709\u65F6\u95F4\u533A\u95F4\u7EC4\u4EF6\uFF0C\u83B7\u53D6\u5230\u7684\u503C\u662F\u4E00\u4E2A\u6570\u7EC4\uFF0C\u4F46\u662F\u5F80\u5F80\u6211\u4EEC\u4F20\u9012\u5230\u540E\u53F0\u9700\u8981\u662F 2 \u4E2A\u5B57\u6BB5

useForm({
+  fieldMapToTime: [
+    // data\u4E3A\u65F6\u95F4\u7EC4\u4EF6\u5728\u8868\u5355\u5185\u7684\u5B57\u6BB5\uFF0CstartTime\uFF0CendTime\u4E3A\u8F6C\u5316\u540E\u7684\u5F00\u59CB\u65F6\u95F4\u4E0E\u7ED3\u675F\u65F6\u95F4
+    // 'YYYY-MM-DD'\u4E3A\u65F6\u95F4\u683C\u5F0F\uFF0C\u53C2\u8003moment
+    ['datetime', ['startTime', 'endTime'], 'YYYY-MM-DD'],
+    // \u652F\u6301\u591A\u4E2A\u5B57\u6BB5
+    ['datetime1', ['startTime1', 'endTime1'], 'YYYY-MM-DD HH:mm:ss'],
+  ],
+});
+
+// fieldMapToTime\u6CA1\u5199\u7684\u65F6\u5019\u8868\u5355\u83B7\u53D6\u5230\u7684\u503C
+{
+  datetime: [Date(),Date()]
+}
+//  ['datetime', ['startTime', 'endTime'], 'YYYY-MM-DD'],\u7B49\u540C\u4E8E dayjs(Date()).format('YYYY-MM-DD'). \u4E4B\u540E
+{
+    startTime: '2020-08-12',
+    endTime: '2020-08-15',
+}
+
+// ['datetime', ['startTime', 'endTime'], 'timestamp'],\u7B49\u540C\u4E8E dayjs(Date()).unix(). \u4E4B\u540E
+{
+    startTime: 1597190400,
+    endTime: 1597449600,
+}
+
+// ['datetime', ['startTime', 'endTime'], 'timestampStartDay'],\u7B49\u540C\u4E8E dayjs(Date()).startOf('day').unix(). \u4E4B\u540E
+{
+    startTime: 1597190400,
+    endTime: 1597449600,
+}
+

FormSchema

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
fieldstring--\u5B57\u6BB5\u540D
labelstring--\u6807\u7B7E\u540D
subLabelstring--\u4E8C\u7EA7\u6807\u7B7E\u540D\u7070\u8272
suffixstring , number , ((values: RenderCallbackParams) => string / number);--\u7EC4\u4EF6\u540E\u9762\u7684\u5185\u5BB9
changeEventstring--\u8868\u5355\u66F4\u65B0\u4E8B\u4EF6\u540D\u79F0
helpMessagestring , string[]--\u6807\u7B7E\u540D\u53F3\u4FA7\u6E29\u99A8\u63D0\u793A
helpComponentPropsHelpComponentProps--\u6807\u7B7E\u540D\u53F3\u4FA7\u6E29\u99A8\u63D0\u793A\u7EC4\u4EF6 props,\u89C1\u4E0B\u65B9 HelpComponentProps
labelWidthstring , number--\u8986\u76D6\u7EDF\u4E00\u8BBE\u7F6E\u7684 labelWidth
disabledLabelWidthbooleanfalsetrue/false\u7981\u7528 form \u5168\u5C40\u8BBE\u7F6E\u7684 labelWidth,\u81EA\u5DF1\u624B\u52A8\u8BBE\u7F6E labelCol \u548C wrapperCol
componentstring--\u7EC4\u4EF6\u7C7B\u578B\uFF0C\u89C1\u4E0B\u65B9 ComponentType
componentPropsany,()=>{}--\u6240\u6E32\u67D3\u7684\u7EC4\u4EF6\u7684 props
rulesValidationRule[]--\u6821\u9A8C\u89C4\u5219,\u89C1\u4E0B\u65B9 ValidationRule
requiredboolean--\u7B80\u5316 rules \u914D\u7F6E\uFF0C\u4E3A true \u5219\u8F6C\u5316\u6210 [{required:true}]\u30022.4.0\u4E4B\u524D\u7684\u7248\u672C\u53EA\u652F\u6301 string \u7C7B\u578B\u7684\u503C
rulesMessageJoinLabelbooleanfalse-\u6821\u9A8C\u4FE1\u606F\u662F\u5426\u52A0\u5165 label
itemPropsany--\u53C2\u8003\u4E0B\u65B9 FormItem
colPropsColEx--\u53C2\u8003\u4E0A\u65B9 actionColOptions
defaultValueobject--\u6240\u6E32\u6E32\u67D3\u7EC4\u4EF6\u7684\u521D\u59CB\u503C
render(renderCallbackParams: RenderCallbackParams) => VNode / VNode[] / string--\u81EA\u5B9A\u4E49\u6E32\u67D3\u7EC4\u4EF6
renderColContent(renderCallbackParams: RenderCallbackParams) => VNode / VNode[] / string--\u81EA\u5B9A\u4E49\u6E32\u67D3\u7EC4\u4EF6\uFF08\u9700\u8981\u81EA\u884C\u5305\u542B formItem\uFF09
renderComponentContent(renderCallbackParams: RenderCallbackParams) => any / string--\u81EA\u5B9A\u4E49\u6E32\u67D3\u7EC4\u5185\u90E8\u7684 slot
slotstring--\u81EA\u5B9A\u4E49 slot\uFF0C\u6E32\u67D3\u7EC4\u4EF6
colSlotstring--\u81EA\u5B9A\u4E49 slot\uFF0C\u6E32\u67D3\u7EC4\u4EF6 \uFF08\u9700\u8981\u81EA\u884C\u5305\u542B formItem\uFF09
show boolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--\u52A8\u6001\u5224\u65AD\u5F53\u524D\u7EC4\u4EF6\u662F\u5426\u663E\u793A\uFF0Ccss \u63A7\u5236\uFF0C\u4E0D\u4F1A\u5220\u9664 dom
ifShow boolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--\u52A8\u6001\u5224\u65AD\u5F53\u524D\u7EC4\u4EF6\u662F\u5426\u663E\u793A\uFF0Cjs \u63A7\u5236\uFF0C\u4F1A\u5220\u9664 dom
dynamicDisabledboolean / ((renderCallbackParams: RenderCallbackParams) => boolean) --\u52A8\u6001\u5224\u65AD\u5F53\u524D\u7EC4\u4EF6\u662F\u5426\u7981\u7528
dynamicRulesboolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--\u52A8\u6001\u5224\u8FD4\u5F53\u524D\u7EC4\u4EF6\u4F60\u6821\u9A8C\u89C4\u5219

RenderCallbackParams

export interface RenderCallbackParams {
+  schema: FormSchema;
+  values: any;
+  model: any;
+  field: string;
+}
+

componentProps

  • \u5F53\u503C\u4E3A\u5BF9\u8C61\u7C7B\u578B\u65F6,\u8BE5\u5BF9\u8C61\u5C06\u4F5C\u4E3Acomponent\u6240\u5BF9\u5E94\u7EC4\u4EF6\u7684\u7684 props \u4F20\u5165\u7EC4\u4EF6

  • \u5F53\u503C\u4E3A\u4E00\u4E2A\u51FD\u6570\u65F6\u5019

\u53C2\u6570\u6709 4 \u4E2A

schema: \u8868\u5355\u7684\u6574\u4E2A schemas

formActionType: \u64CD\u4F5C\u8868\u5355\u7684\u51FD\u6570\u3002\u4E0E useForm \u8FD4\u56DE\u7684\u64CD\u4F5C\u51FD\u6570\u4E00\u81F4

formModel: \u8868\u5355\u7684\u53CC\u5411\u7ED1\u5B9A\u5BF9\u8C61\uFF0C\u8FD9\u4E2A\u503C\u662F\u54CD\u5E94\u5F0F\u7684\u3002\u6240\u4EE5\u53EF\u4EE5\u65B9\u4FBF\u5904\u7406\u5F88\u591A\u64CD\u4F5C

tableAction: \u64CD\u4F5C\u8868\u683C\u7684\u51FD\u6570\uFF0C\u4E0E useTable \u8FD4\u56DE\u7684\u64CD\u4F5C\u51FD\u6570\u4E00\u81F4\u3002\u6CE8\u610F\u8BE5\u53C2\u6570\u53EA\u5728\u8868\u683C\u5185\u5F00\u542F\u641C\u7D22\u8868\u5355\u7684\u65F6\u5019\u6709\u503C\uFF0C\u5176\u4F59\u60C5\u51B5\u4E3Anull,

{
+  // \u7B80\u5355\u4F8B\u5B50\uFF0C\u503C\u6539\u53D8\u7684\u65F6\u5019\u64CD\u4F5C\u8868\u683C\u6216\u8005\u4FEE\u6539\u8868\u5355\u5185\u5176\u4ED6\u5143\u7D20\u7684\u503C
+  component:'Input',
+  componentProps: ({ schema, tableAction, formActionType, formModel }) => {
+    return {
+      // xxxx props
+      onChange:e=>{
+        const {reload}=tableAction
+        reload()
+        // or
+        formModel.xxx='123'
+      }
+    };
+  };
+}
+

HelpComponentProps

export interface HelpComponentProps {
+  maxWidth: string;
+  // \u662F\u5426\u663E\u793A\u5E8F\u53F7
+  showIndex: boolean;
+  // \u6587\u672C\u5217\u8868
+  text: any;
+  // \u989C\u8272
+  color: string;
+  // \u5B57\u4F53\u5927\u5C0F
+  fontSize: string;
+  icon: string;
+  absolute: boolean;
+  // \u5B9A\u4F4D
+  position: any;
+}
+

ComponentType

schema \u5185\u7EC4\u4EF6\u7684\u53EF\u9009\u7C7B\u578B

export type ComponentType =
+  | 'Input'
+  | 'InputGroup'
+  | 'InputPassword'
+  | 'InputSearch'
+  | 'InputTextArea'
+  | 'InputNumber'
+  | 'InputCountDown'
+  | 'Select'
+  | 'ApiSelect'
+  | 'TreeSelect'
+  | 'RadioButtonGroup'
+  | 'RadioGroup'
+  | 'Checkbox'
+  | 'CheckboxGroup'
+  | 'AutoComplete'
+  | 'Cascader'
+  | 'DatePicker'
+  | 'MonthPicker'
+  | 'RangePicker'
+  | 'WeekPicker'
+  | 'TimePicker'
+  | 'Switch'
+  | 'StrengthMeter'
+  | 'Upload'
+  | 'IconPicker'
+  | 'Render'
+  | 'Slider'
+  | 'Rate'
+  | 'Divider'; // v2.7.2\u65B0\u589E
+

Divider schema \u8BF4\u660E

Divider\u7C7B\u578B\u7528\u4E8E\u5728schemas\u4E2D\u5360\u4F4D\uFF0C\u5C06\u4F1A\u6E32\u67D3\u6210\u4E00\u4E2A\u5206\u5272\u7EBF\uFF08\u59CB\u7EC8\u5360\u4E00\u6574\u884C\u7684\u7248\u9762\uFF09\uFF0C\u53EF\u4EE5\u7528\u4E8E\u8F83\u957F\u8868\u5355\u7684\u7248\u9762\u5206\u9694\u3002\u8BF7\u53EA\u5C06 Divider \u7C7B\u578B\u7684 schema \u5F53\u4F5C\u4E00\u4E2A\u5206\u5272\u7EBF\uFF0C\u800C\u4E0D\u662F\u4E00\u4E2A\u5E38\u89C4\u7684\u8868\u5355\u5B57\u6BB5\u3002

  • Divider\u4EC5\u5728showAdvancedButton\u4E3A false \u65F6\u624D\u4F1A\u663E\u793A\uFF08\u4E5F\u5C31\u662F\u8BF4\u5982\u679C\u542F\u7528\u4E86\u8868\u5355\u6536\u8D77\u548C\u5C55\u5F00\u529F\u80FD\uFF0CDivider\u5C06\u4E0D\u4F1A\u663E\u793A\uFF09
  • Divider \u4F7F\u7528schema\u4E2D\u7684label\u4EE5\u53CAhelpMessage\u6765\u6E32\u67D3\u5206\u5272\u7EBF\u4E2D\u7684\u63D0\u793A\u5185\u5BB9
  • Divider \u53EF\u4EE5\u4F7F\u7528componentProps\u6765\u8BBE\u7F6E\u9664type\u4E4B\u5916\u7684 props
  • Divider \u4E0D\u4F1A\u6E32\u67D3AFormItem\uFF0C\u56E0\u6B64schema\u4E2D\u9664label\u3001componentProps\u3001helpMessage\u3001helpComponentProps\u4EE5\u5916\u7684\u5C5E\u6027\u4E0D\u4F1A\u88AB\u7528\u5230

\u81EA\u884C\u6DFB\u52A0\u9700\u8981\u7684\u7EC4\u4EF6\u7C7B\u578B

\u5728 src/components/Form/src/componentMap.ts \u5185\uFF0C\u6DFB\u52A0\u9700\u8981\u7684\u7EC4\u4EF6\uFF0C\u5E76\u5728\u4E0A\u65B9 ComponentType \u6DFB\u52A0\u76F8\u5E94\u7684\u7C7B\u578B key

\u65B9\u5F0F 1

\u8FD9\u79CD\u5199\u6CD5\u9002\u7528\u4E0E\u9002\u7528\u9891\u7387\u8F83\u9AD8\u7684\u7EC4\u4EF6

componentMap.set('componentName', \u7EC4\u4EF6);
+
+// ComponentType
+export type ComponentType = xxxx | 'componentName';
+

\u65B9\u5F0F 2

\u4F7F\u7528 useComponentRegister \u8FDB\u884C\u6CE8\u518C

\u8FD9\u79CD\u5199\u6CD5\u53EA\u80FD\u5728\u5F53\u524D\u9875\u4F7F\u7528\uFF0C\u9875\u9762\u9500\u6BC1\u4E4B\u540E\u4F1A\u4ECE componentMap \u5220\u9664\u76F8\u5E94\u7684\u7EC4\u4EF6

import { useComponentRegister } from '@/components/form/index';
+
+import { StrengthMeter } from '@/components/strength-meter/index';
+
+useComponentRegister('StrengthMeter', StrengthMeter);
+

\u63D0\u793A

\u65B9\u5F0F 2 \u51FA\u73B0\u7684\u539F\u56E0\u662F\u4E3A\u4E86\u51CF\u5C11\u6253\u5305\u4F53\u79EF\uFF0C\u5982\u679C\u67D0\u4E2A\u7EC4\u4EF6\u4F53\u79EF\u5F88\u5927\uFF0C\u7528\u65B9\u5F0F 1 \u7684\u8BDD\u53EF\u80FD\u4F1A\u4F7F\u9996\u5C4F\u4F53\u79EF\u589E\u52A0

render

\u81EA\u5B9A\u4E49\u6E32\u67D3\u5185\u5BB9

<template>
+  <div class="m-4">
+    <BasicForm @register="register" @submit="handleSubmit" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, h } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { Input } from 'ant-design-vue';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '\u5B57\u6BB51',
+      colProps: {
+        span: 8,
+      },
+      rules: [{ required: true }],
+      render: ({ model, field }) => {
+        return h(Input, {
+          placeholder: '\u8BF7\u8F93\u5165',
+          value: model[field],
+          onChange: (e: ChangeEvent) => {
+            model[field] = e.target.value;
+          },
+        });
+      },
+    },
+    {
+      field: 'field2',
+      component: 'Input',
+      label: '\u5B57\u6BB52',
+      colProps: {
+        span: 8,
+      },
+      rules: [{ required: true }],
+      renderComponentContent: () => {
+        return {
+          suffix: () => 'suffix',
+        };
+      },
+    },
+  ];
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const { createMessage } = useMessage();
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+        setProps,
+      };
+    },
+  });
+</script>
+

slot

\u81EA\u5B9A\u4E49\u6E32\u67D3\u5185\u5BB9

\u63D0\u793A

\u4F7F\u7528\u63D2\u69FD\u81EA\u5B9A\u4E49\u8868\u5355\u57DF\u65F6\uFF0C\u8BF7\u6CE8\u610F antdv \u6709\u5173 FormItem \u7684\u76F8\u5173\u8BF4\u660E\u3002

<template>
+  <div class="m-4">
+    <BasicForm @register="register">
+      <template #customSlot="{ model, field }">
+        <a-input v-model:value="model[field]" />
+      </template>
+    </BasicForm>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'compatible-vue';
+  import { BasicForm, useForm } from '@/components/Form/index';
+  import { BasicModal } from '@/components/modal/index';
+  export default defineComponent({
+    name: 'FormDemo',
+    setup(props) {
+      const [register] = useForm({
+        labelWidth: 100,
+        actionColOptions: {
+          span: 24,
+        },
+        schemas: [
+          {
+            field: 'field1',
+            label: '\u5B57\u6BB51',
+            slot: 'customSlot',
+          },
+        ],
+      });
+      return {
+        register,
+      };
+    },
+  });
+</script>
+

ifShow/show/dynamicDisabled

\u81EA\u5B9A\u4E49\u663E\u793A/\u7981\u7528

<template>
+  <div class="m-4">
+    <BasicForm @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '\u5B57\u6BB51',
+      colProps: {
+        span: 8,
+      },
+      show: ({ values }) => {
+        return !!values.field5;
+      },
+    },
+    {
+      field: 'field2',
+      component: 'Input',
+      label: '\u5B57\u6BB52',
+      colProps: {
+        span: 8,
+      },
+      ifShow: ({ values }) => {
+        return !!values.field6;
+      },
+    },
+    {
+      field: 'field3',
+      component: 'DatePicker',
+      label: '\u5B57\u6BB53',
+      colProps: {
+        span: 8,
+      },
+      dynamicDisabled: ({ values }) => {
+        return !!values.field7;
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        setProps,
+      };
+    },
+  });
+</script>
+

\u89C1 antv form

Slots

\u540D\u79F0\u8BF4\u660E
formFooter\u8868\u5355\u5E95\u90E8\u533A\u57DF
formHeader\u8868\u5355\u9876\u90E8\u533A\u57DF
resetBefore\u91CD\u7F6E\u6309\u94AE\u524D
submitBefore\u63D0\u4EA4\u6309\u94AE\u524D
advanceBefore\u5C55\u5F00\u6309\u94AE\u524D
advanceAfter\u5C55\u5F00\u6309\u94AE\u540E

ApiSelect

\u8FDC\u7A0B\u4E0B\u62C9\u52A0\u8F7D\u7EC4\u4EF6\uFF0C\u8BE5\u7EC4\u4EF6\u53EF\u4EE5\u7528\u4E8E\u5B66\u4E60\u53C2\u8003\u5982\u4F55\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u96C6\u6210\u5230 Form \u7EC4\u4EF6\u5185\uFF0C\u5C06\u81EA\u5B9A\u4E49\u7EC4\u4EF6\u4EA4\u7531 Form \u53BB\u7BA1\u7406

Usage

const schemas: FormSchema[] = [
+  {
+    field: 'field',
+    component: 'ApiSelect',
+    label: '\u5B57\u6BB5',
+  },
+];
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
numberToStringbooleanfalse\u662F\u5426\u5C06number\u503C\u8F6C\u5316\u4E3Astring
api()=>Promise<{ label: string; value: string; disabled?: boolean }[]>-\u6570\u636E\u63A5\u53E3\uFF0C\u63A5\u53D7\u4E00\u4E2A Promise \u5BF9\u8C61
paramsobject-\u63A5\u53E3\u53C2\u6570\u3002\u6B64\u5C5E\u6027\u6539\u53D8\u65F6\u4F1A\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u63A5\u53E3\u6570\u636E
resultFieldstring-\u63A5\u53E3\u8FD4\u56DE\u7684\u5B57\u6BB5\uFF0C\u5982\u679C\u63A5\u53E3\u8FD4\u56DE\u6570\u7EC4\uFF0C\u53EF\u4EE5\u4E0D\u586B\u3002\u652F\u6301x.x.x\u683C\u5F0F
labelFieldstringlabel\u4E0B\u62C9\u6570\u7EC4\u9879\u5185label\u663E\u793A\u6587\u672C\u7684\u5B57\u6BB5\uFF0C\u652F\u6301x.x.x\u683C\u5F0F
valueFieldstringvalue\u4E0B\u62C9\u6570\u7EC4\u9879\u5185value\u5B9E\u9645\u503C\u7684\u5B57\u6BB5\uFF0C\u652F\u6301x.x.x\u683C\u5F0F
immediatebooleantrue\u662F\u5426\u7ACB\u5373\u8BF7\u6C42\u63A5\u53E3\uFF0C\u5426\u5219\u5C06\u5728\u7B2C\u4E00\u6B21\u70B9\u51FB\u65F6\u5019\u89E6\u53D1\u8BF7\u6C42

ApiTreeSelect

\u8FDC\u7A0B\u4E0B\u62C9\u6811\u52A0\u8F7D\u7EC4\u4EF6\uFF0C\u548CApiSelect\u7C7B\u4F3C\uFF0C2.6.1 \u4EE5\u4E0A\u7248\u672C

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
api()=>Promise<{ label: string; value: string; children?: any[] }[]>-\u6570\u636E\u63A5\u53E3\uFF0C\u63A5\u53D7\u4E00\u4E2A Promise \u5BF9\u8C61
paramsobject-\u63A5\u53E3\u53C2\u6570\u3002\u6B64\u5C5E\u6027\u6539\u53D8\u65F6\u4F1A\u81EA\u52A8\u91CD\u65B0\u52A0\u8F7D\u63A5\u53E3\u6570\u636E
resultFieldstring-\u63A5\u53E3\u8FD4\u56DE\u7684\u5B57\u6BB5\uFF0C\u5982\u679C\u63A5\u53E3\u8FD4\u56DE\u6570\u7EC4\uFF0C\u53EF\u4EE5\u4E0D\u586B\u3002\u652F\u6301x.x.x\u683C\u5F0F
immediatebooleantrue\u662F\u5426\u7ACB\u5373\u8BF7\u6C42\u63A5\u53E3\u3002

RadioButtonGroup

Radio Button \u98CE\u683C\u7684\u9009\u62E9\u6309\u94AE

Usage

const schemas: FormSchema[] = [
+  {
+    field: 'field',
+    component: 'RadioButtonGroup',
+    label: '\u5B57\u6BB5',
+  },
+];
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
options{ label: string; value: string; disabled?: boolean }[]-\u6570\u636E\u5B57\u6BB5
__VP_STATIC_END__`,133),e=[o];function c(l,u,r,i,k,d){return a(),s("div",null,e)}var h=n(p,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/components_functional_context-menu.md.8f53722d.js b/assets/components_functional_context-menu.md.8f53722d.js new file mode 100644 index 00000000..c22057c0 --- /dev/null +++ b/assets/components_functional_context-menu.md.8f53722d.js @@ -0,0 +1,41 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"ContextMenu","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"createContextMenu","slug":"createcontextmenu"}],"relativePath":"components/functional/context-menu.md","lastUpdated":1694442156381}',p={},o=t(`

ContextMenu

\u51FD\u6570\u5F0F\u521B\u5EFA\u53F3\u952E\u83DC\u5355\u7EC4\u4EF6\uFF0C \u53EA\u8981\u80FD\u62FF\u5230 dom \u7684 event \u5BF9\u8C61\u5C31\u80FD\u4E3A\u5176\u521B\u5EFA\u53F3\u952E\u83DC\u5355\u3002

Usage

<template>
+  <div>
+    <a-button type="primary" @contextmenu="handleContext">Right Click on me</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { useContextMenu } from '/@/hooks/web/useContextMenu';
+  import { CollapseContainer } from '/@/components/Container';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  export default defineComponent({
+    components: { CollapseContainer },
+    setup() {
+      const [createContextMenu] = useContextMenu();
+      const { createMessage } = useMessage();
+      function handleContext(e: MouseEvent) {
+        createContextMenu({
+          event: e,
+          items: [
+            {
+              label: 'New',
+              icon: 'ant-design:plus-outlined',
+              handler: () => {
+                createMessage.success('click new');
+              },
+            },
+            {
+              label: 'Open',
+              icon: 'ant-design:folder-open-filled',
+              handler: () => {
+                createMessage.success('click open');
+              },
+            },
+          ],
+        });
+      }
+      return { handleContext };
+    },
+  });
+</script>
+

createContextMenu

Options

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
eventEvent--\u9700\u8981\u521B\u5EFA\u7684 dom \u7684 Event \u5BF9\u8C61
itemsContextMenuItem[]--\u53F3\u952E\u83DC\u5355\u5217\u8868\uFF0CContextMenuItem\u89C1\u4E0B\u65B9\u8BF4\u660E

ContextMenuItem

\u5C5E\u6027\u7C7B\u578B\u8BF4\u660E
labelstring\u6587\u672C
iconstring\u56FE\u6807,\u53C2\u8003\u56FE\u6807\u7EC4\u4EF6
disabledboolean\u662F\u5426\u7981\u7528
handler()=>void\u70B9\u51FB\u89E6\u53D1\u51FD\u6570
`,9),e=[o];function c(u,l,k,i,r,d){return a(),s("div",null,e)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_functional_context-menu.md.8f53722d.lean.js b/assets/components_functional_context-menu.md.8f53722d.lean.js new file mode 100644 index 00000000..3ee6c334 --- /dev/null +++ b/assets/components_functional_context-menu.md.8f53722d.lean.js @@ -0,0 +1,41 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"ContextMenu","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"createContextMenu","slug":"createcontextmenu"}],"relativePath":"components/functional/context-menu.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

ContextMenu

\u51FD\u6570\u5F0F\u521B\u5EFA\u53F3\u952E\u83DC\u5355\u7EC4\u4EF6\uFF0C \u53EA\u8981\u80FD\u62FF\u5230 dom \u7684 event \u5BF9\u8C61\u5C31\u80FD\u4E3A\u5176\u521B\u5EFA\u53F3\u952E\u83DC\u5355\u3002

Usage

<template>
+  <div>
+    <a-button type="primary" @contextmenu="handleContext">Right Click on me</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { useContextMenu } from '/@/hooks/web/useContextMenu';
+  import { CollapseContainer } from '/@/components/Container';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  export default defineComponent({
+    components: { CollapseContainer },
+    setup() {
+      const [createContextMenu] = useContextMenu();
+      const { createMessage } = useMessage();
+      function handleContext(e: MouseEvent) {
+        createContextMenu({
+          event: e,
+          items: [
+            {
+              label: 'New',
+              icon: 'ant-design:plus-outlined',
+              handler: () => {
+                createMessage.success('click new');
+              },
+            },
+            {
+              label: 'Open',
+              icon: 'ant-design:folder-open-filled',
+              handler: () => {
+                createMessage.success('click open');
+              },
+            },
+          ],
+        });
+      }
+      return { handleContext };
+    },
+  });
+</script>
+

createContextMenu

Options

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
eventEvent--\u9700\u8981\u521B\u5EFA\u7684 dom \u7684 Event \u5BF9\u8C61
itemsContextMenuItem[]--\u53F3\u952E\u83DC\u5355\u5217\u8868\uFF0CContextMenuItem\u89C1\u4E0B\u65B9\u8BF4\u660E

ContextMenuItem

\u5C5E\u6027\u7C7B\u578B\u8BF4\u660E
labelstring\u6587\u672C
iconstring\u56FE\u6807,\u53C2\u8003\u56FE\u6807\u7EC4\u4EF6
disabledboolean\u662F\u5426\u7981\u7528
handler()=>void\u70B9\u51FB\u89E6\u53D1\u51FD\u6570
__VP_STATIC_END__`,9),e=[o];function c(u,l,k,i,r,d){return a(),s("div",null,e)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_functional_loading.md.0ad29673.js b/assets/components_functional_loading.md.0ad29673.js new file mode 100644 index 00000000..05bf3388 --- /dev/null +++ b/assets/components_functional_loading.md.0ad29673.js @@ -0,0 +1,54 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Loading","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"useLoading","slug":"useloading"},{"level":3,"title":"UseLoadingOptions","slug":"useloadingoptions"},{"level":3,"title":"LoadingProps","slug":"loadingprops"},{"level":3,"title":"\u8FD4\u56DE\u503C","slug":"\u8FD4\u56DE\u503C"}],"relativePath":"components/functional/loading.md","lastUpdated":1694442156381}',p={},o=t(`

Loading

Usage

<template>
+  <div class="p-5" ref="wrapEl" v-loading="loadingRef" loading-tip="\u52A0\u8F7D\u4E2D...">
+    <a-alert message="\u51FD\u6570\u65B9\u5F0F" />
+
+    <a-button class="my-4 mr-4" type="primary" @click="openFnFullLoading">\u5168\u5C4F Loading</a-button>
+    <a-button class="my-4" type="primary" @click="openFnWrapLoading">\u5BB9\u5668\u5185 Loading</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs, ref } from 'vue';
+  import { Loading, useLoading } from '/@/components/Loading';
+  export default defineComponent({
+    components: { Loading },
+    setup() {
+      const [openFullLoading, closeFullLoading] = useLoading({
+        tip: '\u52A0\u8F7D\u4E2D...',
+      });
+
+      const [openWrapLoading, closeWrapLoading] = useLoading({
+        target: wrapEl,
+        props: {
+          tip: '\u52A0\u8F7D\u4E2D...',
+          absolute: true,
+        },
+      });
+
+      function openFnFullLoading() {
+        openFullLoading();
+
+        setTimeout(() => {
+          closeFullLoading();
+        }, 2000);
+      }
+
+      function openFnWrapLoading() {
+        openWrapLoading();
+
+        setTimeout(() => {
+          closeWrapLoading();
+        }, 2000);
+      }
+
+      return {
+        openFnFullLoading,
+        openFnWrapLoading,
+        ...toRefs(compState),
+      };
+    },
+  });
+</script>
+

useLoading

\u4F7F\u7528

import { useLoading } from '/@/components/Loading';
+
+const [open, close, setTip] = useLoading(opt: Partial<LoadingProps> | Partial<UseLoadingOptions>);
+

UseLoadingOptions

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
targetHTMLElement or Ref<HTMLElement>--\u6302\u8F7D\u7684 dom \u8282\u70B9
propsLoadingProps--loading \u7EC4\u4EF6\u53C2\u6570

LoadingProps

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
tipstring--\u52A0\u8F7D\u6587\u672C
sizedefault, small , largedefault-\u5927\u5C0F
absolutebooleanfalse-\u7EDD\u5BF9\u5B9A\u4F4D\uFF0C\u4E3A false \u65F6\u53EF\u4EE5\u5168\u5C4F
loadingboolean--\u5F53\u524D\u52A0\u8F7D\u72B6\u6001
backgroundstring--\u80CC\u666F\u8272\uFF0C
theme'dark' or 'light'light-\u80CC\u666F\u8272\u4E3B\u9898 \uFF0C\u5F53\u80CC\u666F\u8272\u4E0D\u4E3A\u7A7A\u65F6\u4F7F\u7528\u80CC\u666F\u8272

\u8FD4\u56DE\u503C

open

\u6253\u5F00 loading

close

\u5173\u95ED loading

setTip

\u8BBE\u7F6E\u52A0\u5728\u63D0\u793A\u6587\u6848(v2.6.2\u4EE5\u4E0A\u7248\u672C)

`,17),e=[o];function c(u,l,i,k,r,d){return s(),a("div",null,e)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_functional_loading.md.0ad29673.lean.js b/assets/components_functional_loading.md.0ad29673.lean.js new file mode 100644 index 00000000..923a40f0 --- /dev/null +++ b/assets/components_functional_loading.md.0ad29673.lean.js @@ -0,0 +1,54 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Loading","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"useLoading","slug":"useloading"},{"level":3,"title":"UseLoadingOptions","slug":"useloadingoptions"},{"level":3,"title":"LoadingProps","slug":"loadingprops"},{"level":3,"title":"\u8FD4\u56DE\u503C","slug":"\u8FD4\u56DE\u503C"}],"relativePath":"components/functional/loading.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Loading

Usage

<template>
+  <div class="p-5" ref="wrapEl" v-loading="loadingRef" loading-tip="\u52A0\u8F7D\u4E2D...">
+    <a-alert message="\u51FD\u6570\u65B9\u5F0F" />
+
+    <a-button class="my-4 mr-4" type="primary" @click="openFnFullLoading">\u5168\u5C4F Loading</a-button>
+    <a-button class="my-4" type="primary" @click="openFnWrapLoading">\u5BB9\u5668\u5185 Loading</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs, ref } from 'vue';
+  import { Loading, useLoading } from '/@/components/Loading';
+  export default defineComponent({
+    components: { Loading },
+    setup() {
+      const [openFullLoading, closeFullLoading] = useLoading({
+        tip: '\u52A0\u8F7D\u4E2D...',
+      });
+
+      const [openWrapLoading, closeWrapLoading] = useLoading({
+        target: wrapEl,
+        props: {
+          tip: '\u52A0\u8F7D\u4E2D...',
+          absolute: true,
+        },
+      });
+
+      function openFnFullLoading() {
+        openFullLoading();
+
+        setTimeout(() => {
+          closeFullLoading();
+        }, 2000);
+      }
+
+      function openFnWrapLoading() {
+        openWrapLoading();
+
+        setTimeout(() => {
+          closeWrapLoading();
+        }, 2000);
+      }
+
+      return {
+        openFnFullLoading,
+        openFnWrapLoading,
+        ...toRefs(compState),
+      };
+    },
+  });
+</script>
+

useLoading

\u4F7F\u7528

import { useLoading } from '/@/components/Loading';
+
+const [open, close, setTip] = useLoading(opt: Partial<LoadingProps> | Partial<UseLoadingOptions>);
+

UseLoadingOptions

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
targetHTMLElement or Ref<HTMLElement>--\u6302\u8F7D\u7684 dom \u8282\u70B9
propsLoadingProps--loading \u7EC4\u4EF6\u53C2\u6570

LoadingProps

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
tipstring--\u52A0\u8F7D\u6587\u672C
sizedefault, small , largedefault-\u5927\u5C0F
absolutebooleanfalse-\u7EDD\u5BF9\u5B9A\u4F4D\uFF0C\u4E3A false \u65F6\u53EF\u4EE5\u5168\u5C4F
loadingboolean--\u5F53\u524D\u52A0\u8F7D\u72B6\u6001
backgroundstring--\u80CC\u666F\u8272\uFF0C
theme'dark' or 'light'light-\u80CC\u666F\u8272\u4E3B\u9898 \uFF0C\u5F53\u80CC\u666F\u8272\u4E0D\u4E3A\u7A7A\u65F6\u4F7F\u7528\u80CC\u666F\u8272

\u8FD4\u56DE\u503C

open

\u6253\u5F00 loading

close

\u5173\u95ED loading

setTip

\u8BBE\u7F6E\u52A0\u5728\u63D0\u793A\u6587\u6848(v2.6.2\u4EE5\u4E0A\u7248\u672C)

__VP_STATIC_END__`,17),e=[o];function c(u,l,i,k,r,d){return s(),a("div",null,e)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_functional_preview.md.ae69f3ce.js b/assets/components_functional_preview.md.ae69f3ce.js new file mode 100644 index 00000000..ac95e8ff --- /dev/null +++ b/assets/components_functional_preview.md.ae69f3ce.js @@ -0,0 +1,48 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Preview","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"createImgPreview","slug":"createimgpreview"},{"level":3,"title":"\u53C2\u6570/Options","slug":"\u53C2\u6570-options"},{"level":3,"title":"\u8FD4\u56DE\u503C/PreviewActions","slug":"\u8FD4\u56DE\u503C-previewactions"}],"relativePath":"components/functional/preview.md","lastUpdated":1694442156381}',p={},o=t(`

Preview

\u5C06\u56FE\u7247\u9884\u89C8\u7EC4\u4EF6\u7EC4\u4EF6\u51FD\u6570\u5316\u3002\u901A\u8FC7\u51FD\u6570\u65B9\u4FBF\u521B\u5EFA\u7EC4\u4EF6

Usage

<template>
+  <div class="p-4">
+    <Alert message="\u6709\u9884\u89C8\u56FE" type="info" />
+    <div class="flex justify-center mt-4">
+      <img :src="img" v-for="img in imgList" :key="img" class="mr-2" @click="handleClick(img)" />
+    </div>
+    <Alert message="\u65E0\u9884\u89C8\u56FE" type="info" />
+    <a-button @click="handlePreview" type="primary" class="mt-4">\u9884\u89C8\u56FE\u7247</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { createImgPreview } from '/@/components/Preview/index';
+  const imgList: string[] = [
+    'https://picsum.photos/id/66/346/216',
+    'https://picsum.photos/id/67/346/216',
+    'https://picsum.photos/id/68/346/216',
+  ];
+  export default defineComponent({
+    components: { Alert },
+    setup() {
+      function handleClick(img: string) {
+        createImgPreview({ imageList: [img] });
+      }
+
+      function handlePreview() {
+        createImgPreview({ imageList: imgList });
+      }
+      return { imgList, handleClick, handlePreview };
+    },
+  });
+</script>
+

createImgPreview

\u53C2\u6570/Options

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
imgListstring[]--\u56FE\u7247\u5217\u8868
indexnumber0-\u521D\u59CB\u9884\u89C8\u65F6\u7684\u56FE\u7247\u7D22\u5F15
scaleStepnumber--\u7F29\u653E\u6B65\u8FDB\u503C\uFF08\u6BCF\u6B21\u7F29\u653E\u7684\u5E45\u5EA6\uFF09\u3002\u9ED8\u8BA4\u4E3A\u81EA\u52A8\uFF08\u5F53\u524D\u7F29\u653E\u503C\u768410%\uFF09
defaultWidthnumber--\u9ED8\u8BA4\u5BBD\u5EA6\uFF08\u5355\u4F4Dpx\uFF09\u3002\u5F53\u63D0\u4F9B\u6B64\u503C\u65F6\uFF0C\u6240\u6709\u56FE\u7247\u521D\u59CB\u65F6\u90FD\u4F1A\u88AB\u7F29\u653E\u81F3\u6B64\u5BBD\u5EA6
maskClosablebooleanfalsetrue/false\u70B9\u51FB\u906E\u7F69\u65F6\u662F\u5426\u81EA\u52A8\u5173\u95ED\u9884\u89C8
rememberStatebooleanfalsetrue/false\u662F\u5426\u8BB0\u4F4F\u6BCF\u5F20\u56FE\u7247\u5404\u81EA\u7684\u7F29\u653E\u72B6\u6001
onImgLoad({ index: number, url: string, dom: HTMLImageElement }) => void--\u56FE\u7247\u52A0\u8F7D\u6210\u529F\u65F6\u7684\u56DE\u8C03\u51FD\u6570
onImgError({ index: number, url: string, dom: HTMLImageElement }) => void--\u56FE\u7247\u52A0\u8F7D\u5931\u8D25\u65F6\u7684\u56DE\u8C03\u51FD\u6570

\u8FD4\u56DE\u503C/PreviewActions

\u53EF\u7528\u4E8E\u63A7\u5236\u5F53\u524D\u9884\u89C8\u72B6\u6001

interface PreviewActions {
+  // \u91CD\u7F6E\u72B6\u6001
+  resume: () => void;
+  // \u5173\u95ED\u9884\u89C8
+  close: () => void;
+  // \u663E\u793A\u524D\u4E00\u5F20
+  prev: () => void;
+  // \u663E\u793A\u540E\u4E00\u5F20
+  next: () => void;
+  // \u8BBE\u7F6E\u7F29\u653E\u6BD4\u4F8B(\u9488\u5BF9\u5F53\u524D\u56FE\u7247)
+  setScale: (scale: number) => void;
+  // \u8BBE\u7F6E\u65CB\u8F6C\u89D2\u5EA6(\u9488\u5BF9\u5F53\u524D\u56FE\u7247)
+  setRotate: (rotate: number) => void;
+}
+
`,10),e=[o];function c(u,l,i,k,r,d){return s(),a("div",null,e)}var v=n(p,[["render",c]]);export{m as __pageData,v as default}; diff --git a/assets/components_functional_preview.md.ae69f3ce.lean.js b/assets/components_functional_preview.md.ae69f3ce.lean.js new file mode 100644 index 00000000..457222ea --- /dev/null +++ b/assets/components_functional_preview.md.ae69f3ce.lean.js @@ -0,0 +1,48 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Preview","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"createImgPreview","slug":"createimgpreview"},{"level":3,"title":"\u53C2\u6570/Options","slug":"\u53C2\u6570-options"},{"level":3,"title":"\u8FD4\u56DE\u503C/PreviewActions","slug":"\u8FD4\u56DE\u503C-previewactions"}],"relativePath":"components/functional/preview.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Preview

\u5C06\u56FE\u7247\u9884\u89C8\u7EC4\u4EF6\u7EC4\u4EF6\u51FD\u6570\u5316\u3002\u901A\u8FC7\u51FD\u6570\u65B9\u4FBF\u521B\u5EFA\u7EC4\u4EF6

Usage

<template>
+  <div class="p-4">
+    <Alert message="\u6709\u9884\u89C8\u56FE" type="info" />
+    <div class="flex justify-center mt-4">
+      <img :src="img" v-for="img in imgList" :key="img" class="mr-2" @click="handleClick(img)" />
+    </div>
+    <Alert message="\u65E0\u9884\u89C8\u56FE" type="info" />
+    <a-button @click="handlePreview" type="primary" class="mt-4">\u9884\u89C8\u56FE\u7247</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { createImgPreview } from '/@/components/Preview/index';
+  const imgList: string[] = [
+    'https://picsum.photos/id/66/346/216',
+    'https://picsum.photos/id/67/346/216',
+    'https://picsum.photos/id/68/346/216',
+  ];
+  export default defineComponent({
+    components: { Alert },
+    setup() {
+      function handleClick(img: string) {
+        createImgPreview({ imageList: [img] });
+      }
+
+      function handlePreview() {
+        createImgPreview({ imageList: imgList });
+      }
+      return { imgList, handleClick, handlePreview };
+    },
+  });
+</script>
+

createImgPreview

\u53C2\u6570/Options

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
imgListstring[]--\u56FE\u7247\u5217\u8868
indexnumber0-\u521D\u59CB\u9884\u89C8\u65F6\u7684\u56FE\u7247\u7D22\u5F15
scaleStepnumber--\u7F29\u653E\u6B65\u8FDB\u503C\uFF08\u6BCF\u6B21\u7F29\u653E\u7684\u5E45\u5EA6\uFF09\u3002\u9ED8\u8BA4\u4E3A\u81EA\u52A8\uFF08\u5F53\u524D\u7F29\u653E\u503C\u768410%\uFF09
defaultWidthnumber--\u9ED8\u8BA4\u5BBD\u5EA6\uFF08\u5355\u4F4Dpx\uFF09\u3002\u5F53\u63D0\u4F9B\u6B64\u503C\u65F6\uFF0C\u6240\u6709\u56FE\u7247\u521D\u59CB\u65F6\u90FD\u4F1A\u88AB\u7F29\u653E\u81F3\u6B64\u5BBD\u5EA6
maskClosablebooleanfalsetrue/false\u70B9\u51FB\u906E\u7F69\u65F6\u662F\u5426\u81EA\u52A8\u5173\u95ED\u9884\u89C8
rememberStatebooleanfalsetrue/false\u662F\u5426\u8BB0\u4F4F\u6BCF\u5F20\u56FE\u7247\u5404\u81EA\u7684\u7F29\u653E\u72B6\u6001
onImgLoad({ index: number, url: string, dom: HTMLImageElement }) => void--\u56FE\u7247\u52A0\u8F7D\u6210\u529F\u65F6\u7684\u56DE\u8C03\u51FD\u6570
onImgError({ index: number, url: string, dom: HTMLImageElement }) => void--\u56FE\u7247\u52A0\u8F7D\u5931\u8D25\u65F6\u7684\u56DE\u8C03\u51FD\u6570

\u8FD4\u56DE\u503C/PreviewActions

\u53EF\u7528\u4E8E\u63A7\u5236\u5F53\u524D\u9884\u89C8\u72B6\u6001

interface PreviewActions {
+  // \u91CD\u7F6E\u72B6\u6001
+  resume: () => void;
+  // \u5173\u95ED\u9884\u89C8
+  close: () => void;
+  // \u663E\u793A\u524D\u4E00\u5F20
+  prev: () => void;
+  // \u663E\u793A\u540E\u4E00\u5F20
+  next: () => void;
+  // \u8BBE\u7F6E\u7F29\u653E\u6BD4\u4F8B(\u9488\u5BF9\u5F53\u524D\u56FE\u7247)
+  setScale: (scale: number) => void;
+  // \u8BBE\u7F6E\u65CB\u8F6C\u89D2\u5EA6(\u9488\u5BF9\u5F53\u524D\u56FE\u7247)
+  setRotate: (rotate: number) => void;
+}
+
__VP_STATIC_END__`,10),e=[o];function c(u,l,i,k,r,d){return s(),a("div",null,e)}var v=n(p,[["render",c]]);export{m as __pageData,v as default}; diff --git a/assets/components_glob_button.md.0b640325.js b/assets/components_glob_button.md.0b640325.js new file mode 100644 index 00000000..1d0555a2 --- /dev/null +++ b/assets/components_glob_button.md.0b640325.js @@ -0,0 +1,6 @@ +import{_ as t,f as a,e as n,N as s}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"button \u6309\u94AE","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/glob/button.md","lastUpdated":1694442156381}',o={},e=s(`

button \u6309\u94AE

\u4E8C\u6B21\u5C01\u88C5\u6309\u94AE\u7EC4\u4EF6\uFF0C\u4E14\u4F7F\u7528\u76F8\u540C\u7684\u7EC4\u4EF6\u540D\u66FF\u6362\u5168\u5C40\u7684 a-button \u7EC4\u4EF6

TIP

  • \u6309\u94AE\u4E0D\u9700\u8981 import\uFF0C\u5DF2\u7ECF\u5168\u5C40\u6CE8\u518C\uFF0C\u76F4\u63A5\u4F7F\u7528 a-button \u6807\u7B7E\u5373\u53EF
  • \u5982\u679C\u662F Tsx \u6587\u4EF6\uFF0C\u9700\u8981\u624B\u52A8 import

Usage

<template>
+  <a-button color="success">\u6210\u529F\u6309\u94AE</a-button>
+  <a-button color="error">\u9519\u8BEF\u6309\u94AE</a-button>
+  <a-button color="warning">\u8B66\u544A\u6309\u94AE</a-button>
+</template>
+

Props

\u63D0\u793A

\u4FDD\u6301 anv design button \u7EC4\u4EF6 \u539F\u6709\u529F\u80FD\u7684\u60C5\u51B5\u4E0B\u6269\u5C55\u4EE5\u4E0B\u5C5E\u6027

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
color'error','warning', 'success'-\u6309\u94AE\u7684\u989C\u8272\u573A\u666F\u72B6\u6001\u989C\u8272\uFF0C
preIconstring-\u6309\u94AE\u6587\u672C\u524D\u56FE\u6807\uFF0C\u53C2\u8003 Icon \u7EC4\u4EF6
postIconstring-\u6309\u94AE\u6587\u672C\u540E\u56FE\u6807\uFF0C\u53C2\u8003 Icon \u7EC4\u4EF6
iconSizenumber14\u6309\u94AE\u56FE\u6807\u5927\u5C0F
`,8),p=[e];function c(l,u,r,d,i,k){return n(),a("div",null,p)}var _=t(o,[["render",c]]);export{h as __pageData,_ as default}; diff --git a/assets/components_glob_button.md.0b640325.lean.js b/assets/components_glob_button.md.0b640325.lean.js new file mode 100644 index 00000000..3b576ef6 --- /dev/null +++ b/assets/components_glob_button.md.0b640325.lean.js @@ -0,0 +1,6 @@ +import{_ as t,f as a,e as n,N as s}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"button \u6309\u94AE","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/glob/button.md","lastUpdated":1694442156381}',o={},e=s(`__VP_STATIC_START__

button \u6309\u94AE

\u4E8C\u6B21\u5C01\u88C5\u6309\u94AE\u7EC4\u4EF6\uFF0C\u4E14\u4F7F\u7528\u76F8\u540C\u7684\u7EC4\u4EF6\u540D\u66FF\u6362\u5168\u5C40\u7684 a-button \u7EC4\u4EF6

TIP

  • \u6309\u94AE\u4E0D\u9700\u8981 import\uFF0C\u5DF2\u7ECF\u5168\u5C40\u6CE8\u518C\uFF0C\u76F4\u63A5\u4F7F\u7528 a-button \u6807\u7B7E\u5373\u53EF
  • \u5982\u679C\u662F Tsx \u6587\u4EF6\uFF0C\u9700\u8981\u624B\u52A8 import

Usage

<template>
+  <a-button color="success">\u6210\u529F\u6309\u94AE</a-button>
+  <a-button color="error">\u9519\u8BEF\u6309\u94AE</a-button>
+  <a-button color="warning">\u8B66\u544A\u6309\u94AE</a-button>
+</template>
+

Props

\u63D0\u793A

\u4FDD\u6301 anv design button \u7EC4\u4EF6 \u539F\u6709\u529F\u80FD\u7684\u60C5\u51B5\u4E0B\u6269\u5C55\u4EE5\u4E0B\u5C5E\u6027

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
color'error','warning', 'success'-\u6309\u94AE\u7684\u989C\u8272\u573A\u666F\u72B6\u6001\u989C\u8272\uFF0C
preIconstring-\u6309\u94AE\u6587\u672C\u524D\u56FE\u6807\uFF0C\u53C2\u8003 Icon \u7EC4\u4EF6
postIconstring-\u6309\u94AE\u6587\u672C\u540E\u56FE\u6807\uFF0C\u53C2\u8003 Icon \u7EC4\u4EF6
iconSizenumber14\u6309\u94AE\u56FE\u6807\u5927\u5C0F
__VP_STATIC_END__`,8),p=[e];function c(l,u,r,d,i,k){return n(),a("div",null,p)}var _=t(o,[["render",c]]);export{h as __pageData,_ as default}; diff --git a/assets/components_icon.md.67a4f1a5.js b/assets/components_icon.md.67a4f1a5.js new file mode 100644 index 00000000..15899712 --- /dev/null +++ b/assets/components_icon.md.67a4f1a5.js @@ -0,0 +1,36 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"icon \u56FE\u6807\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Icon","slug":"icon"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":2,"title":"SvgIcon","slug":"svgicon"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"},{"level":2,"title":"IconPicker","slug":"iconpicker"},{"level":3,"title":"Usage","slug":"usage-2"},{"level":3,"title":"Props","slug":"props-2"}],"relativePath":"components/icon.md","lastUpdated":1694442156381}',p={},o=t(`

icon \u56FE\u6807\u7EC4\u4EF6

Icon

\u7528\u4E8E\u9879\u76EE\u5185\u7EC4\u4EF6\u7684\u5C55\u793A\uFF0C\u57FA\u672C\u652F\u6301\u6240\u6709\u56FE\u6807\u5E93\uFF08\u652F\u6301\u6309\u9700\u52A0\u8F7D\uFF0C\u53EA\u6253\u5305\u6240\u7528\u5230\u7684\u56FE\u6807\uFF09

icon \u7EC4\u4EF6\u4F4D\u4E8E src/components/Icon \u5185

TIP

icon \u7684\u503C\u53EF\u4EE5\u5728 Iconify \u6216 Netlify \u4E0A\u67E5\u8BE2

Usage

<template>
+  <Icon icon="gg:loadbar-doc"></Icon>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Icon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { Icon },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
iconstring-\u56FE\u6807\u540D
colorstring-\u56FE\u6807\u989C\u8272
sizenumber16\u56FE\u6807\u5927\u5C0F
prefixstring-\u56FE\u6807\u524D\u7F00

\u63D0\u793A

\u5982\u679C icon \u503C\u4EE5 |svg \u7ED3\u5C3E\uFF0C\u5219\u4F1A\u6E32\u67D3\u6210 SvgIcon \u7EC4\u4EF6

SvgIcon

\u7528\u4E8E\u4F7F\u7528\u9879\u76EE svg \u96EA\u78A7\u56FE

Usage

<template>
+  <div>
+    <SvgIcon name="test"> </SvgIcon>
+  </div>
+</template>
+<script>
+  import { SvgIcon } from '/@/components/Icon';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { SvgIcon },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
namestring-svg \u56FE\u6807\u540D
sizenumber16\u56FE\u6807\u5927\u5C0F

IconPicker

\u672C\u7EC4\u4EF6\u8BE6\u7EC6\u8BF4\u660E\u8BF7\u53C2\u9605\u56FE\u6807\u9009\u62E9\u5668

Usage

<template>
+  <div>
+    <IconPicker />
+  </div>
+</template>
+<script>
+  import { IconPicker } from '/@/components/Icon';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { IconPicker },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
widthstring100%\u5BBD\u5EA6
pageSizenumber140\u6BCF\u9875\u663E\u793A\u7684\u56FE\u6807\u6570
copybooleanfalse\u662F\u5426\u53EF\u4EE5\u590D\u5236
modestringiconify\u5907\u9009\u56FE\u6807\u6C60\uFF0C\u4E3A svg \u65F6\uFF0C\u4F1A\u8BFB\u53D6\u6240\u6709 svg sprite \u56FE\u6807\u3002\u8BE6\u89C1\u4E0B\u65B9\u8BF4\u660E

mode \u8BF4\u660E

  • mode\u4E3Aiconify\u65F6\uFF0C\u4F1A\u4F7F\u7528\u9884\u751F\u6210\u7684\u56FE\u6807\u96C6\u6570\u636E\u4F5C\u4E3A\u5907\u9009\u56FE\u6807\u6C60
  • mode\u4E3Asvg\u65F6\uFF0C\u4F1A\u4F7F\u7528 /src/assets/icons \u4E0B\u7684\u6240\u6709svg\u56FE\u6807\uFF08\u53EF\u5305\u542B\u4E00\u7EA7\u5B50\u76EE\u5F55\uFF09\u4F5C\u4E3A\u5907\u9009\u56FE\u6807\u6C60\uFF0C\u8BE6\u89C1vite-plugin-svg-icons\u3002
`,23),e=[o];function c(l,i,u,r,d,k){return a(),s("div",null,e)}var v=n(p,[["render",c]]);export{h as __pageData,v as default}; diff --git a/assets/components_icon.md.67a4f1a5.lean.js b/assets/components_icon.md.67a4f1a5.lean.js new file mode 100644 index 00000000..c7895c67 --- /dev/null +++ b/assets/components_icon.md.67a4f1a5.lean.js @@ -0,0 +1,36 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"icon \u56FE\u6807\u7EC4\u4EF6","description":"","frontmatter":{},"headers":[{"level":2,"title":"Icon","slug":"icon"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":2,"title":"SvgIcon","slug":"svgicon"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Props","slug":"props-1"},{"level":2,"title":"IconPicker","slug":"iconpicker"},{"level":3,"title":"Usage","slug":"usage-2"},{"level":3,"title":"Props","slug":"props-2"}],"relativePath":"components/icon.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

icon \u56FE\u6807\u7EC4\u4EF6

Icon

\u7528\u4E8E\u9879\u76EE\u5185\u7EC4\u4EF6\u7684\u5C55\u793A\uFF0C\u57FA\u672C\u652F\u6301\u6240\u6709\u56FE\u6807\u5E93\uFF08\u652F\u6301\u6309\u9700\u52A0\u8F7D\uFF0C\u53EA\u6253\u5305\u6240\u7528\u5230\u7684\u56FE\u6807\uFF09

icon \u7EC4\u4EF6\u4F4D\u4E8E src/components/Icon \u5185

TIP

icon \u7684\u503C\u53EF\u4EE5\u5728 Iconify \u6216 Netlify \u4E0A\u67E5\u8BE2

Usage

<template>
+  <Icon icon="gg:loadbar-doc"></Icon>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Icon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { Icon },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
iconstring-\u56FE\u6807\u540D
colorstring-\u56FE\u6807\u989C\u8272
sizenumber16\u56FE\u6807\u5927\u5C0F
prefixstring-\u56FE\u6807\u524D\u7F00

\u63D0\u793A

\u5982\u679C icon \u503C\u4EE5 |svg \u7ED3\u5C3E\uFF0C\u5219\u4F1A\u6E32\u67D3\u6210 SvgIcon \u7EC4\u4EF6

SvgIcon

\u7528\u4E8E\u4F7F\u7528\u9879\u76EE svg \u96EA\u78A7\u56FE

Usage

<template>
+  <div>
+    <SvgIcon name="test"> </SvgIcon>
+  </div>
+</template>
+<script>
+  import { SvgIcon } from '/@/components/Icon';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { SvgIcon },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
namestring-svg \u56FE\u6807\u540D
sizenumber16\u56FE\u6807\u5927\u5C0F

IconPicker

\u672C\u7EC4\u4EF6\u8BE6\u7EC6\u8BF4\u660E\u8BF7\u53C2\u9605\u56FE\u6807\u9009\u62E9\u5668

Usage

<template>
+  <div>
+    <IconPicker />
+  </div>
+</template>
+<script>
+  import { IconPicker } from '/@/components/Icon';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { IconPicker },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
widthstring100%\u5BBD\u5EA6
pageSizenumber140\u6BCF\u9875\u663E\u793A\u7684\u56FE\u6807\u6570
copybooleanfalse\u662F\u5426\u53EF\u4EE5\u590D\u5236
modestringiconify\u5907\u9009\u56FE\u6807\u6C60\uFF0C\u4E3A svg \u65F6\uFF0C\u4F1A\u8BFB\u53D6\u6240\u6709 svg sprite \u56FE\u6807\u3002\u8BE6\u89C1\u4E0B\u65B9\u8BF4\u660E

mode \u8BF4\u660E

  • mode\u4E3Aiconify\u65F6\uFF0C\u4F1A\u4F7F\u7528\u9884\u751F\u6210\u7684\u56FE\u6807\u96C6\u6570\u636E\u4F5C\u4E3A\u5907\u9009\u56FE\u6807\u6C60
  • mode\u4E3Asvg\u65F6\uFF0C\u4F1A\u4F7F\u7528 /src/assets/icons \u4E0B\u7684\u6240\u6709svg\u56FE\u6807\uFF08\u53EF\u5305\u542B\u4E00\u7EA7\u5B50\u76EE\u5F55\uFF09\u4F5C\u4E3A\u5907\u9009\u56FE\u6807\u6C60\uFF0C\u8BE6\u89C1vite-plugin-svg-icons\u3002
__VP_STATIC_END__`,23),e=[o];function c(l,i,u,r,d,k){return a(),s("div",null,e)}var v=n(p,[["render",c]]);export{h as __pageData,v as default}; diff --git a/assets/components_introduction.md.cf6b7dcd.js b/assets/components_introduction.md.cf6b7dcd.js new file mode 100644 index 00000000..76a6e3ed --- /dev/null +++ b/assets/components_introduction.md.cf6b7dcd.js @@ -0,0 +1,15 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const _='{"title":"\u524D\u8A00","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"}],"relativePath":"components/introduction.md","lastUpdated":1694442156381}',p={},o=t(`

\u524D\u8A00

\u6CE8\u610F\u4E8B\u9879

\u7EC4\u4EF6\u7684 defaultXXX \u5C5E\u6027\u4E0D\u8981\u4F7F\u7528\uFF0Cant-design-vue 2.2 \u7248\u672C\u4E4B\u540E\u5C06\u4F1A\u9010\u6B65\u79FB\u9664\u3002\u4E8C\u6B21\u5C01\u88C5\u7684\u7EC4\u4EF6\u4E5F\u4E0D\u517C\u5BB9 defaultXXX \u5C5E\u6027\u3002

Usage

\u8BE5\u9879\u76EE\u7684\u7EC4\u4EF6\u5927\u90E8\u5206\u6CA1\u6709\u8FDB\u884C\u5168\u5C40\u6CE8\u518C\u3002\u91C7\u7528\u4E86\u6309\u9700\u5F15\u5165\u6CE8\u518C\u65B9\u5F0F\uFF0C\u5982\u4E0B

<template>
+  <ConfigProvider>
+    <router-view />
+  </ConfigProvider>
+</template>
+
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { ConfigProvider } from 'ant-design-vue';
+  export default defineComponent({
+    name: 'App',
+    components: { ConfigProvider },
+  });
+</script>
+
`,5),e=[o];function c(l,u,i,r,k,d){return s(),a("div",null,e)}var f=n(p,[["render",c]]);export{_ as __pageData,f as default}; diff --git a/assets/components_introduction.md.cf6b7dcd.lean.js b/assets/components_introduction.md.cf6b7dcd.lean.js new file mode 100644 index 00000000..031759c4 --- /dev/null +++ b/assets/components_introduction.md.cf6b7dcd.lean.js @@ -0,0 +1,15 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const _='{"title":"\u524D\u8A00","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"}],"relativePath":"components/introduction.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

\u524D\u8A00

\u6CE8\u610F\u4E8B\u9879

\u7EC4\u4EF6\u7684 defaultXXX \u5C5E\u6027\u4E0D\u8981\u4F7F\u7528\uFF0Cant-design-vue 2.2 \u7248\u672C\u4E4B\u540E\u5C06\u4F1A\u9010\u6B65\u79FB\u9664\u3002\u4E8C\u6B21\u5C01\u88C5\u7684\u7EC4\u4EF6\u4E5F\u4E0D\u517C\u5BB9 defaultXXX \u5C5E\u6027\u3002

Usage

\u8BE5\u9879\u76EE\u7684\u7EC4\u4EF6\u5927\u90E8\u5206\u6CA1\u6709\u8FDB\u884C\u5168\u5C40\u6CE8\u518C\u3002\u91C7\u7528\u4E86\u6309\u9700\u5F15\u5165\u6CE8\u518C\u65B9\u5F0F\uFF0C\u5982\u4E0B

<template>
+  <ConfigProvider>
+    <router-view />
+  </ConfigProvider>
+</template>
+
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { ConfigProvider } from 'ant-design-vue';
+  export default defineComponent({
+    name: 'App',
+    components: { ConfigProvider },
+  });
+</script>
+
__VP_STATIC_END__`,5),e=[o];function c(l,u,i,r,k,d){return s(),a("div",null,e)}var f=n(p,[["render",c]]);export{_ as __pageData,f as default}; diff --git a/assets/components_json-preview.md.0491da4a.js b/assets/components_json-preview.md.0491da4a.js new file mode 100644 index 00000000..c27e2fb4 --- /dev/null +++ b/assets/components_json-preview.md.0491da4a.js @@ -0,0 +1,17 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"JsonPreview","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/json-preview.md","lastUpdated":1694442156381}',p={},e=t(`

JsonPreview

json \u6570\u636E\u9884\u89C8\u7EC4\u4EF6

Usage

<template>
+  <JsonPreview :data="data" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { JsonPreview } from '/@/components/CodeEditor';
+
+  export default defineComponent({
+    components: { JsonPreview },
+    setup() {
+      return {
+        data: {},
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
dataobject--\u9700\u8981\u9884\u89C8\u7684 Json \u6570\u636E
`,6),o=[e];function c(l,u,r,i,k,d){return s(),a("div",null,o)}var _=n(p,[["render",c]]);export{g as __pageData,_ as default}; diff --git a/assets/components_json-preview.md.0491da4a.lean.js b/assets/components_json-preview.md.0491da4a.lean.js new file mode 100644 index 00000000..abe5eed9 --- /dev/null +++ b/assets/components_json-preview.md.0491da4a.lean.js @@ -0,0 +1,17 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"JsonPreview","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/json-preview.md","lastUpdated":1694442156381}',p={},e=t(`__VP_STATIC_START__

JsonPreview

json \u6570\u636E\u9884\u89C8\u7EC4\u4EF6

Usage

<template>
+  <JsonPreview :data="data" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { JsonPreview } from '/@/components/CodeEditor';
+
+  export default defineComponent({
+    components: { JsonPreview },
+    setup() {
+      return {
+        data: {},
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
dataobject--\u9700\u8981\u9884\u89C8\u7684 Json \u6570\u636E
__VP_STATIC_END__`,6),o=[e];function c(l,u,r,i,k,d){return s(),a("div",null,o)}var _=n(p,[["render",c]]);export{g as __pageData,_ as default}; diff --git a/assets/components_lazy-container.md.8dd0276a.js b/assets/components_lazy-container.md.8dd0276a.js new file mode 100644 index 00000000..ee24bd1d --- /dev/null +++ b/assets/components_lazy-container.md.8dd0276a.js @@ -0,0 +1,43 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"LazyContainer","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/lazy-container.md","lastUpdated":1694442156381}',p={},o=t(`

LazyContainer

\u5EF6\u65F6\u52A0\u8F7D/\u61D2\u52A0\u8F7D\u7EC4\u4EF6, \u53EA\u5728\u7EC4\u4EF6\u53EF\u89C1\u6216\u8005\u5EF6\u8FDF\u4E00\u6BB5\u65F6\u95F4\u624D\u8FDB\u884C\u52A0\u8F7D

Usage

<template>
+  <div class="p-4 lazy-base-demo">
+    <div class="lazy-base-demo-wrap">
+      <h1>\u5411\u4E0B\u6EDA\u52A8</h1>
+      <LazyContainer @init="() => {}">
+        <TargetContent />
+        <template #skeleton>
+          <Skeleton :rows="10" />
+        </template>
+      </LazyContainer>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Skeleton } from 'ant-design-vue';
+  import TargetContent from './TargetContent.vue';
+  import { LazyContainer } from '/@/components/Container/index';
+  export default defineComponent({
+    components: { LazyContainer, TargetContent, Skeleton },
+  });
+</script>
+<style lang="less" scoped>
+  .lazy-base-demo {
+    &-wrap {
+      display: flex;
+      width: 50%;
+      height: 2000px;
+      margin: 20px auto;
+      text-align: center;
+      background: #fff;
+      justify-content: center;
+      flex-direction: column;
+      align-items: center;
+    }
+
+    h1 {
+      height: 1300px;
+      margin: 20px 0;
+    }
+  }
+</style>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
timeoutnumber--\u7B49\u5F85\u65F6\u95F4\uFF0C\u5982\u679C\u6307\u5B9A\u4E86\u65F6\u95F4\uFF0C\u4E0D\u8BBA\u53EF\u89C1\u4E0E\u5426\uFF0C\u5728\u6307\u5B9A\u65F6\u95F4\u4E4B\u540E\u81EA\u52A8\u52A0\u8F7D
viewportHTMLElement--\u7EC4\u4EF6\u6240\u5728\u7684\u89C6\u53E3\uFF0C\u5982\u679C\u7EC4\u4EF6\u662F\u5728\u9875\u9762\u5BB9\u5668\u5185\u6EDA\u52A8\uFF0C\u89C6\u53E3\u5C31\u662F\u8BE5\u5BB9\u5668
thresholdstring0px-\u9884\u52A0\u8F7D\u9608\u503C, css \u5355\u4F4D
direction'vertical', 'horizontal' , vertical-\u89C6\u53E3\u7684\u6EDA\u52A8\u65B9\u5411, vertical \u4EE3\u8868\u5782\u76F4\u65B9\u5411\uFF0Chorizontal \u4EE3\u8868\u6C34\u5E73\u65B9\u5411
tagstring'div-\u5305\u88F9\u7EC4\u4EF6\u7684\u5916\u5C42\u5BB9\u5668\u7684\u6807\u7B7E\u540D
transitionNamestring'lazy-container-transition \u52A8\u753B name
maxWaitingTimenumber'80-\u6700\u5927\u7B49\u5F85\u65F6\u95F4

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
init()=>void\u521D\u59CB\u5316\u4E4B\u540E

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4\u533A\u57DF
skeleton\u61D2\u52A0\u8F7D\u9AA8\u67B6\u5C4F
`,10),e=[o];function c(l,u,i,k,r,d){return s(),a("div",null,e)}var y=n(p,[["render",c]]);export{h as __pageData,y as default}; diff --git a/assets/components_lazy-container.md.8dd0276a.lean.js b/assets/components_lazy-container.md.8dd0276a.lean.js new file mode 100644 index 00000000..3e4e8337 --- /dev/null +++ b/assets/components_lazy-container.md.8dd0276a.lean.js @@ -0,0 +1,43 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"LazyContainer","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/lazy-container.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

LazyContainer

\u5EF6\u65F6\u52A0\u8F7D/\u61D2\u52A0\u8F7D\u7EC4\u4EF6, \u53EA\u5728\u7EC4\u4EF6\u53EF\u89C1\u6216\u8005\u5EF6\u8FDF\u4E00\u6BB5\u65F6\u95F4\u624D\u8FDB\u884C\u52A0\u8F7D

Usage

<template>
+  <div class="p-4 lazy-base-demo">
+    <div class="lazy-base-demo-wrap">
+      <h1>\u5411\u4E0B\u6EDA\u52A8</h1>
+      <LazyContainer @init="() => {}">
+        <TargetContent />
+        <template #skeleton>
+          <Skeleton :rows="10" />
+        </template>
+      </LazyContainer>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Skeleton } from 'ant-design-vue';
+  import TargetContent from './TargetContent.vue';
+  import { LazyContainer } from '/@/components/Container/index';
+  export default defineComponent({
+    components: { LazyContainer, TargetContent, Skeleton },
+  });
+</script>
+<style lang="less" scoped>
+  .lazy-base-demo {
+    &-wrap {
+      display: flex;
+      width: 50%;
+      height: 2000px;
+      margin: 20px auto;
+      text-align: center;
+      background: #fff;
+      justify-content: center;
+      flex-direction: column;
+      align-items: center;
+    }
+
+    h1 {
+      height: 1300px;
+      margin: 20px 0;
+    }
+  }
+</style>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
timeoutnumber--\u7B49\u5F85\u65F6\u95F4\uFF0C\u5982\u679C\u6307\u5B9A\u4E86\u65F6\u95F4\uFF0C\u4E0D\u8BBA\u53EF\u89C1\u4E0E\u5426\uFF0C\u5728\u6307\u5B9A\u65F6\u95F4\u4E4B\u540E\u81EA\u52A8\u52A0\u8F7D
viewportHTMLElement--\u7EC4\u4EF6\u6240\u5728\u7684\u89C6\u53E3\uFF0C\u5982\u679C\u7EC4\u4EF6\u662F\u5728\u9875\u9762\u5BB9\u5668\u5185\u6EDA\u52A8\uFF0C\u89C6\u53E3\u5C31\u662F\u8BE5\u5BB9\u5668
thresholdstring0px-\u9884\u52A0\u8F7D\u9608\u503C, css \u5355\u4F4D
direction'vertical', 'horizontal' , vertical-\u89C6\u53E3\u7684\u6EDA\u52A8\u65B9\u5411, vertical \u4EE3\u8868\u5782\u76F4\u65B9\u5411\uFF0Chorizontal \u4EE3\u8868\u6C34\u5E73\u65B9\u5411
tagstring'div-\u5305\u88F9\u7EC4\u4EF6\u7684\u5916\u5C42\u5BB9\u5668\u7684\u6807\u7B7E\u540D
transitionNamestring'lazy-container-transition \u52A8\u753B name
maxWaitingTimenumber'80-\u6700\u5927\u7B49\u5F85\u65F6\u95F4

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
init()=>void\u521D\u59CB\u5316\u4E4B\u540E

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4\u533A\u57DF
skeleton\u61D2\u52A0\u8F7D\u9AA8\u67B6\u5C4F
__VP_STATIC_END__`,10),e=[o];function c(l,u,i,k,r,d){return s(),a("div",null,e)}var y=n(p,[["render",c]]);export{h as __pageData,y as default}; diff --git a/assets/components_loading.md.5e89cf7f.js b/assets/components_loading.md.5e89cf7f.js new file mode 100644 index 00000000..e89fe178 --- /dev/null +++ b/assets/components_loading.md.5e89cf7f.js @@ -0,0 +1,44 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Loading","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"}],"relativePath":"components/loading.md","lastUpdated":1694442156381}',p={},o=t(`

Loading

Usage

<template>
+  <div class="p-5" ref="wrapEl" v-loading="loadingRef" loading-tip="\u52A0\u8F7D\u4E2D...">
+    <a-button class="my-4 mr-4" type="primary" @click="openCompFullLoading">\u5168\u5C4F Loading</a-button>
+    <a-button class="my-4" type="primary" @click="openCompAbsolute">\u5BB9\u5668\u5185 Loading</a-button>
+    <Loading :loading="loading" :absolute="absolute" :tip="tip" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs, ref } from 'vue';
+  import { Loading } from '/@/components/Loading';
+  export default defineComponent({
+    components: { Loading },
+    setup() {
+      const compState = reactive({
+        absolute: false,
+        loading: false,
+        tip: '\u52A0\u8F7D\u4E2D...',
+      });
+
+      function openLoading(absolute: boolean) {
+        compState.absolute = absolute;
+        compState.loading = true;
+        setTimeout(() => {
+          compState.loading = false;
+        }, 2000);
+      }
+
+      function openCompFullLoading() {
+        openLoading(false);
+      }
+
+      function openCompAbsolute() {
+        openLoading(true);
+      }
+
+      return {
+        openCompFullLoading,
+        openCompAbsolute,
+        ...toRefs(compState),
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
tipstring--\u52A0\u8F7D\u6587\u672C
sizedefault, small , largedefault-\u5927\u5C0F
absolutebooleanfalse-\u7EDD\u5BF9\u5B9A\u4F4D\uFF0C\u4E3A false \u65F6\u53EF\u4EE5\u5168\u5C4F
loadingboolean--\u5F53\u524D\u52A0\u8F7D\u72B6\u6001
backgroundstring--\u80CC\u666F\u8272
theme'dark' or 'light'light-\u80CC\u666F\u8272\u4E3B\u9898\uFF0C\u5F53\u80CC\u666F\u8272\u4E0D\u4E3A\u7A7A\u65F6\u4F7F\u7528\u80CC\u666F\u8272
`,5),e=[o];function c(u,l,k,i,r,d){return s(),a("div",null,e)}var f=n(p,[["render",c]]);export{m as __pageData,f as default}; diff --git a/assets/components_loading.md.5e89cf7f.lean.js b/assets/components_loading.md.5e89cf7f.lean.js new file mode 100644 index 00000000..84665afb --- /dev/null +++ b/assets/components_loading.md.5e89cf7f.lean.js @@ -0,0 +1,44 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Loading","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"}],"relativePath":"components/loading.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Loading

Usage

<template>
+  <div class="p-5" ref="wrapEl" v-loading="loadingRef" loading-tip="\u52A0\u8F7D\u4E2D...">
+    <a-button class="my-4 mr-4" type="primary" @click="openCompFullLoading">\u5168\u5C4F Loading</a-button>
+    <a-button class="my-4" type="primary" @click="openCompAbsolute">\u5BB9\u5668\u5185 Loading</a-button>
+    <Loading :loading="loading" :absolute="absolute" :tip="tip" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs, ref } from 'vue';
+  import { Loading } from '/@/components/Loading';
+  export default defineComponent({
+    components: { Loading },
+    setup() {
+      const compState = reactive({
+        absolute: false,
+        loading: false,
+        tip: '\u52A0\u8F7D\u4E2D...',
+      });
+
+      function openLoading(absolute: boolean) {
+        compState.absolute = absolute;
+        compState.loading = true;
+        setTimeout(() => {
+          compState.loading = false;
+        }, 2000);
+      }
+
+      function openCompFullLoading() {
+        openLoading(false);
+      }
+
+      function openCompAbsolute() {
+        openLoading(true);
+      }
+
+      return {
+        openCompFullLoading,
+        openCompAbsolute,
+        ...toRefs(compState),
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
tipstring--\u52A0\u8F7D\u6587\u672C
sizedefault, small , largedefault-\u5927\u5C0F
absolutebooleanfalse-\u7EDD\u5BF9\u5B9A\u4F4D\uFF0C\u4E3A false \u65F6\u53EF\u4EE5\u5168\u5C4F
loadingboolean--\u5F53\u524D\u52A0\u8F7D\u72B6\u6001
backgroundstring--\u80CC\u666F\u8272
theme'dark' or 'light'light-\u80CC\u666F\u8272\u4E3B\u9898\uFF0C\u5F53\u80CC\u666F\u8272\u4E0D\u4E3A\u7A7A\u65F6\u4F7F\u7528\u80CC\u666F\u8272
__VP_STATIC_END__`,5),e=[o];function c(u,l,k,i,r,d){return s(),a("div",null,e)}var f=n(p,[["render",c]]);export{m as __pageData,f as default}; diff --git a/assets/components_markdown.md.f6a08223.js b/assets/components_markdown.md.f6a08223.js new file mode 100644 index 00000000..28a2b62a --- /dev/null +++ b/assets/components_markdown.md.f6a08223.js @@ -0,0 +1,34 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Markdown","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":3,"title":"Methods","slug":"methods"}],"relativePath":"components/markdown.md","lastUpdated":1694442156381}',p={},o=t(`

Markdown

\u57FA\u4E8E Vditor \u7684 MarkDown \u7F16\u8F91\u5668

Usage

<template>
+  <div class="p-4">
+    <a-button @click="toggleTheme" class="mb-2" type="primary">\u9ED1\u6697\u4E3B\u9898</a-button>
+    <MarkDown v-model:value="value" ref="markDownRef" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { MarkDown, MarkDownActionType } from '/@/components/Markdown';
+  export default defineComponent({
+    components: { MarkDown },
+    setup() {
+      const markDownRef = ref<Nullable<MarkDownActionType>>(null);
+      const valueRef = ref(\`
+# title
+
+# content
+\`);
+
+      function toggleTheme() {
+        const markDown = unref(markDownRef);
+        if (!markDown) return;
+        const vditor = markDown.getVditor();
+        vditor.setTheme('dark');
+      }
+      return {
+        value: valueRef,
+        toggleTheme,
+        markDownRef,
+      };
+    },
+  });
+</script>
+

Props

TIP

\u9664\u4EE5\u4E0B\u4E24\u4E2A\u5916\uFF0Cprops \u8FD8\u53EF\u4EE5\u4F20\u5165 vidtor \u7684\u6240\u6709\u5C5E\u6027\u3002\u53EF\u7528 v-bind \u7EDF\u4E00\u7ED1\u5B9A

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
v-modelstring--\u53CC\u5411\u7ED1\u5B9A\u6587\u672C\u503C
heightnumber--\u9AD8\u5EA6

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
getVditorFunction\u83B7\u53D6 vditor \u5B9E\u4F8B
`,9),e=[o];function c(l,u,k,r,i,d){return s(),a("div",null,e)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_markdown.md.f6a08223.lean.js b/assets/components_markdown.md.f6a08223.lean.js new file mode 100644 index 00000000..e7e3200a --- /dev/null +++ b/assets/components_markdown.md.f6a08223.lean.js @@ -0,0 +1,34 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Markdown","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":3,"title":"Methods","slug":"methods"}],"relativePath":"components/markdown.md","lastUpdated":1694442156381}',p={},o=t(`__VP_STATIC_START__

Markdown

\u57FA\u4E8E Vditor \u7684 MarkDown \u7F16\u8F91\u5668

Usage

<template>
+  <div class="p-4">
+    <a-button @click="toggleTheme" class="mb-2" type="primary">\u9ED1\u6697\u4E3B\u9898</a-button>
+    <MarkDown v-model:value="value" ref="markDownRef" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { MarkDown, MarkDownActionType } from '/@/components/Markdown';
+  export default defineComponent({
+    components: { MarkDown },
+    setup() {
+      const markDownRef = ref<Nullable<MarkDownActionType>>(null);
+      const valueRef = ref(\`
+# title
+
+# content
+\`);
+
+      function toggleTheme() {
+        const markDown = unref(markDownRef);
+        if (!markDown) return;
+        const vditor = markDown.getVditor();
+        vditor.setTheme('dark');
+      }
+      return {
+        value: valueRef,
+        toggleTheme,
+        markDownRef,
+      };
+    },
+  });
+</script>
+

Props

TIP

\u9664\u4EE5\u4E0B\u4E24\u4E2A\u5916\uFF0Cprops \u8FD8\u53EF\u4EE5\u4F20\u5165 vidtor \u7684\u6240\u6709\u5C5E\u6027\u3002\u53EF\u7528 v-bind \u7EDF\u4E00\u7ED1\u5B9A

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
v-modelstring--\u53CC\u5411\u7ED1\u5B9A\u6587\u672C\u503C
heightnumber--\u9AD8\u5EA6

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
getVditorFunction\u83B7\u53D6 vditor \u5B9E\u4F8B
__VP_STATIC_END__`,9),e=[o];function c(l,u,k,r,i,d){return s(),a("div",null,e)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_modal.md.d871b84b.js b/assets/components_modal.md.d871b84b.js new file mode 100644 index 00000000..fc46f50e --- /dev/null +++ b/assets/components_modal.md.d871b84b.js @@ -0,0 +1,84 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Modal \u5F39\u7A97","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"useModal","slug":"usemodal"},{"level":2,"title":"useModalInner","slug":"usemodalinner"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/modal.md","lastUpdated":1694442156385}',p={},o=t(`

Modal \u5F39\u7A97

\u5BF9 antv \u7684 modal \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5\uFF0C\u6269\u5C55\u62D6\u62FD\uFF0C\u5168\u5C4F\uFF0C\u81EA\u9002\u5E94\u9AD8\u5EA6\u7B49\u529F\u80FD

\u4EE3\u7801\u8DEF\u5F84 src/components/Modal

Usage

\u7531\u4E8E\u5F39\u7A97\u5185\u4EE3\u7801\u4E00\u822C\u4F5C\u4E3A\u5355\u6587\u4EF6\u7EC4\u4EF6\u5B58\u5728\uFF0C\u4E5F\u63A8\u8350\u8FD9\u6837\u505A\uFF0C\u6240\u4EE5\u793A\u4F8B\u90FD\u4E3A\u5355\u6587\u4EF6\u7EC4\u4EF6\u5F62\u5F0F

TIP

\u6CE8\u610F v-bind="$attrs"\u8BB0\u5F97\u5199\uFF0C\u7528\u4E8E\u5C06\u5F39\u7A97\u7EC4\u4EF6\u7684 attribute \u4F20\u5165 BasicModal \u7EC4\u4EF6

// Modal.vue
+<template>
+  <BasicModal v-bind="$attrs" title="Modal Title" :helpMessage="['\u63D0\u793A1', '\u63D0\u793A2']">
+    Modal Info.
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicModal } from '/@/components/Modal';
+  export default defineComponent({
+    components: { BasicModal },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

\u9875\u9762\u5F15\u7528\u5F39\u7A97

// Page.vue
+<template>
+  <div class="px-10">
+    <Modal @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { useModal } from '/@/components/Modal';
+  import Modal from './Modal.vue';
+  export default defineComponent({
+    components: { Modal },
+    setup() {
+      const [register, { openModal }] = useModal();
+      return {
+        register,
+        openModal,
+      };
+    },
+  });
+</script>
+

useModal

\u7528\u4E8E\u5916\u90E8\u7EC4\u4EF6\u8C03\u7528

useModal \u7528\u4E8E\u64CD\u4F5C\u7EC4\u4EF6

const [register, { openModal, setModalProps }] = useModal();
+

register

register \u7528\u4E8E\u6CE8\u518C useModal\uFF0C\u5982\u679C\u9700\u8981\u4F7F\u7528 useModal \u63D0\u4F9B\u7684 api\uFF0C\u5FC5\u987B\u5C06 register \u4F20\u5165\u7EC4\u4EF6\u7684 onRegister\u3002

\u539F\u7406\u5176\u5B9E\u5F88\u7B80\u5355\uFF0C\u5C31\u662F vue \u7684\u7EC4\u4EF6\u5B50\u4F20\u7236\u901A\u4FE1\uFF0C\u5185\u90E8\u901A\u8FC7 emit("register"\uFF0Cinstance) \u5B9E\u73B0\u3002

\u540C\u65F6\u72EC\u7ACB\u51FA\u53BB\u7684\u7EC4\u4EF6\u9700\u8981\u5C06 attrs \u7ED1\u5B9A\u5230 BasicModal \u4E0A\u9762\u3002

<template>
+  <BasicModal v-bind="$attrs"></BasicModal>
+</template>
+

openModal

\u7528\u4E8E\u6253\u5F00/\u5173\u95ED\u5F39\u7A97

// true/false: \u6253\u5F00\u5173\u95ED\u5F39\u7A97
+// data: \u4F20\u9012\u5230\u5B50\u7EC4\u4EF6\u7684\u6570\u636E
+openModal(true, data);
+

closeModal

\u7528\u4E8E\u5173\u95ED\u5F39\u7A97

closeModal();
+

setModalProps

\u7528\u4E8E\u66F4\u6539 modal \u7684 props \u53C2\u6570\u56E0\u4E3A modal \u5185\u5BB9\u72EC\u7ACB\u6210\u7EC4\u4EF6\uFF0C\u5982\u679C\u5728\u5916\u90E8\u9875\u9762\u9700\u8981\u66F4\u6539 props \u53EF\u80FD\u6BD4\u8F83\u9EBB\u70E6\uFF0C\u6240\u4EE5\u63D0\u4F9B setModalProps \u65B9\u4FBF\u66F4\u6539\u5185\u90E8 modal \u7684 props

Props \u5185\u5BB9\u53EF\u4EE5\u89C1\u4E0B\u65B9

setModalProps(props);
+

useModalInner

\u7528\u4E8E\u72EC\u7ACB\u7684 Modal \u5185\u90E8\u8C03\u7528

Usage

<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="register"
+    title="Modal Title"
+    :helpMessage="['\u63D0\u793A1', '\u63D0\u793A2']"
+  >
+    <a-button type="primary" @click="closeModal" class="mr-2">\u4ECE\u5185\u90E8\u5173\u95ED\u5F39\u7A97</a-button>
+
+    <a-button type="primary" @click="setModalProps">\u4ECE\u5185\u90E8\u4FEE\u6539title</a-button>
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  export default defineComponent({
+    components: { BasicModal },
+    setup() {
+      const [register, { closeModal, setModalProps }] = useModalInner();
+      return {
+        register,
+        closeModal,
+        setModalProps: () => {
+          setModalProps({ title: 'Modal New Title' });
+        },
+      };
+    },
+  });
+</script>
+

useModalInner\u7528\u4E8E\u64CD\u4F5C\u72EC\u7ACB\u7EC4\u4EF6

const [register, { closeModal, setModalProps }] = useModalInner(callback);
+

callback

type: (data:any)=>void

\u56DE\u8C03\u51FD\u6570\u7528\u4E8E\u63A5\u6536 openModal \u7B2C\u4E8C\u4E2A\u53C2\u6570\u4F20\u9012\u7684\u503C

useModal((data: any) => {
+  console.log(data);
+});
+

closeModal

\u7528\u4E8E\u5173\u95ED\u5F39\u7A97

closeModal();
+

changeOkLoading

\u7528\u4E8E\u4FEE\u6539\u786E\u8BA4\u6309\u94AE\u7684 loading \u72B6\u6001

changeOkLoading(true);
+

changeLoading

\u7528\u4E8E\u4FEE\u6539 modal \u7684 loading \u72B6\u6001

// true or false
+changeLoading(true);
+

setModalProps

\u7528\u4E8E\u66F4\u6539 modal \u7684 props \u53C2\u6570\u56E0\u4E3A modal \u5185\u5BB9\u72EC\u7ACB\u6210\u7EC4\u4EF6\uFF0C\u5982\u679C\u5728\u5916\u90E8\u9875\u9762\u9700\u8981\u66F4\u6539 props \u53EF\u80FD\u6BD4\u8F83\u9EBB\u70E6\uFF0C\u6240\u4EE5\u63D0\u4F9B setModalProps \u65B9\u4FBF\u66F4\u6539\u5185\u90E8 modal \u7684 props

Props \u5185\u5BB9\u53EF\u4EE5\u89C1\u4E0B\u65B9

Props

TIP

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u7EC4\u4EF6\u5E93\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv modal

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
titlestring--modal \u6807\u9898
heightnumber--\u56FA\u5B9A modal \u7684\u9AD8\u5EA6
minHeightnumber--\u8BBE\u7F6E modal \u7684\u6700\u5C0F\u9AD8\u5EA6
draggablebooleantruetrue/false\u662F\u5426\u5F00\u542F\u62D6\u62FD
useWrapperbooleantruetrue/false\u662F\u5426\u5F00\u542F\u81EA\u9002\u5E94\u9AD8\u5EA6\uFF0C\u5F00\u542F\u540E\u4F1A\u8DDF\u968F\u5C4F\u5E55\u53D8\u5316\u81EA\u9002\u5E94\u5185\u5BB9\uFF0C\u5E76\u51FA\u73B0\u6EDA\u52A8\u6761
wrapperFooterOffsetnumber0-\u5F00\u542F\u662F\u9002\u5E94\u9AD8\u5EA6\u540E\uFF0C\u5982\u679C\u8D85\u8FC7\u5C4F\u5E55\u9AD8\u5EA6\uFF0C\u5E95\u90E8\u548C\u9876\u90E8\u4F1A\u4FDD\u6301\u4E00\u6837\u7684\u95F4\u8DDD\uFF0C\u8BE5\u53C2\u6570\u53EF\u4EE5\u7528\u6765\u7F29\u5C0F\u5E95\u90E8\u7684\u95F4\u8DDD
canFullscreenbooleantruetrue/false\u662F\u5426\u53EF\u4EE5\u8FDB\u884C\u5168\u5C4F
defaultFullscreenbooleanfalsetrue/false\u9ED8\u8BA4\u5168\u5C4F
loadingbooleanfalsetrue/falseloading \u72B6\u6001
loadingTipstring--loading \u6587\u672C
showCancelBtnbooleantruetrue/false\u663E\u793A\u5173\u95ED\u6309\u94AE
showOkBtnbooleantruetrue/false\u663E\u793A\u786E\u8BA4\u6309\u94AE
helpMessagestring , string[]--\u6807\u9898\u53F3\u4FA7\u63D0\u793A\u6587\u672C
centeredbooleanfalsetrue/false\u662F\u5426\u5C45\u4E2D\u5F39\u7A97
cancelTextstring'\u5173\u95ED'-\u5173\u95ED\u6309\u94AE\u6587\u672C
okTextstring'\u4FDD\u5B58'-\u786E\u8BA4\u6309\u94AE\u6587\u672C
closeFunc() => Promise<boolean>\u5173\u95ED\u51FD\u6570-\u5173\u95ED\u524D\u6267\u884C\uFF0C\u8FD4\u56DE true \u5219\u5173\u95ED\uFF0C\u5426\u5219\u4E0D\u5173\u95ED

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
okfunction(e)\u70B9\u51FB\u786E\u5B9A\u56DE\u8C03
cancelfunction(e)\u70B9\u51FB\u53D6\u6D88\u56DE\u8C03
visible-change(visible:boolean)=>{}\u6253\u5F00\u6216\u8005\u5173\u95ED\u89E6\u53D1

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4\u533A\u57DF
footer\u5E95\u90E8\u533A\u57DF(\u4F1A\u66FF\u6362\u6389\u9ED8\u8BA4\u7684\u6309\u94AE)
insertFooter\u5173\u95ED\u6309\u94AE\u7684\u5DE6\u8FB9(\u4E0D\u4F7F\u7528footer\u63D2\u69FD\u65F6\u6709\u6548)
centerFooter\u5173\u95ED\u6309\u94AE\u548C\u786E\u8BA4\u6309\u94AE\u7684\u4E2D\u95F4(\u4E0D\u4F7F\u7528footer\u63D2\u69FD\u65F6\u6709\u6548)
appendFooter\u786E\u8BA4\u6309\u94AE\u7684\u53F3\u8FB9(\u4E0D\u4F7F\u7528footer\u63D2\u69FD\u65F6\u6709\u6548)
`,57),e=[o];function c(l,u,d,i,r,k){return s(),a("div",null,e)}var h=n(p,[["render",c]]);export{m as __pageData,h as default}; diff --git a/assets/components_modal.md.d871b84b.lean.js b/assets/components_modal.md.d871b84b.lean.js new file mode 100644 index 00000000..5ce0c10a --- /dev/null +++ b/assets/components_modal.md.d871b84b.lean.js @@ -0,0 +1,84 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Modal \u5F39\u7A97","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"useModal","slug":"usemodal"},{"level":2,"title":"useModalInner","slug":"usemodalinner"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/modal.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

Modal \u5F39\u7A97

\u5BF9 antv \u7684 modal \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5\uFF0C\u6269\u5C55\u62D6\u62FD\uFF0C\u5168\u5C4F\uFF0C\u81EA\u9002\u5E94\u9AD8\u5EA6\u7B49\u529F\u80FD

\u4EE3\u7801\u8DEF\u5F84 src/components/Modal

Usage

\u7531\u4E8E\u5F39\u7A97\u5185\u4EE3\u7801\u4E00\u822C\u4F5C\u4E3A\u5355\u6587\u4EF6\u7EC4\u4EF6\u5B58\u5728\uFF0C\u4E5F\u63A8\u8350\u8FD9\u6837\u505A\uFF0C\u6240\u4EE5\u793A\u4F8B\u90FD\u4E3A\u5355\u6587\u4EF6\u7EC4\u4EF6\u5F62\u5F0F

TIP

\u6CE8\u610F v-bind="$attrs"\u8BB0\u5F97\u5199\uFF0C\u7528\u4E8E\u5C06\u5F39\u7A97\u7EC4\u4EF6\u7684 attribute \u4F20\u5165 BasicModal \u7EC4\u4EF6

// Modal.vue
+<template>
+  <BasicModal v-bind="$attrs" title="Modal Title" :helpMessage="['\u63D0\u793A1', '\u63D0\u793A2']">
+    Modal Info.
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicModal } from '/@/components/Modal';
+  export default defineComponent({
+    components: { BasicModal },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

\u9875\u9762\u5F15\u7528\u5F39\u7A97

// Page.vue
+<template>
+  <div class="px-10">
+    <Modal @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { useModal } from '/@/components/Modal';
+  import Modal from './Modal.vue';
+  export default defineComponent({
+    components: { Modal },
+    setup() {
+      const [register, { openModal }] = useModal();
+      return {
+        register,
+        openModal,
+      };
+    },
+  });
+</script>
+

useModal

\u7528\u4E8E\u5916\u90E8\u7EC4\u4EF6\u8C03\u7528

useModal \u7528\u4E8E\u64CD\u4F5C\u7EC4\u4EF6

const [register, { openModal, setModalProps }] = useModal();
+

register

register \u7528\u4E8E\u6CE8\u518C useModal\uFF0C\u5982\u679C\u9700\u8981\u4F7F\u7528 useModal \u63D0\u4F9B\u7684 api\uFF0C\u5FC5\u987B\u5C06 register \u4F20\u5165\u7EC4\u4EF6\u7684 onRegister\u3002

\u539F\u7406\u5176\u5B9E\u5F88\u7B80\u5355\uFF0C\u5C31\u662F vue \u7684\u7EC4\u4EF6\u5B50\u4F20\u7236\u901A\u4FE1\uFF0C\u5185\u90E8\u901A\u8FC7 emit("register"\uFF0Cinstance) \u5B9E\u73B0\u3002

\u540C\u65F6\u72EC\u7ACB\u51FA\u53BB\u7684\u7EC4\u4EF6\u9700\u8981\u5C06 attrs \u7ED1\u5B9A\u5230 BasicModal \u4E0A\u9762\u3002

<template>
+  <BasicModal v-bind="$attrs"></BasicModal>
+</template>
+

openModal

\u7528\u4E8E\u6253\u5F00/\u5173\u95ED\u5F39\u7A97

// true/false: \u6253\u5F00\u5173\u95ED\u5F39\u7A97
+// data: \u4F20\u9012\u5230\u5B50\u7EC4\u4EF6\u7684\u6570\u636E
+openModal(true, data);
+

closeModal

\u7528\u4E8E\u5173\u95ED\u5F39\u7A97

closeModal();
+

setModalProps

\u7528\u4E8E\u66F4\u6539 modal \u7684 props \u53C2\u6570\u56E0\u4E3A modal \u5185\u5BB9\u72EC\u7ACB\u6210\u7EC4\u4EF6\uFF0C\u5982\u679C\u5728\u5916\u90E8\u9875\u9762\u9700\u8981\u66F4\u6539 props \u53EF\u80FD\u6BD4\u8F83\u9EBB\u70E6\uFF0C\u6240\u4EE5\u63D0\u4F9B setModalProps \u65B9\u4FBF\u66F4\u6539\u5185\u90E8 modal \u7684 props

Props \u5185\u5BB9\u53EF\u4EE5\u89C1\u4E0B\u65B9

setModalProps(props);
+

useModalInner

\u7528\u4E8E\u72EC\u7ACB\u7684 Modal \u5185\u90E8\u8C03\u7528

Usage

<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="register"
+    title="Modal Title"
+    :helpMessage="['\u63D0\u793A1', '\u63D0\u793A2']"
+  >
+    <a-button type="primary" @click="closeModal" class="mr-2">\u4ECE\u5185\u90E8\u5173\u95ED\u5F39\u7A97</a-button>
+
+    <a-button type="primary" @click="setModalProps">\u4ECE\u5185\u90E8\u4FEE\u6539title</a-button>
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  export default defineComponent({
+    components: { BasicModal },
+    setup() {
+      const [register, { closeModal, setModalProps }] = useModalInner();
+      return {
+        register,
+        closeModal,
+        setModalProps: () => {
+          setModalProps({ title: 'Modal New Title' });
+        },
+      };
+    },
+  });
+</script>
+

useModalInner\u7528\u4E8E\u64CD\u4F5C\u72EC\u7ACB\u7EC4\u4EF6

const [register, { closeModal, setModalProps }] = useModalInner(callback);
+

callback

type: (data:any)=>void

\u56DE\u8C03\u51FD\u6570\u7528\u4E8E\u63A5\u6536 openModal \u7B2C\u4E8C\u4E2A\u53C2\u6570\u4F20\u9012\u7684\u503C

useModal((data: any) => {
+  console.log(data);
+});
+

closeModal

\u7528\u4E8E\u5173\u95ED\u5F39\u7A97

closeModal();
+

changeOkLoading

\u7528\u4E8E\u4FEE\u6539\u786E\u8BA4\u6309\u94AE\u7684 loading \u72B6\u6001

changeOkLoading(true);
+

changeLoading

\u7528\u4E8E\u4FEE\u6539 modal \u7684 loading \u72B6\u6001

// true or false
+changeLoading(true);
+

setModalProps

\u7528\u4E8E\u66F4\u6539 modal \u7684 props \u53C2\u6570\u56E0\u4E3A modal \u5185\u5BB9\u72EC\u7ACB\u6210\u7EC4\u4EF6\uFF0C\u5982\u679C\u5728\u5916\u90E8\u9875\u9762\u9700\u8981\u66F4\u6539 props \u53EF\u80FD\u6BD4\u8F83\u9EBB\u70E6\uFF0C\u6240\u4EE5\u63D0\u4F9B setModalProps \u65B9\u4FBF\u66F4\u6539\u5185\u90E8 modal \u7684 props

Props \u5185\u5BB9\u53EF\u4EE5\u89C1\u4E0B\u65B9

Props

TIP

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u7EC4\u4EF6\u5E93\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv modal

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
titlestring--modal \u6807\u9898
heightnumber--\u56FA\u5B9A modal \u7684\u9AD8\u5EA6
minHeightnumber--\u8BBE\u7F6E modal \u7684\u6700\u5C0F\u9AD8\u5EA6
draggablebooleantruetrue/false\u662F\u5426\u5F00\u542F\u62D6\u62FD
useWrapperbooleantruetrue/false\u662F\u5426\u5F00\u542F\u81EA\u9002\u5E94\u9AD8\u5EA6\uFF0C\u5F00\u542F\u540E\u4F1A\u8DDF\u968F\u5C4F\u5E55\u53D8\u5316\u81EA\u9002\u5E94\u5185\u5BB9\uFF0C\u5E76\u51FA\u73B0\u6EDA\u52A8\u6761
wrapperFooterOffsetnumber0-\u5F00\u542F\u662F\u9002\u5E94\u9AD8\u5EA6\u540E\uFF0C\u5982\u679C\u8D85\u8FC7\u5C4F\u5E55\u9AD8\u5EA6\uFF0C\u5E95\u90E8\u548C\u9876\u90E8\u4F1A\u4FDD\u6301\u4E00\u6837\u7684\u95F4\u8DDD\uFF0C\u8BE5\u53C2\u6570\u53EF\u4EE5\u7528\u6765\u7F29\u5C0F\u5E95\u90E8\u7684\u95F4\u8DDD
canFullscreenbooleantruetrue/false\u662F\u5426\u53EF\u4EE5\u8FDB\u884C\u5168\u5C4F
defaultFullscreenbooleanfalsetrue/false\u9ED8\u8BA4\u5168\u5C4F
loadingbooleanfalsetrue/falseloading \u72B6\u6001
loadingTipstring--loading \u6587\u672C
showCancelBtnbooleantruetrue/false\u663E\u793A\u5173\u95ED\u6309\u94AE
showOkBtnbooleantruetrue/false\u663E\u793A\u786E\u8BA4\u6309\u94AE
helpMessagestring , string[]--\u6807\u9898\u53F3\u4FA7\u63D0\u793A\u6587\u672C
centeredbooleanfalsetrue/false\u662F\u5426\u5C45\u4E2D\u5F39\u7A97
cancelTextstring'\u5173\u95ED'-\u5173\u95ED\u6309\u94AE\u6587\u672C
okTextstring'\u4FDD\u5B58'-\u786E\u8BA4\u6309\u94AE\u6587\u672C
closeFunc() => Promise<boolean>\u5173\u95ED\u51FD\u6570-\u5173\u95ED\u524D\u6267\u884C\uFF0C\u8FD4\u56DE true \u5219\u5173\u95ED\uFF0C\u5426\u5219\u4E0D\u5173\u95ED

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
okfunction(e)\u70B9\u51FB\u786E\u5B9A\u56DE\u8C03
cancelfunction(e)\u70B9\u51FB\u53D6\u6D88\u56DE\u8C03
visible-change(visible:boolean)=>{}\u6253\u5F00\u6216\u8005\u5173\u95ED\u89E6\u53D1

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4\u533A\u57DF
footer\u5E95\u90E8\u533A\u57DF(\u4F1A\u66FF\u6362\u6389\u9ED8\u8BA4\u7684\u6309\u94AE)
insertFooter\u5173\u95ED\u6309\u94AE\u7684\u5DE6\u8FB9(\u4E0D\u4F7F\u7528footer\u63D2\u69FD\u65F6\u6709\u6548)
centerFooter\u5173\u95ED\u6309\u94AE\u548C\u786E\u8BA4\u6309\u94AE\u7684\u4E2D\u95F4(\u4E0D\u4F7F\u7528footer\u63D2\u69FD\u65F6\u6709\u6548)
appendFooter\u786E\u8BA4\u6309\u94AE\u7684\u53F3\u8FB9(\u4E0D\u4F7F\u7528footer\u63D2\u69FD\u65F6\u6709\u6548)
__VP_STATIC_END__`,57),e=[o];function c(l,u,d,i,r,k){return s(),a("div",null,e)}var h=n(p,[["render",c]]);export{m as __pageData,h as default}; diff --git a/assets/components_page.md.fb8744b0.js b/assets/components_page.md.fb8744b0.js new file mode 100644 index 00000000..59e5a8b5 --- /dev/null +++ b/assets/components_page.md.fb8744b0.js @@ -0,0 +1,37 @@ +import{_ as a,f as n,e as t,N as s}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Page","description":"","frontmatter":{},"headers":[{"level":2,"title":"PageWrapper","slug":"pagewrapper"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":3,"title":"Slots","slug":"slots"},{"level":2,"title":"PageFooter","slug":"pagefooter"},{"level":3,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":3,"title":"Slots","slug":"slots-1"}],"relativePath":"components/page.md","lastUpdated":1694442156385}',p={},e=s(`

Page

\u9875\u9762\u76F8\u5173\u7EC4\u4EF6

PageWrapper

\u7528\u4E8E\u5305\u88F9\u9875\u9762\u7EC4\u4EF6

Usage

<template>
+  <div>
+    <PageWrapper>
+      <template #left>left</template>
+      <template #right>right</template>
+    </PageWrapper>
+  </div>
+</template>
+<script>
+  import { PageWrapper } from '/@/components/Page';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { PageWrapper },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
titlestring-pageHeader title
dense\u662F\u5426\u7F29\u5C0F\u4E3B\u4F53\u533A\u57DFfalse\u4E3A true \u5C06\u4F1A\u53D6\u6D88 padding/margin
contentstring-pageHeader Content \u5185\u5BB9
contentStyleobject-\u4E3B\u4F53\u533A\u57DF\u6837\u5F0F
contentClassstring-\u4E3B\u4F53\u533A\u57DF class
contentBackgroundboolean-\u4E3B\u4F53\u533A\u57DF\u80CC\u666F
contentFullHeightbooleanfalse\u4E3B\u4F53\u533A\u57DF\u662F\u5426\u5360\u6EE1\u6574\u4E2A\u5C4F\u5E55\u9AD8\u5EA6
fixedHeightbooleanfalse\u56FA\u5B9A\u4E3B\u4F53\u533A\u57DF\u9AD8\u5EA6

Slots

pageHeader \u7684 slot \u90FD\u652F\u6301

\u540D\u79F0\u8BF4\u660E
leftFooterPageFooter \u5DE6\u4FA7\u533A\u57DF
rightFooterPageFooter \u53F3\u4FA7\u533A\u57DF
headerContentpageHeader \u4E3B\u4F53\u5185\u5BB9
default\u4E3B\u4F53\u533A\u57DF

\u7528\u4E8E\u9875\u9762\u5E95\u90E8\u5DE5\u5177\u680F

\u4F7F\u7528

<template>
+  <div>
+    <PageFooter>
+      <template #left>left</template>
+      <template #right>right</template>
+    </PageFooter>
+  </div>
+</template>
+<script>
+  import { PageFooter } from '/@/components/Page';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { PageFooter },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

Slots

\u540D\u79F0\u8BF4\u660E
left\u5DE6\u4FA7\u533A\u57DF
right\u53F3\u4FA7\u533A\u57DF
`,17),o=[e];function c(l,u,r,d,k,i){return t(),n("div",null,o)}var f=a(p,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/components_page.md.fb8744b0.lean.js b/assets/components_page.md.fb8744b0.lean.js new file mode 100644 index 00000000..635cd002 --- /dev/null +++ b/assets/components_page.md.fb8744b0.lean.js @@ -0,0 +1,37 @@ +import{_ as a,f as n,e as t,N as s}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Page","description":"","frontmatter":{},"headers":[{"level":2,"title":"PageWrapper","slug":"pagewrapper"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":3,"title":"Slots","slug":"slots"},{"level":2,"title":"PageFooter","slug":"pagefooter"},{"level":3,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":3,"title":"Slots","slug":"slots-1"}],"relativePath":"components/page.md","lastUpdated":1694442156385}',p={},e=s(`__VP_STATIC_START__

Page

\u9875\u9762\u76F8\u5173\u7EC4\u4EF6

PageWrapper

\u7528\u4E8E\u5305\u88F9\u9875\u9762\u7EC4\u4EF6

Usage

<template>
+  <div>
+    <PageWrapper>
+      <template #left>left</template>
+      <template #right>right</template>
+    </PageWrapper>
+  </div>
+</template>
+<script>
+  import { PageWrapper } from '/@/components/Page';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { PageWrapper },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
titlestring-pageHeader title
dense\u662F\u5426\u7F29\u5C0F\u4E3B\u4F53\u533A\u57DFfalse\u4E3A true \u5C06\u4F1A\u53D6\u6D88 padding/margin
contentstring-pageHeader Content \u5185\u5BB9
contentStyleobject-\u4E3B\u4F53\u533A\u57DF\u6837\u5F0F
contentClassstring-\u4E3B\u4F53\u533A\u57DF class
contentBackgroundboolean-\u4E3B\u4F53\u533A\u57DF\u80CC\u666F
contentFullHeightbooleanfalse\u4E3B\u4F53\u533A\u57DF\u662F\u5426\u5360\u6EE1\u6574\u4E2A\u5C4F\u5E55\u9AD8\u5EA6
fixedHeightbooleanfalse\u56FA\u5B9A\u4E3B\u4F53\u533A\u57DF\u9AD8\u5EA6

Slots

pageHeader \u7684 slot \u90FD\u652F\u6301

\u540D\u79F0\u8BF4\u660E
leftFooterPageFooter \u5DE6\u4FA7\u533A\u57DF
rightFooterPageFooter \u53F3\u4FA7\u533A\u57DF
headerContentpageHeader \u4E3B\u4F53\u5185\u5BB9
default\u4E3B\u4F53\u533A\u57DF

\u7528\u4E8E\u9875\u9762\u5E95\u90E8\u5DE5\u5177\u680F

\u4F7F\u7528

<template>
+  <div>
+    <PageFooter>
+      <template #left>left</template>
+      <template #right>right</template>
+    </PageFooter>
+  </div>
+</template>
+<script>
+  import { PageFooter } from '/@/components/Page';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { PageFooter },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

Slots

\u540D\u79F0\u8BF4\u660E
left\u5DE6\u4FA7\u533A\u57DF
right\u53F3\u4FA7\u533A\u57DF
__VP_STATIC_END__`,17),o=[e];function c(l,u,r,d,k,i){return t(),n("div",null,o)}var f=a(p,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/components_pop-confirm-button.md.5f2fe256.js b/assets/components_pop-confirm-button.md.5f2fe256.js new file mode 100644 index 00000000..52fb54b6 --- /dev/null +++ b/assets/components_pop-confirm-button.md.5f2fe256.js @@ -0,0 +1,12 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"PopConfirmButton \u6309\u94AE","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/pop-confirm-button.md","lastUpdated":1694442156385}',p={},o=t(`

PopConfirmButton \u6309\u94AE

\u5E26\u6709 PopConfirm \u4E0B\u62C9\u83DC\u5355\u529F\u80FD\u7684\u6309\u94AE

Usage

<template>
+  <PopConfirmButton>\u6309\u94AE\u6587\u672C</PopConfirmButton>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { PopConfirmButton } from '/@/components/Button';
+  export default defineComponent({
+    components: { PopConfirmButton },
+  });
+</script>
+

Props

\u63D0\u793A

\u4FDD\u6301 anv design popconfirm \u7EC4\u4EF6 \u539F\u6709\u529F\u80FD\u7684\u60C5\u51B5\u4E0B\u6269\u5C55\u4EE5\u4E0B\u5C5E\u6027

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
enablebooleantrue\u662F\u5426\u542F\u7528\u4E0B\u62C9\u83DC\u5355\uFF0C\u4E3A false \u5219\u663E\u793A\u9ED8\u8BA4\u6309\u94AE
`,7),e=[o];function c(l,r,u,i,k,d){return s(),a("div",null,e)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_pop-confirm-button.md.5f2fe256.lean.js b/assets/components_pop-confirm-button.md.5f2fe256.lean.js new file mode 100644 index 00000000..05f6f908 --- /dev/null +++ b/assets/components_pop-confirm-button.md.5f2fe256.lean.js @@ -0,0 +1,12 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"PopConfirmButton \u6309\u94AE","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/pop-confirm-button.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

PopConfirmButton \u6309\u94AE

\u5E26\u6709 PopConfirm \u4E0B\u62C9\u83DC\u5355\u529F\u80FD\u7684\u6309\u94AE

Usage

<template>
+  <PopConfirmButton>\u6309\u94AE\u6587\u672C</PopConfirmButton>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { PopConfirmButton } from '/@/components/Button';
+  export default defineComponent({
+    components: { PopConfirmButton },
+  });
+</script>
+

Props

\u63D0\u793A

\u4FDD\u6301 anv design popconfirm \u7EC4\u4EF6 \u539F\u6709\u529F\u80FD\u7684\u60C5\u51B5\u4E0B\u6269\u5C55\u4EE5\u4E0B\u5C5E\u6027

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
enablebooleantrue\u662F\u5426\u542F\u7528\u4E0B\u62C9\u83DC\u5355\uFF0C\u4E3A false \u5219\u663E\u793A\u9ED8\u8BA4\u6309\u94AE
__VP_STATIC_END__`,7),e=[o];function c(l,r,u,i,k,d){return s(),a("div",null,e)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_qrcode.md.f0fe898e.js b/assets/components_qrcode.md.f0fe898e.js new file mode 100644 index 00000000..f998e1d3 --- /dev/null +++ b/assets/components_qrcode.md.f0fe898e.js @@ -0,0 +1,92 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"QrCode","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Methods","slug":"methods"},{"level":2,"title":"\u4E8B\u4EF6","slug":"\u4E8B\u4EF6"}],"relativePath":"components/qrcode.md","lastUpdated":1694442156385}',p={},o=t(`

QrCode

\u7528\u4E8E\u751F\u6210\u4E8C\u7EF4\u7801\u7684\u7EC4\u4EF6

Usage

<template>
+  <QrCode :value="qrCodeUrl" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { QrCode, QrCodeActionType } from '/@/components/Qrcode/index';
+  import LogoImg from '/@/assets/images/logo.png';
+  const qrCodeUrl = 'https://www.vvbin.cn';
+  export default defineComponent({
+    components: { QrCode },
+    setup() {
+      const qrRef = ref<Nullable<QrCodeActionType>>(null);
+      function download() {
+        const qrEl = unref(qrRef);
+        if (!qrEl) return;
+        qrEl.download('\u6587\u4EF6\u540D');
+      }
+      return {
+        qrCodeUrl,
+        LogoImg,
+        download,
+        qrRef,
+      };
+    },
+  });
+</script>
+<style scoped>
+  .qrcode-demo-item {
+    width: 30%;
+    margin-right: 1%;
+  }
+</style>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valuestring--\u4E8C\u7EF4\u7801\u5730\u5740
optionsQRCodeRenderersOptions--\u4E8C\u7EF4\u7801\u914D\u7F6E ,\u89C1 QRCodeRenderersOptions
widthnumber2-\u5BBD\u5EA6
logostring\uFF5CLogoType--\u4E2D\u95F4 logo \u914D\u7F6E\uFF0C\u89C1 LogoType
tag\u6E32\u67D3\u6807\u7B7Ecanvascanvas | imgimg \u4E0D\u652F\u6301\u5185\u5D4C logo

QRCodeRenderersOptions

/**
+ * \u5B9A\u4E49margin\u7684\u5BBD\u5EA6\u3002.
+ * Default: 4
+ */
+margin?: number;
+/**
+ * \u6BD4\u4F8B\u56E0\u5B50\u3002\u503C1\u8868\u793A\u6BCF\u4E2A\u6A21\u57571\u50CF\u7D20\uFF08\u9ED1\u70B9\uFF09\u3002
+ * Default: 4
+ */
+scale?: number;
+/**
+ * \u4E3A\u8F93\u51FA\u56FE\u50CF\u5F3A\u5236\u6307\u5B9A\u5BBD\u5EA6\u3002
+ * \u5982\u679C\u5BBD\u5EA6\u592A\u5C0F\u800C\u4E0D\u80FD\u5305\u542Bqr\u7B26\u53F7\uFF0C\u5219\u6B64\u9009\u9879\u5C06\u88AB\u5FFD\u7565\u3002
+ * \u4F18\u5148\u4E8E\u89C4\u6A21\u3002
+ */
+width?: number;
+color?: {
+  /**
+   * \u6697\u6A21\u5757\u7684\u989C\u8272\u3002\u503C\u5FC5\u987B\u4E3A\u5341\u516D\u8FDB\u5236\u683C\u5F0F\uFF08RGBA\uFF09.
+   * \u6CE8\u610F\uFF1A\u6DF1\u8272\u5E94\u59CB\u7EC8\u6BD4color.light\u6697\u3002.
+   * Default: #000000ff
+   */
+  dark?: string;
+  /**
+   * \u7167\u660E\u6A21\u5757\u7684\u989C\u8272\u3002\u503C\u5FC5\u987B\u4E3A\u5341\u516D\u8FDB\u5236\u683C\u5F0F\uFF08RGBA\uFF09.
+   * Default: #ffffffff
+   */
+  light?: string;
+};
+
+

LogoType

{
+  // logo\u56FE\u7247
+  src: string;
+  // logo\u5927\u5C0F
+  logoSize: number;
+  // \u80CC\u666F\u989C\u8272
+  bgColor: string;
+  // logo\u5706\u89D2
+  logoRadius: number;
+}
+

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
downloadFunction(fileName:string)\u4E0B\u8F7D

\u4E8B\u4EF6

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
done(data: QrcodeDoneEventParams)=>void\u7ED8\u5236\u5B8C\u6210
error(error)=>void\u751F\u6210\u4E8C\u7EF4\u7801\u65F6\u53D1\u751F\u9519\u8BEF

QrcodeDoneEventParams

{
+  url: string;  // \u4E8C\u7EF4\u7801DataURL\u6570\u636E
+  ctx?: CanvasRenderingContext2D;  // \u8BE5\u5BF9\u8C61\u4E3A\u753B\u5E03\u76842D\u6E32\u67D3\u4E0A\u4E0B\u6587\uFF0C\u4EC5\u5728tag\u4E3Acanvas\u65F6\u6709\u6548\uFF0C\u53EF\u7528\u4E8E\u81EA\u5B9A\u4E49\u7ED8\u5236
+}
+

done \u4E8B\u4EF6\u56DE\u8C03\u4E2D\u53EF\u4EE5\u5BF9\u4E8C\u7EF4\u7801\u8FDB\u884C\u81EA\u5B9A\u4E49\u7684\u7ED8\u5236\uFF0C\u793A\u4F8B\u4EE3\u7801\u5982\u4E0B\uFF1A

<QrCode
+  :value="qrCodeUrl"
+  :width="200"
+  @done="onQrcodeDone"
+/>
+
function onQrcodeDone({ ctx }) {
+  if (ctx instanceof CanvasRenderingContext2D) {
+    // \u989D\u5916\u7ED8\u5236
+    ctx.fillStyle = 'black';
+    ctx.font = '16px "\u5FAE\u8F6F\u96C5\u9ED1"';
+    ctx.textBaseline = 'bottom';
+    ctx.textAlign = 'center';
+    ctx.fillText('\u4F60\u5E05\u4F60\u5148\u626B', 100, 195, 200);
+  }
+}
+

\u6709\u5173 CanvasRenderingContext2D \u7684\u66F4\u591A\u8D44\u6599\u4EE5\u53CA\u7ED8\u5236\u65B9\u6CD5\uFF0C\u8BF7\u53C2\u8003MDN

`,20),e=[o];function c(l,u,r,k,i,d){return a(),s("div",null,e)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_qrcode.md.f0fe898e.lean.js b/assets/components_qrcode.md.f0fe898e.lean.js new file mode 100644 index 00000000..46809b09 --- /dev/null +++ b/assets/components_qrcode.md.f0fe898e.lean.js @@ -0,0 +1,92 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"QrCode","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Methods","slug":"methods"},{"level":2,"title":"\u4E8B\u4EF6","slug":"\u4E8B\u4EF6"}],"relativePath":"components/qrcode.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

QrCode

\u7528\u4E8E\u751F\u6210\u4E8C\u7EF4\u7801\u7684\u7EC4\u4EF6

Usage

<template>
+  <QrCode :value="qrCodeUrl" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { QrCode, QrCodeActionType } from '/@/components/Qrcode/index';
+  import LogoImg from '/@/assets/images/logo.png';
+  const qrCodeUrl = 'https://www.vvbin.cn';
+  export default defineComponent({
+    components: { QrCode },
+    setup() {
+      const qrRef = ref<Nullable<QrCodeActionType>>(null);
+      function download() {
+        const qrEl = unref(qrRef);
+        if (!qrEl) return;
+        qrEl.download('\u6587\u4EF6\u540D');
+      }
+      return {
+        qrCodeUrl,
+        LogoImg,
+        download,
+        qrRef,
+      };
+    },
+  });
+</script>
+<style scoped>
+  .qrcode-demo-item {
+    width: 30%;
+    margin-right: 1%;
+  }
+</style>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valuestring--\u4E8C\u7EF4\u7801\u5730\u5740
optionsQRCodeRenderersOptions--\u4E8C\u7EF4\u7801\u914D\u7F6E ,\u89C1 QRCodeRenderersOptions
widthnumber2-\u5BBD\u5EA6
logostring\uFF5CLogoType--\u4E2D\u95F4 logo \u914D\u7F6E\uFF0C\u89C1 LogoType
tag\u6E32\u67D3\u6807\u7B7Ecanvascanvas | imgimg \u4E0D\u652F\u6301\u5185\u5D4C logo

QRCodeRenderersOptions

/**
+ * \u5B9A\u4E49margin\u7684\u5BBD\u5EA6\u3002.
+ * Default: 4
+ */
+margin?: number;
+/**
+ * \u6BD4\u4F8B\u56E0\u5B50\u3002\u503C1\u8868\u793A\u6BCF\u4E2A\u6A21\u57571\u50CF\u7D20\uFF08\u9ED1\u70B9\uFF09\u3002
+ * Default: 4
+ */
+scale?: number;
+/**
+ * \u4E3A\u8F93\u51FA\u56FE\u50CF\u5F3A\u5236\u6307\u5B9A\u5BBD\u5EA6\u3002
+ * \u5982\u679C\u5BBD\u5EA6\u592A\u5C0F\u800C\u4E0D\u80FD\u5305\u542Bqr\u7B26\u53F7\uFF0C\u5219\u6B64\u9009\u9879\u5C06\u88AB\u5FFD\u7565\u3002
+ * \u4F18\u5148\u4E8E\u89C4\u6A21\u3002
+ */
+width?: number;
+color?: {
+  /**
+   * \u6697\u6A21\u5757\u7684\u989C\u8272\u3002\u503C\u5FC5\u987B\u4E3A\u5341\u516D\u8FDB\u5236\u683C\u5F0F\uFF08RGBA\uFF09.
+   * \u6CE8\u610F\uFF1A\u6DF1\u8272\u5E94\u59CB\u7EC8\u6BD4color.light\u6697\u3002.
+   * Default: #000000ff
+   */
+  dark?: string;
+  /**
+   * \u7167\u660E\u6A21\u5757\u7684\u989C\u8272\u3002\u503C\u5FC5\u987B\u4E3A\u5341\u516D\u8FDB\u5236\u683C\u5F0F\uFF08RGBA\uFF09.
+   * Default: #ffffffff
+   */
+  light?: string;
+};
+
+

LogoType

{
+  // logo\u56FE\u7247
+  src: string;
+  // logo\u5927\u5C0F
+  logoSize: number;
+  // \u80CC\u666F\u989C\u8272
+  bgColor: string;
+  // logo\u5706\u89D2
+  logoRadius: number;
+}
+

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
downloadFunction(fileName:string)\u4E0B\u8F7D

\u4E8B\u4EF6

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
done(data: QrcodeDoneEventParams)=>void\u7ED8\u5236\u5B8C\u6210
error(error)=>void\u751F\u6210\u4E8C\u7EF4\u7801\u65F6\u53D1\u751F\u9519\u8BEF

QrcodeDoneEventParams

{
+  url: string;  // \u4E8C\u7EF4\u7801DataURL\u6570\u636E
+  ctx?: CanvasRenderingContext2D;  // \u8BE5\u5BF9\u8C61\u4E3A\u753B\u5E03\u76842D\u6E32\u67D3\u4E0A\u4E0B\u6587\uFF0C\u4EC5\u5728tag\u4E3Acanvas\u65F6\u6709\u6548\uFF0C\u53EF\u7528\u4E8E\u81EA\u5B9A\u4E49\u7ED8\u5236
+}
+

done \u4E8B\u4EF6\u56DE\u8C03\u4E2D\u53EF\u4EE5\u5BF9\u4E8C\u7EF4\u7801\u8FDB\u884C\u81EA\u5B9A\u4E49\u7684\u7ED8\u5236\uFF0C\u793A\u4F8B\u4EE3\u7801\u5982\u4E0B\uFF1A

<QrCode
+  :value="qrCodeUrl"
+  :width="200"
+  @done="onQrcodeDone"
+/>
+
function onQrcodeDone({ ctx }) {
+  if (ctx instanceof CanvasRenderingContext2D) {
+    // \u989D\u5916\u7ED8\u5236
+    ctx.fillStyle = 'black';
+    ctx.font = '16px "\u5FAE\u8F6F\u96C5\u9ED1"';
+    ctx.textBaseline = 'bottom';
+    ctx.textAlign = 'center';
+    ctx.fillText('\u4F60\u5E05\u4F60\u5148\u626B', 100, 195, 200);
+  }
+}
+

\u6709\u5173 CanvasRenderingContext2D \u7684\u66F4\u591A\u8D44\u6599\u4EE5\u53CA\u7ED8\u5236\u65B9\u6CD5\uFF0C\u8BF7\u53C2\u8003MDN

__VP_STATIC_END__`,20),e=[o];function c(l,u,r,k,i,d){return a(),s("div",null,e)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_scroll-container.md.6072510a.js b/assets/components_scroll-container.md.6072510a.js new file mode 100644 index 00000000..fa109492 --- /dev/null +++ b/assets/components_scroll-container.md.6072510a.js @@ -0,0 +1,59 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"ScrollContainer","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Methods","slug":"methods"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/scroll-container.md","lastUpdated":1694442156385}',p={},o=t(`

ScrollContainer

\u53C2\u8003 element-ui \u7684 el-scrollbar \u7EC4\u4EF6\u5B9E\u73B0

\u6EDA\u52A8\u5BB9\u5668\u7EC4\u4EF6

Usage

<template>
+  <div class="p-4">
+    <div class="my-4">
+      <a-button @click="scrollTo(100)">\u6EDA\u52A8\u5230100px\u4F4D\u7F6E</a-button>
+      <a-button @click="scrollTo(800)">\u6EDA\u52A8\u5230800px\u4F4D\u7F6E</a-button>
+      <a-button @click="scrollTo(0)">\u6EDA\u52A8\u5230\u9876\u90E8</a-button>
+      <a-button @click="scrollBottom()">\u6EDA\u52A8\u5230\u5E95\u90E8</a-button>
+    </div>
+    <div class="scroll-wrap">
+      <ScrollContainer ref="scrollRef">
+        <ul>
+          <template v-for="index in 100" :key="index">
+            <li>{{ index }}</li>
+          </template>
+        </ul>
+      </ScrollContainer>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { ScrollContainer, ScrollActionType } from '/@/components/Container/index';
+  export default defineComponent({
+    components: { CollapseContainer, ScrollContainer },
+    setup() {
+      const scrollRef = ref<Nullable<ScrollActionType>>(null);
+      const getScroll = () => {
+        const scroll = unref(scrollRef);
+        if (!scroll) {
+          throw new Error('scroll is Null');
+        }
+        return scroll;
+      };
+
+      function scrollTo(top: number) {
+        getScroll()?.scrollTo(top);
+      }
+
+      function scrollBottom() {
+        getScroll()?.scrollBottom();
+      }
+
+      return {
+        scrollTo,
+        scrollRef,
+        scrollBottom,
+      };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .scroll-wrap {
+    width: 50%;
+    height: 300px;
+    background: #fff;
+  }
+</style>
+

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
getScrollWrap()=>HtmlElement\u83B7\u53D6\u6EDA\u52A8\u5BB9\u5668 el
scrollBottomFunction\u6EDA\u52A8\u5230\u5E95\u90E8
scrollToFunction(to:number,duration = 500)\u6EDA\u52A8\u5230\u6307\u5B9A\u4F4D\u7F6E

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4\u533A\u57DF
`,9),c=[o];function e(l,u,k,i,r,g){return s(),a("div",null,c)}var m=n(p,[["render",e]]);export{h as __pageData,m as default}; diff --git a/assets/components_scroll-container.md.6072510a.lean.js b/assets/components_scroll-container.md.6072510a.lean.js new file mode 100644 index 00000000..163a6368 --- /dev/null +++ b/assets/components_scroll-container.md.6072510a.lean.js @@ -0,0 +1,59 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"ScrollContainer","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Methods","slug":"methods"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/scroll-container.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

ScrollContainer

\u53C2\u8003 element-ui \u7684 el-scrollbar \u7EC4\u4EF6\u5B9E\u73B0

\u6EDA\u52A8\u5BB9\u5668\u7EC4\u4EF6

Usage

<template>
+  <div class="p-4">
+    <div class="my-4">
+      <a-button @click="scrollTo(100)">\u6EDA\u52A8\u5230100px\u4F4D\u7F6E</a-button>
+      <a-button @click="scrollTo(800)">\u6EDA\u52A8\u5230800px\u4F4D\u7F6E</a-button>
+      <a-button @click="scrollTo(0)">\u6EDA\u52A8\u5230\u9876\u90E8</a-button>
+      <a-button @click="scrollBottom()">\u6EDA\u52A8\u5230\u5E95\u90E8</a-button>
+    </div>
+    <div class="scroll-wrap">
+      <ScrollContainer ref="scrollRef">
+        <ul>
+          <template v-for="index in 100" :key="index">
+            <li>{{ index }}</li>
+          </template>
+        </ul>
+      </ScrollContainer>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { ScrollContainer, ScrollActionType } from '/@/components/Container/index';
+  export default defineComponent({
+    components: { CollapseContainer, ScrollContainer },
+    setup() {
+      const scrollRef = ref<Nullable<ScrollActionType>>(null);
+      const getScroll = () => {
+        const scroll = unref(scrollRef);
+        if (!scroll) {
+          throw new Error('scroll is Null');
+        }
+        return scroll;
+      };
+
+      function scrollTo(top: number) {
+        getScroll()?.scrollTo(top);
+      }
+
+      function scrollBottom() {
+        getScroll()?.scrollBottom();
+      }
+
+      return {
+        scrollTo,
+        scrollRef,
+        scrollBottom,
+      };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .scroll-wrap {
+    width: 50%;
+    height: 300px;
+    background: #fff;
+  }
+</style>
+

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
getScrollWrap()=>HtmlElement\u83B7\u53D6\u6EDA\u52A8\u5BB9\u5668 el
scrollBottomFunction\u6EDA\u52A8\u5230\u5E95\u90E8
scrollToFunction(to:number,duration = 500)\u6EDA\u52A8\u5230\u6307\u5B9A\u4F4D\u7F6E

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4\u533A\u57DF
__VP_STATIC_END__`,9),c=[o];function e(l,u,k,i,r,g){return s(),a("div",null,c)}var m=n(p,[["render",e]]);export{h as __pageData,m as default}; diff --git a/assets/components_strength-meter.md.f1e422e9.js b/assets/components_strength-meter.md.f1e422e9.js new file mode 100644 index 00000000..0c0d6bf5 --- /dev/null +++ b/assets/components_strength-meter.md.f1e422e9.js @@ -0,0 +1,28 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"StrengthMeter","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"}],"relativePath":"components/strength-meter.md","lastUpdated":1694442156385}',p={},e=t(`

StrengthMeter

\u7528\u4E8E\u6821\u9A8C\u5BC6\u7801\u5F3A\u5EA6

Usage

<template>
+  <div class="p-4 flex justify-center">
+    <div class="demo-wrap p-10">
+      <StrengthMeter placeholder="\u9ED8\u8BA4" />
+      <StrengthMeter placeholder="\u7981\u7528" disabled />
+      <br />
+      <StrengthMeter placeholder="\u9690\u85CFinput" :show-input="false" value="!@#qwe12345" />
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import StrengthMeter from '/@/components/StrengthMeter/index';
+  export default defineComponent({
+    components: {
+      StrengthMeter,
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .demo-wrap {
+    width: 50%;
+    background: #fff;
+    border-radius: 10px;
+  }
+</style>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valuestring--\u6821\u9A8C\u7684\u503C
showInputbooleantrue-\u662F\u5426\u663E\u793A input
disabledbooleanfalse-\u662F\u5426\u7981\u7528

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
score-changenumber\u5F3A\u5EA6\u503C\u6539\u53D8\u89E6\u53D1
changestringinput \u503C\u6539\u53D8\u89E6\u53D1
`,8),o=[e];function c(l,u,r,k,i,d){return s(),a("div",null,o)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_strength-meter.md.f1e422e9.lean.js b/assets/components_strength-meter.md.f1e422e9.lean.js new file mode 100644 index 00000000..5c97285d --- /dev/null +++ b/assets/components_strength-meter.md.f1e422e9.lean.js @@ -0,0 +1,28 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"StrengthMeter","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"}],"relativePath":"components/strength-meter.md","lastUpdated":1694442156385}',p={},e=t(`__VP_STATIC_START__

StrengthMeter

\u7528\u4E8E\u6821\u9A8C\u5BC6\u7801\u5F3A\u5EA6

Usage

<template>
+  <div class="p-4 flex justify-center">
+    <div class="demo-wrap p-10">
+      <StrengthMeter placeholder="\u9ED8\u8BA4" />
+      <StrengthMeter placeholder="\u7981\u7528" disabled />
+      <br />
+      <StrengthMeter placeholder="\u9690\u85CFinput" :show-input="false" value="!@#qwe12345" />
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import StrengthMeter from '/@/components/StrengthMeter/index';
+  export default defineComponent({
+    components: {
+      StrengthMeter,
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .demo-wrap {
+    width: 50%;
+    background: #fff;
+    border-radius: 10px;
+  }
+</style>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valuestring--\u6821\u9A8C\u7684\u503C
showInputbooleantrue-\u662F\u5426\u663E\u793A input
disabledbooleanfalse-\u662F\u5426\u7981\u7528

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
score-changenumber\u5F3A\u5EA6\u503C\u6539\u53D8\u89E6\u53D1
changestringinput \u503C\u6539\u53D8\u89E6\u53D1
__VP_STATIC_END__`,8),o=[e];function c(l,u,r,k,i,d){return s(),a("div",null,o)}var m=n(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/components_table.md.aca1b158.js b/assets/components_table.md.aca1b158.js new file mode 100644 index 00000000..2313f727 --- /dev/null +++ b/assets/components_table.md.aca1b158.js @@ -0,0 +1,312 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Table \u8868\u683C","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":3,"title":"\u793A\u4F8B","slug":"\u793A\u4F8B"},{"level":3,"title":"template \u793A\u4F8B","slug":"template-\u793A\u4F8B"},{"level":3,"title":"BasicColumn \u548C tableAction \u901A\u8FC7\u6743\u9650\u548C\u4E1A\u52A1\u63A7\u5236\u663E\u793A\u9690\u85CF\u7684\u793A\u4F8B","slug":"basiccolumn-\u548C-tableaction-\u901A\u8FC7\u6743\u9650\u548C\u4E1A\u52A1\u63A7\u5236\u663E\u793A\u9690\u85CF\u7684\u793A\u4F8B"},{"level":2,"title":"useTable","slug":"usetable"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Methods","slug":"methods"},{"level":2,"title":"Props","slug":"props"},{"level":3,"title":"TableSetting","slug":"tablesetting"},{"level":2,"title":"BasicColumn","slug":"basiccolumn"},{"level":3,"title":"EditComponentType","slug":"editcomponenttype"},{"level":3,"title":"CellFormat","slug":"cellformat"},{"level":2,"title":"\u4E8B\u4EF6","slug":"\u4E8B\u4EF6"},{"level":2,"title":"Slots","slug":"slots"},{"level":2,"title":"Form-Slots","slug":"form-slots"},{"level":2,"title":"ColumnSetting\u7EC4\u4EF6","slug":"columnsetting\u7EC4\u4EF6"},{"level":2,"title":"\u5185\u7F6E\u7EC4\u4EF6\uFF08\u53EA\u80FD\u7528\u4E8E\u8868\u683C\u5185\u90E8\uFF09","slug":"\u5185\u7F6E\u7EC4\u4EF6\uFF08\u53EA\u80FD\u7528\u4E8E\u8868\u683C\u5185\u90E8\uFF09"},{"level":3,"title":"TableAction","slug":"tableaction"},{"level":3,"title":"TableImg","slug":"tableimg"},{"level":2,"title":"\u5168\u5C40\u914D\u7F6E","slug":"\u5168\u5C40\u914D\u7F6E"}],"relativePath":"components/table.md","lastUpdated":1694442156385}',p={},o=t(`

Table \u8868\u683C

\u5BF9 antv \u7684 table \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5

\u5982\u679C\u6587\u6863\u5185\u6CA1\u6709\uFF0C\u53EF\u4EE5\u5C1D\u8BD5\u5728\u5728\u7EBF\u793A\u4F8B\u5185\u5BFB\u627E

Usage

\u793A\u4F8B

<template>
+  <div class="p-4">
+    <BasicTable
+      title="\u57FA\u7840\u793A\u4F8B"
+      titleHelpMessage="\u6E29\u99A8\u63D0\u9192"
+      :columns="columns"
+      :dataSource="data"
+      :canResize="canResize"
+      :loading="loading"
+      :striped="striped"
+      :bordered="border"
+      :pagination="{ pageSize: 20 }"
+    >
+      <template #toolbar>
+        <a-button type="primary"> \u64CD\u4F5C\u6309\u94AE </a-button>
+      </template>
+    </BasicTable>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicTable } from '/@/components/Table';
+  import { getBasicColumns, getBasicData } from './tableData';
+
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      return {
+        columns: getBasicColumns(),
+        data: getBasicData(),
+      };
+    },
+  });
+</script>
+

template \u793A\u4F8B

\u6240\u6709\u53EF\u8C03\u7528\u51FD\u6570\u89C1\u4E0B\u65B9 Methods \u8BF4\u660E

<template>
+  <div class="p-4">
+    <BasicTable
+      :canResize="false"
+      title="RefTable\u793A\u4F8B"
+      titleHelpMessage="\u4F7F\u7528Ref\u8C03\u7528\u8868\u683C\u5185\u65B9\u6CD5"
+      ref="tableRef"
+      :api="api"
+      :columns="columns"
+      rowKey="id"
+      :rowSelection="{ type: 'checkbox' }"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { BasicTable, TableActionType } from '/@/components/Table';
+  import { getBasicColumns, getBasicShortColumns } from './tableData';
+  import { demoListApi } from '/@/api/demo/table';
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      const tableRef = ref<Nullable<TableActionType>>(null);
+
+      function getTableAction() {
+        const tableAction = unref(tableRef);
+        if (!tableAction) {
+          throw new Error('tableAction is null');
+        }
+        return tableAction;
+      }
+      function changeLoading() {
+        getTableAction().setLoading(true);
+        setTimeout(() => {
+          getTableAction().setLoading(false);
+        }, 1000);
+      }
+      return {
+        tableRef,
+        api: demoListApi,
+        columns: getBasicColumns(),
+        changeLoading,
+      };
+    },
+  });
+</script>
+

BasicColumn \u548C tableAction \u901A\u8FC7\u6743\u9650\u548C\u4E1A\u52A1\u63A7\u5236\u663E\u793A\u9690\u85CF\u7684\u793A\u4F8B

<template>
+  <div class="p-4">
+    <BasicTable @register="registerTable">
+      <template #action="{ record }">
+        <TableAction
+          :actions="[
+            {
+              label: '\u7F16\u8F91',
+              onClick: handleEdit.bind(null, record),
+              auth: 'other', // \u6839\u636E\u6743\u9650\u63A7\u5236\u662F\u5426\u663E\u793A: \u65E0\u6743\u9650\uFF0C\u4E0D\u663E\u793A
+            },
+            {
+              label: '\u5220\u9664',
+              icon: 'ic:outline-delete-outline',
+              onClick: handleDelete.bind(null, record),
+              auth: 'super', // \u6839\u636E\u6743\u9650\u63A7\u5236\u662F\u5426\u663E\u793A: \u6709\u6743\u9650\uFF0C\u4F1A\u663E\u793A
+            },
+          ]"
+          :dropDownActions="[
+            {
+              label: '\u542F\u7528',
+              popConfirm: {
+                title: '\u662F\u5426\u542F\u7528\uFF1F',
+                confirm: handleOpen.bind(null, record),
+              },
+              ifShow: (_action) => {
+                return record.status !== 'enable'; // \u6839\u636E\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A: \u975Eenable\u72B6\u6001\u7684\u4E0D\u663E\u793A\u542F\u7528\u6309\u94AE
+              },
+            },
+            {
+              label: '\u7981\u7528',
+              popConfirm: {
+                title: '\u662F\u5426\u7981\u7528\uFF1F',
+                confirm: handleOpen.bind(null, record),
+              },
+              ifShow: () => {
+                return record.status === 'enable'; // \u6839\u636E\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A: enable\u72B6\u6001\u7684\u663E\u793A\u7981\u7528\u6309\u94AE
+              },
+            },
+            {
+              label: '\u540C\u65F6\u63A7\u5236',
+              popConfirm: {
+                title: '\u662F\u5426\u52A8\u6001\u663E\u793A\uFF1F',
+                confirm: handleOpen.bind(null, record),
+              },
+              auth: 'super', // \u540C\u65F6\u6839\u636E\u6743\u9650\u548C\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A
+              ifShow: () => {
+                return true; // \u6839\u636E\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A
+              },
+            },
+          ]"
+        />
+      </template>
+    </BasicTable>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
+
+  import { demoListApi } from '/@/api/demo/table';
+  const columns: BasicColumn[] = [
+    {
+      title: '\u59D3\u540D',
+      dataIndex: 'name',
+      auth: 'test', // \u6839\u636E\u6743\u9650\u63A7\u5236\u662F\u5426\u663E\u793A: \u65E0\u6743\u9650\uFF0C\u4E0D\u663E\u793A
+    },
+    {
+      title: '\u5730\u5740',
+      dataIndex: 'address',
+      auth: 'super', // \u540C\u65F6\u6839\u636E\u6743\u9650\u63A7\u5236\u662F\u5426\u663E\u793A
+      ifShow: (_column) => {
+        return true; // \u6839\u636E\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A
+      },
+    },
+  ];
+  export default defineComponent({
+    components: { BasicTable, TableAction },
+    setup() {
+      const [registerTable] = useTable({
+        title: 'TableAction\u7EC4\u4EF6\u53CA\u56FA\u5B9A\u5217\u793A\u4F8B',
+        api: demoListApi,
+        columns: columns,
+        bordered: true,
+        actionColumn: {
+          width: 250,
+          title: 'Action',
+          dataIndex: 'action',
+          slots: { customRender: 'action' },
+        },
+      });
+      function handleEdit(record: Recordable) {
+        console.log('\u70B9\u51FB\u4E86\u7F16\u8F91', record);
+      }
+      function handleDelete(record: Recordable) {
+        console.log('\u70B9\u51FB\u4E86\u5220\u9664', record);
+      }
+      function handleOpen(record: Recordable) {
+        console.log('\u70B9\u51FB\u4E86\u542F\u7528', record);
+      }
+      return {
+        registerTable,
+        handleEdit,
+        handleDelete,
+        handleOpen,
+      };
+    },
+  });
+</script>
+

useTable

\u4F7F\u7528\u7EC4\u4EF6\u81EA\u5E26\u7684 useTable \u53EF\u4EE5\u65B9\u4FBF\u4F7F\u7528\u8868\u5355

\u4E0B\u9762\u662F\u4E00\u4E2A\u4F7F\u7528\u7B80\u5355\u8868\u683C\u7684\u793A\u4F8B\uFF0C

<template>
+  <BasicTable @register="registerTable" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTable, useTable } from '/@/components/Table';
+  import { getBasicColumns, getBasicShortColumns } from './tableData';
+  import { demoListApi } from '/@/api/demo/table';
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      const [
+        registerTable,
+        {
+          setLoading,
+        },
+      ] = useTable({
+        api: demoListApi,
+        columns: getBasicColumns(),
+      });
+
+      function changeLoading() {
+        setLoading(true);
+        setTimeout(() => {
+          setLoading(false);
+        }, 1000);
+      }
+      }
+      return {
+        registerTable,
+        changeLoading,
+      };
+    },
+  });
+</script>
+

Usage

\u7528\u4E8E\u8C03\u7528 Table \u5185\u90E8\u65B9\u6CD5\u53CA table \u53C2\u6570\u914D\u7F6E

// \u8868\u683C\u7684props\u4E5F\u53EF\u4EE5\u76F4\u63A5\u6CE8\u518C\u5230useTable\u5185\u90E8
+const [register, methods] = useTable(props);
+

register

register \u7528\u4E8E\u6CE8\u518C useTable\uFF0C\u5982\u679C\u9700\u8981\u4F7F\u7528useTable\u63D0\u4F9B\u7684 api\uFF0C\u5FC5\u987B\u5C06 register \u4F20\u5165\u7EC4\u4EF6\u7684 onRegister

<template>
+  <BasicTable @register="register" />
+</template>
+<script>
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register] = useTable();
+      return { register };
+    },
+  });
+</script>
+

Methods

setProps

\u7C7B\u578B\uFF1A(props: Partial<BasicTableProps>) => void

\u8BF4\u660E: \u7528\u4E8E\u8BBE\u7F6E\u8868\u683C\u53C2\u6570

reload

\u7C7B\u578B\uFF1A(opt?: FetchParams) => Promise<void>

\u8BF4\u660E: \u5237\u65B0\u8868\u683C

redoHeight

\u7C7B\u578B\uFF1A() => void

\u8BF4\u660E: \u91CD\u65B0\u8BA1\u7B97\u8868\u683C\u9AD8\u5EA6

setLoading

\u7C7B\u578B\uFF1A(loading: boolean) => void

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u683C loading \u72B6\u6001

getDataSource

\u83B7\u53D6\u8868\u683C\u6570\u636E

\u7C7B\u578B\uFF1A<T = Recordable>() => T[]

\u8BF4\u660E: \u83B7\u53D6\u8868\u683C\u6570\u636E

getRawDataSource

\u83B7\u53D6\u540E\u7AEF\u63A5\u53E3\u539F\u59CB\u6570\u636E

\u7C7B\u578B\uFF1A<T = Recordable>() => T

\u8BF4\u660E: \u83B7\u53D6\u540E\u7AEF\u63A5\u53E3\u539F\u59CB\u6570\u636E

getColumns

\u7C7B\u578B\uFF1A(opt?: GetColumnsParams) => BasicColumn[]

\u8BF4\u660E: \u83B7\u53D6\u8868\u683C\u6570\u636E

setColumns

\u7C7B\u578B\uFF1A(columns: BasicColumn[] | string[]) => void

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u5934\u6570\u636E

setTableData

\u7C7B\u578B\uFF1A<T = Recordable>(values: T[]) => void

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u683C\u6570\u636E

setPagination

\u7C7B\u578B\uFF1A(info: Partial<PaginationProps>) => void

\u8BF4\u660E: \u8BBE\u7F6E\u5206\u9875\u4FE1\u606F

deleteSelectRowByKey

\u7C7B\u578B\uFF1A(key: string) => void

\u8BF4\u660E: \u6839\u636E key \u5220\u9664\u53D6\u6D88\u9009\u4E2D\u884C

getSelectRowKeys

\u7C7B\u578B\uFF1A() => string[]

\u8BF4\u660E: \u83B7\u53D6\u9009\u4E2D\u884C\u7684 keys

getSelectRows

\u7C7B\u578B\uFF1A<T = Recordable>() => T[]

\u8BF4\u660E: \u83B7\u53D6\u9009\u4E2D\u884C\u7684 rows

clearSelectedRowKeys

\u7C7B\u578B\uFF1A() => void

\u8BF4\u660E: \u6E05\u7A7A\u9009\u4E2D\u884C

setSelectedRowKeys

\u7C7B\u578B\uFF1A(rowKeys: string[] | number[]) => void

\u8BF4\u660E: \u8BBE\u7F6E\u9009\u4E2D\u884C

getPaginationRef

\u7C7B\u578B\uFF1A() => PaginationProps | boolean

\u8BF4\u660E: \u83B7\u53D6\u5F53\u524D\u5206\u9875\u4FE1\u606F

getShowPagination

\u7C7B\u578B\uFF1A() => boolean

\u8BF4\u660E: \u83B7\u53D6\u5F53\u524D\u662F\u5426\u663E\u793A\u5206\u9875

setShowPagination

\u7C7B\u578B\uFF1A(show: boolean) => Promise<void>

\u8BF4\u660E: \u8BBE\u7F6E\u5F53\u524D\u662F\u5426\u663E\u793A\u5206\u9875

getRowSelection

\u7C7B\u578B\uFF1A() => TableRowSelection<Recordable>

\u8BF4\u660E: \u83B7\u53D6\u52FE\u9009\u6846\u4FE1\u606F

updateTableData

\u7C7B\u578B\uFF1A(index: number, key: string, value: any)=>void

\u8BF4\u660E: \u66F4\u65B0\u8868\u683C\u6570\u636E

updateTableDataRecord

\u7C7B\u578B\uFF1A (rowKey: string | number, record: Recordable) => Recordable | void

\u8BF4\u660E\uFF1A \u6839\u636E\u552F\u4E00\u7684 rowKey \u66F4\u65B0\u6307\u5B9A\u884C\u7684\u6570\u636E.\u53EF\u7528\u4E8E\u4E0D\u5237\u65B0\u6574\u4E2A\u8868\u683C\u800C\u5C40\u90E8\u66F4\u65B0\u6570\u636E

deleteTableDataRecord

\u7C7B\u578B\uFF1A (rowKey: string | number | string[] | number[]) => void

\u8BF4\u660E\uFF1A \u6839\u636E\u552F\u4E00\u7684rowKey \u52A8\u6001\u5220\u9664\u6307\u5B9A\u884C\u7684\u6570\u636E.\u53EF\u7528\u4E8E\u4E0D\u5237\u65B0\u6574\u4E2A\u8868\u683C\u800C\u5C40\u90E8\u66F4\u65B0\u6570\u636E

insertTableDataRecord

\u7C7B\u578B\uFF1A (record: Recordable, index?: number) => Recordable | void

\u8BF4\u660E\uFF1A \u53EF\u6839\u636E\u4F20\u5165\u7684 index \u503C\u51B3\u5B9A\u63D2\u5165\u6570\u636E\u884C\u7684\u4F4D\u7F6E\uFF0C\u4E0D\u4F20\u5219\u662F\u987A\u5E8F\u63D2\u5165\uFF0C\u53EF\u7528\u4E8E\u4E0D\u5237\u65B0\u6574\u4E2A\u8868\u683C\u800C\u5C40\u90E8\u66F4\u65B0\u6570\u636E

getForm

\u7C7B\u578B\uFF1A() => FormActionType

\u8BF4\u660E: \u5982\u679C\u5F00\u542F\u4E86\u641C\u7D22\u533A\u57DF\u3002\u53EF\u4EE5\u901A\u8FC7\u8BE5\u51FD\u6570\u83B7\u53D6\u8868\u5355\u5BF9\u8C61\u51FD\u6570\u8FDB\u884C\u64CD\u4F5C

expandAll

\u7C7B\u578B\uFF1A() => void

\u8BF4\u660E: \u5C55\u5F00\u6811\u5F62\u8868\u683C

collapseAll

\u7C7B\u578B\uFF1A() => void

\u8BF4\u660E: \u6298\u53E0\u6811\u5F62\u8868\u683C

Props

\u6E29\u99A8\u63D0\u9192

  • \u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv table
  • \u6CE8\u610F\uFF1AdefaultExpandAllRows\u3001defaultExpandedRowKeys \u5C5E\u6027\u5728basicTable\u4E2D\u4E0D\u53D7\u652F\u6301\uFF0C\u5E76\u4E14\u5728antv table v2.2.0\u4E4B\u540E\u4E5F\u88AB\u79FB\u9664\u3002
\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
clickToRowSelectbooleantrue-\u70B9\u51FB\u884C\u662F\u5426\u9009\u4E2D checkbox \u6216\u8005 radio\u3002\u9700\u8981\u5F00\u542F
sortFn(sortInfo: SorterResult<any>) => any--\u81EA\u5B9A\u4E49\u6392\u5E8F\u65B9\u6CD5\u3002\u89C1\u4E0B\u65B9\u5168\u5C40\u914D\u7F6E\u8BF4\u660E
filterFn(sortInfo: Partial<Recordable<string[]>>) => any--\u81EA\u5B9A\u4E49\u8FC7\u6EE4\u65B9\u6CD5\u3002\u89C1\u4E0B\u65B9\u5168\u5C40\u914D\u7F6E\u8BF4\u660E
showTableSettingbooleanfalse-\u663E\u793A\u8868\u683C\u8BBE\u7F6E\u5DE5\u5177
tableSettingTableSetting--\u8868\u683C\u8BBE\u7F6E\u5DE5\u5177\u914D\u7F6E\uFF0C\u89C1\u4E0B\u65B9 TableSetting
stripedbooleantrue-\u6591\u9A6C\u7EB9
insetbooleanfalse-\u53D6\u6D88\u8868\u683C\u7684\u9ED8\u8BA4 padding
autoCreateKeybooleantrue-\u662F\u5426\u81EA\u52A8\u751F\u6210 key
showSummarybooleanfalse-\u662F\u5426\u663E\u793A\u5408\u8BA1\u884C
summaryDataany[]--\u81EA\u5B9A\u4E49\u5408\u8BA1\u6570\u636E\u3002\u5982\u679C\u6709\u5219\u663E\u793A\u8BE5\u6570\u636E
emptyDataIsShowTablebooleantrue-\u5728\u542F\u7528\u641C\u7D22\u8868\u5355\u7684\u524D\u63D0\u4E0B\uFF0C\u662F\u5426\u5728\u8868\u683C\u6CA1\u6709\u6570\u636E\u7684\u65F6\u5019\u663E\u793A\u8868\u683C
summaryFunc(...arg) => any[]--\u8BA1\u7B97\u5408\u8BA1\u884C\u7684\u65B9\u6CD5
canRowDragbooleanfalse-\u662F\u5426\u53EF\u62D6\u62FD\u884C\u6392\u5E8F
canColDragbooleanfalse-\u662F\u5426\u53EF\u62D6\u62FD\u5217
isTreeTablebooleanfalse-\u662F\u5426\u6811\u8868
api(...arg: any) => Promise<any>--\u8BF7\u6C42\u63A5\u53E3\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5C06src/api\u5185\u7684\u51FD\u6570\u76F4\u63A5\u4F20\u5165
beforeFetch(T)=>T--\u8BF7\u6C42\u4E4B\u524D\u5BF9\u53C2\u6570\u8FDB\u884C\u5904\u7406
afterFetch(T)=>T--\u8BF7\u6C42\u4E4B\u540E\u5BF9\u8FD4\u56DE\u503C\u8FDB\u884C\u5904\u7406
handleSearchInfoFn(T)=>T--\u5F00\u542F\u8868\u5355\u540E\uFF0C\u5728\u8BF7\u6C42\u4E4B\u524D\u5904\u7406\u641C\u7D22\u6761\u4EF6\u53C2\u6570
fetchSettingFetchSetting--\u63A5\u53E3\u8BF7\u6C42\u914D\u7F6E\uFF0C\u53EF\u4EE5\u914D\u7F6E\u8BF7\u6C42\u7684\u5B57\u6BB5\u548C\u54CD\u5E94\u7684\u5B57\u6BB5\u540D\uFF0C\u89C1\u4E0B\u65B9\u5168\u5C40\u914D\u7F6E\u8BF4\u660E
immediatebooleantrue-\u7EC4\u4EF6\u52A0\u8F7D\u540E\u662F\u5426\u7ACB\u5373\u8BF7\u6C42\u63A5\u53E3\uFF0C\u5728 api \u6709\u4F20\u7684\u60C5\u51B5\u4E0B\uFF0C\u5982\u679C\u4E3A false\uFF0C\u9700\u8981\u81EA\u884C\u4F7F\u7528 reload \u52A0\u8F7D\u8868\u683C\u6570\u636E
searchInfoany--\u989D\u5916\u7684\u8BF7\u6C42\u53C2\u6570
useSearchFormbooleanfalse-\u4F7F\u7528\u641C\u7D22\u8868\u5355
formConfigany--\u8868\u5355\u914D\u7F6E\uFF0C\u53C2\u8003\u8868\u5355\u7EC4\u4EF6\u7684 Props
columnsany--\u8868\u5355\u5217\u4FE1\u606F BasicColumn[]
showIndexColumnbooleanture-\u662F\u5426\u663E\u793A\u5E8F\u53F7\u5217
indexColumnPropsany--\u5E8F\u53F7\u5217\u914D\u7F6E BasicColumn
actionColumnany--\u8868\u683C\u53F3\u4FA7\u64CD\u4F5C\u5217\u914D\u7F6E BasicColumn
ellipsisbooleantrue-\u6587\u672C\u8D85\u8FC7\u5BBD\u5EA6\u662F\u5426\u663E\u793A...
canResizebooleantrue-\u662F\u5426\u53EF\u4EE5\u81EA\u9002\u5E94\u9AD8\u5EA6(\u5982\u679C\u7F6E\u4E8EPageWrapper\u7EC4\u4EF6\u5185\uFF0C\u8BF7\u52FF\u542F\u7528PageWrapper\u7684fixedHeight\u5C5E\u6027\uFF0C\u4E8C\u8005\u4E0D\u53EF\u540C\u65F6\u4F7F\u7528)
clearSelectOnPageChangebooleanfalse-\u5207\u6362\u9875\u7801\u662F\u5426\u91CD\u7F6E\u52FE\u9009\u72B6\u6001
resizeHeightOffsetnumber0-\u8868\u683C\u81EA\u9002\u5E94\u9AD8\u5EA6\u8BA1\u7B97\u7ED3\u679C\u4F1A\u51CF\u53BB\u8FD9\u4E2A\u503C
rowSelectionany--\u9009\u62E9\u5217\u914D\u7F6E
titlestring--\u8868\u683C\u6807\u9898
titleHelpMessagestring \uFF5C string[]--\u8868\u683C\u6807\u9898\u53F3\u4FA7\u6E29\u99A8\u63D0\u9192
maxHeightnumber--\u8868\u683C\u6700\u5927\u9AD8\u5EA6\uFF0C\u8D85\u51FA\u4F1A\u663E\u793A\u6EDA\u52A8\u6761
dataSourceany[]--\u8868\u683C\u6570\u636E\uFF0C\u975E api \u52A0\u8F7D\u60C5\u51B5
borderedbooleanfalse-\u662F\u5426\u663E\u793A\u8868\u683C\u8FB9\u6846
paginationany--\u5206\u9875\u4FE1\u606F\u914D\u7F6E\uFF0C\u4E3A false \u4E0D\u663E\u793A\u5206\u9875
loadingbooleanfalse-\u8868\u683C loading \u72B6\u6001
scrollany--\u53C2\u8003\u5B98\u65B9\u6587\u6863 scroll
beforeEditSubmit({record: Recordable,index: number,key: string | number,value: any}) => Promise<any>--\u5355\u5143\u683C\u7F16\u8F91\u72B6\u6001\u63D0\u4EA4\u56DE\u8C03\uFF0C\u8FD4\u56DEfalse\u5C06\u963B\u6B62\u5355\u5143\u683C\u63D0\u4EA4\u6570\u636E\u5230table\u3002\u8BE5\u56DE\u8C03\u5728\u884C\u7F16\u8F91\u6A21\u5F0F\u4E0B\u65E0\u6548\u30022.7.2

TableSetting

{
+  // \u662F\u5426\u663E\u793A\u5237\u65B0\u6309\u94AE
+  redo?: boolean;
+  // \u662F\u5426\u663E\u793A\u5C3A\u5BF8\u8C03\u6574\u6309\u94AE
+  size?: boolean;
+  // \u662F\u5426\u663E\u793A\u5B57\u6BB5\u8C03\u6574\u6309\u94AE
+  setting?: boolean;
+  // \u662F\u5426\u663E\u793A\u5168\u5C4F\u6309\u94AE
+  fullScreen?: boolean;
+}
+

BasicColumn

\u9664 \u53C2\u8003\u5B98\u65B9 Column \u914D\u7F6E\u5916\uFF0C\u6269\u5C55\u4EE5\u4E0B\u53C2\u6570

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
defaultHiddenbooleanfalse-\u9ED8\u8BA4\u9690\u85CF\uFF0C\u53EF\u5728\u5217\u914D\u7F6E\u663E\u793A
helpMessagestring\uFF5Cstring[]--\u5217\u5934\u53F3\u4FA7\u5E2E\u52A9\u6587\u672C
editboolean--\u662F\u5426\u5F00\u542F\u5355\u5143\u683C\u7F16\u8F91
editRowboolean--\u662F\u5426\u5F00\u542F\u884C\u7F16\u8F91
editablebooleanfalse-\u662F\u5426\u5904\u4E8E\u7F16\u8F91\u72B6\u6001
editComponentComponentTypeInput-\u7F16\u8F91\u7EC4\u4EF6
editComponentPropsany--\u5BF9\u5E94\u7F16\u8F91\u7EC4\u4EF6\u7684 props
editRule((text: string, record: Recordable) => Promise<string>)--\u5BF9\u5E94\u7F16\u8F91\u7EC4\u4EF6\u7684\u8868\u5355\u6821\u9A8C
editValueMap(value: any) => string--\u5BF9\u5E94\u5355\u5143\u683C\u503C\u679A\u4E3E
onEditRow\uFF08\uFF09=>void--\u89E6\u53D1\u884C\u7F16\u8F91
formatCellFormat--\u5355\u5143\u683C\u683C\u5F0F\u5316
authRoleEnum \uFF5C RoleEnum[] \uFF5C string \uFF5C string[]--\u6839\u636E\u6743\u9650\u7F16\u7801\u6765\u63A7\u5236\u5F53\u524D\u5217\u662F\u5426\u663E\u793A
ifShowboolean \uFF5C ((action: ActionItem) => boolean)--\u6839\u636E\u4E1A\u52A1\u72B6\u6001\u6765\u63A7\u5236\u5F53\u524D\u5217\u662F\u5426\u663E\u793A

EditComponentType

export type ComponentType =
+  | 'Input'
+  | 'InputNumber'
+  | 'Select'
+  | 'ApiSelect'
+  | 'Checkbox'
+  | 'Switch'
+  | 'DatePicker'  // v2.5.0 \u4EE5\u4E0A
+  | 'TimePicker'; // v2.5.0 \u4EE5\u4E0A
+

CellFormat

export type CellFormat =
+  | string
+  | ((text: string, record: Recordable, index: number) => string | number)
+  | Map<string | number, any>;
+

\u4E8B\u4EF6

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u4E8B\u4EF6\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 event \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv table

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
fetch-successFunction({items,total})\u63A5\u53E3\u8BF7\u6C42\u6210\u529F\u540E\u89E6\u53D1
fetch-errorFunction(error)\u9519\u8BEF\u4FE1\u606F
selection-changeFunction({keys\uFF0Crows})\u52FE\u9009\u4E8B\u4EF6\u89E6\u53D1
row-clickFunction(record, index, event)\u884C\u70B9\u51FB\u89E6\u53D1
row-dbClickFunction(record, index, event)\u884C\u53CC\u51FB\u89E6\u53D1
row-contextmenuFunction(record, index, event)\u884C\u53F3\u952E\u89E6\u53D1
row-mouseenterFunction(record, index, event)\u884C\u79FB\u5165\u89E6\u53D1
row-mouseleaveFunction(record, index, event)\u884C\u79FB\u51FA\u89E6\u53D1
edit-endFunction({record, index, key, value})\u5355\u5143\u683C\u7F16\u8F91\u5B8C\u6210\u89E6\u53D1
edit-cancelFunction({record, index, key, value})\u5355\u5143\u683C\u53D6\u6D88\u7F16\u8F91\u89E6\u53D1
edit-row-endFunction()\u884C\u7F16\u8F91\u7ED3\u675F\u89E6\u53D1
edit-changeFunction({column,value,record})\u5355\u5143\u683C\u7F16\u8F91\u7EC4\u4EF6\u7684 value \u53D1\u751F\u53D8\u5316\u65F6\u89E6\u53D1

edit-change \u8BF4\u660E

\u4ECE\u7248\u672C 2.4.2 \u8D77\uFF0C\u5BF9\u4E8E edit-change \u4E8B\u4EF6\uFF0Crecord \u4E2D\u7684 editValueRefs \u88C5\u8F7D\u4E86\u5F53\u524D\u884C\u7684\u6240\u6709\u7F16\u8F91\u7EC4\u4EF6\uFF08\u5982\u679C\u6709\u7684\u8BDD\uFF09\u7684\u503C\u7684 ref \u5BF9\u8C61\uFF0C\u53EF\u7528\u4E8E\u5904\u7406\u540C\u4E00\u884C\u4E2D\u7684\u7F16\u8F91\u7EC4\u4EF6\u7684\u8054\u52A8\u3002\u8BF7\u770B\u4E0B\u9762\u7684\u4F8B\u5B50

      function onEditChange({ column, record }) {
+        // \u5F53\u540C\u4E00\u884C\u7684\u5355\u4EF7\u6216\u8005\u6570\u91CF\u53D1\u751F\u53D8\u5316\u65F6\uFF0C\u66F4\u65B0\u5408\u8BA1\u91D1\u989D\uFF08\u4E09\u4E2A\u6570\u636E\u5747\u4E3A\u5F53\u524D\u884C\u7F16\u8F91\u7EC4\u4EF6\u7684\u503C\uFF09
+        if (column.dataIndex === 'qty' || column.dataIndex === 'price') {
+          const { editValueRefs: { total, qty, price } } = record;
+          total.value = unref(qty) * unref(price);
+        }
+      }
+

Slots

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 slot \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv table

\u540D\u79F0\u8BF4\u660E\u7248\u672C
tableTitle\u8868\u683C\u9876\u90E8\u5DE6\u4FA7\u533A\u57DF
toolbar\u8868\u683C\u9876\u90E8\u53F3\u4FA7\u533A\u57DF
expandedRowRender\u5C55\u5F00\u884C\u533A\u57DF
headerTop\u8868\u683C\u9876\u90E8\u533A\u57DF\uFF08\u6807\u9898\u4E0A\u65B9\uFF092.6.1

Form-Slots

\u5F53\u5F00\u542F form \u8868\u5355\u540E\u3002\u4EE5form-xxxx\u4E3A\u524D\u7F00\u7684 slot \u4F1A\u88AB\u89C6\u4E3A form \u7684 slot

xxxx \u4E3A form \u7EC4\u4EF6\u7684 slot\u3002\u5177\u4F53\u53C2\u8003form \u7EC4\u4EF6\u6587\u6863

e.g

form-submitBefore
+

ColumnSetting\u7EC4\u4EF6

\u5B57\u6BB5\u8C03\u6574\u7EC4\u4EF6

\u63D0\u4F9B\u4E86\u53EF\u89C6\u5316\u64CD\u4F5C\u8868\u683C\u6BCF\u4E00\u5217\u7684\u662F\u5426\u5C55\u793A\u3001\u4F4D\u7F6E\u3001\u56FA\u5B9A\uFF1B\u5305\u62EC\u5E8F\u53F7\u5217\u3001\u52FE\u9009\u5217\u3002\u4F1A\u54CD\u5E94tableMethods\u4E2DsetColumns\u548CsetProps\u65B9\u6CD5\u7684\u66F4\u6539\u5185\u5BB9\u3002

\u503C\u5F97\u6CE8\u610F\u7684\u662F

\u5E8F\u53F7\u5217\u548C\u52FE\u9009\u5217\u662F\u5728table\u7684props\u4E2D\u5B9A\u4E49\u7684\uFF0C\u5BF9\u5E94\u7684\u5B57\u6BB5\u5206\u522B\u662FshowIndexColumn\u3001rowSelection\u3002\u56E0\u6B64\u5728\u52A8\u6001\u6539\u53D8\u8868\u683C\u5217\u914D\u7F6E\u7684\u65F6\u5019\uFF0C\u5EFA\u8BAE\u4F7F\u7528setProps\u65B9\u6CD5\uFF0C\u5E76\u663E\u5F0F\u5730\u8BBE\u7F6E\u8FD9\u4E24\u4E2A\u5B57\u6BB5\u7684\u503C\u6765\u4FDD\u8BC1\u8FBE\u5230\u9884\u671F\u6548\u679C

// ...
+const [registerTable, { setProps }] = useTable({...})
+
+setProps({
+  columns: [], // \u8868\u683C\u7684\u5217\u914D\u7F6E BasicColumn[]
+  showIndexColumn: false, // \u662F\u5426\u5C55\u793A\u5E8F\u53F7\u5217
+  rowSelection: false // \u52FE\u9009\u5217\u914D\u7F6E
+})
+

\u5185\u7F6E\u7EC4\u4EF6\uFF08\u53EA\u80FD\u7528\u4E8E\u8868\u683C\u5185\u90E8\uFF09

TableAction

\u7528\u4E8E\u8868\u683C\u53F3\u4FA7\u64CD\u4F5C\u5217\u6E32\u67D3

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
actionsActionItem[]--\u53F3\u4FA7\u64CD\u4F5C\u5217\u6309\u94AE\u5217\u8868
dropDownActionsActionItem[]--\u53F3\u4FA7\u64CD\u4F5C\u5217\u66F4\u591A\u4E0B\u62C9\u6309\u94AE\u5217\u8868
stopButtonPropagationbooleanfalsetrue/false\u662F\u5426\u963B\u6B62\u64CD\u4F5C\u6309\u94AE\u7684click\u4E8B\u4EF6\u5192\u6CE12.5.0

ActionItem

export interface ActionItem {
+  // \u6309\u94AE\u6587\u672C
+  label: string;
+  // \u662F\u5426\u7981\u7528
+  disabled?: boolean;
+  // \u6309\u94AE\u989C\u8272
+  color?: 'success' | 'error' | 'warning';
+  // \u6309\u94AE\u7C7B\u578B
+  type?: string;
+  // button\u7EC4\u4EF6props
+  props?: any;
+  // \u6309\u94AE\u56FE\u6807
+  icon?: string;
+  // \u6C14\u6CE1\u786E\u8BA4\u6846
+  popConfirm?: PopConfirm;
+  // \u662F\u5426\u663E\u793A\u5206\u9694\u7EBF\uFF0Cv2.0.0+
+  divider?: boolean;
+  // \u6839\u636E\u6743\u9650\u7F16\u7801\u6765\u63A7\u5236\u5F53\u524D\u5217\u662F\u5426\u663E\u793A\uFF0Cv2.4.0+
+  auth?: RoleEnum | RoleEnum[] | string | string[];
+  // \u6839\u636E\u4E1A\u52A1\u72B6\u6001\u6765\u63A7\u5236\u5F53\u524D\u5217\u662F\u5426\u663E\u793A\uFF0Cv2.4.0+
+  ifShow?: boolean | ((action: ActionItem) => boolean);
+  // \u70B9\u51FB\u56DE\u8C03
+  onClick?: Fn;
+  // Tooltip\u914D\u7F6E\uFF0C2.5.3\u4EE5\u4E0A\u7248\u672C\u652F\u6301\uFF0C\u53EF\u4EE5\u914D\u7F6E\u4E3Astring\uFF0C\u6216\u8005\u5B8C\u6574\u7684tooltip\u5C5E\u6027
+  tooltip?: string | TooltipProps
+}
+

\u6709\u5173TooltipProps\u7684\u8BF4\u660E\uFF0C\u8BF7\u53C2\u8003tooltip

PopConfirm

export interface PopConfirm {
+  title: string;
+  okText?: string;
+  cancelText?: string;
+  confirm: Fn;
+  cancel?: Fn;
+  icon?: string;
+}
+

TableImg

\u7528\u4E8E\u6E32\u67D3\u5355\u5143\u683C\u56FE\u7247,\u652F\u6301\u56FE\u7247\u9884\u89C8

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
imgListstring[]--\u56FE\u7247\u5730\u5740\u5217\u8868
sizenumber--\u56FE\u7247\u5927\u5C0F
simpleShowbooleanfalsetrue/false\u7B80\u5355\u663E\u793A\u6A21\u5F0F\uFF08\u53EA\u663E\u793A\u7B2C\u4E00\u5F20\u56FE\u7247\uFF092.5.0
showBadgebooleantruetrue/false\u7B80\u5355\u6A21\u5F0F\u4E0B\u662F\u5426\u663E\u793A\u8BA1\u6570Badge2.5.0
marginnumber4-\u5E38\u89C4\u6A21\u5F0F\u4E0B\u7684\u56FE\u7247\u95F4\u8DDD2.5.0
srcPrefixstring--\u5728\u6BCF\u4E00\u4E2A\u56FE\u7247src\u524D\u63D2\u5165\u7684\u5185\u5BB92.5.0

\u5168\u5C40\u914D\u7F6E

\u5728componentsSettings \u53EF\u4EE5\u914D\u7F6E\u5168\u5C40\u53C2\u6570\u3002\u7528\u4E8E\u7EDF\u4E00\u6574\u4E2A\u9879\u76EE\u7684\u98CE\u683C\u3002\u53EF\u4EE5\u901A\u8FC7 props \u4F20\u503C\u8986\u76D6

`,148),e=[o];function c(l,u,d,r,i,k){return s(),a("div",null,e)}var b=n(p,[["render",c]]);export{m as __pageData,b as default}; diff --git a/assets/components_table.md.aca1b158.lean.js b/assets/components_table.md.aca1b158.lean.js new file mode 100644 index 00000000..be681ed6 --- /dev/null +++ b/assets/components_table.md.aca1b158.lean.js @@ -0,0 +1,312 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"Table \u8868\u683C","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":3,"title":"\u793A\u4F8B","slug":"\u793A\u4F8B"},{"level":3,"title":"template \u793A\u4F8B","slug":"template-\u793A\u4F8B"},{"level":3,"title":"BasicColumn \u548C tableAction \u901A\u8FC7\u6743\u9650\u548C\u4E1A\u52A1\u63A7\u5236\u663E\u793A\u9690\u85CF\u7684\u793A\u4F8B","slug":"basiccolumn-\u548C-tableaction-\u901A\u8FC7\u6743\u9650\u548C\u4E1A\u52A1\u63A7\u5236\u663E\u793A\u9690\u85CF\u7684\u793A\u4F8B"},{"level":2,"title":"useTable","slug":"usetable"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"Methods","slug":"methods"},{"level":2,"title":"Props","slug":"props"},{"level":3,"title":"TableSetting","slug":"tablesetting"},{"level":2,"title":"BasicColumn","slug":"basiccolumn"},{"level":3,"title":"EditComponentType","slug":"editcomponenttype"},{"level":3,"title":"CellFormat","slug":"cellformat"},{"level":2,"title":"\u4E8B\u4EF6","slug":"\u4E8B\u4EF6"},{"level":2,"title":"Slots","slug":"slots"},{"level":2,"title":"Form-Slots","slug":"form-slots"},{"level":2,"title":"ColumnSetting\u7EC4\u4EF6","slug":"columnsetting\u7EC4\u4EF6"},{"level":2,"title":"\u5185\u7F6E\u7EC4\u4EF6\uFF08\u53EA\u80FD\u7528\u4E8E\u8868\u683C\u5185\u90E8\uFF09","slug":"\u5185\u7F6E\u7EC4\u4EF6\uFF08\u53EA\u80FD\u7528\u4E8E\u8868\u683C\u5185\u90E8\uFF09"},{"level":3,"title":"TableAction","slug":"tableaction"},{"level":3,"title":"TableImg","slug":"tableimg"},{"level":2,"title":"\u5168\u5C40\u914D\u7F6E","slug":"\u5168\u5C40\u914D\u7F6E"}],"relativePath":"components/table.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

Table \u8868\u683C

\u5BF9 antv \u7684 table \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5

\u5982\u679C\u6587\u6863\u5185\u6CA1\u6709\uFF0C\u53EF\u4EE5\u5C1D\u8BD5\u5728\u5728\u7EBF\u793A\u4F8B\u5185\u5BFB\u627E

Usage

\u793A\u4F8B

<template>
+  <div class="p-4">
+    <BasicTable
+      title="\u57FA\u7840\u793A\u4F8B"
+      titleHelpMessage="\u6E29\u99A8\u63D0\u9192"
+      :columns="columns"
+      :dataSource="data"
+      :canResize="canResize"
+      :loading="loading"
+      :striped="striped"
+      :bordered="border"
+      :pagination="{ pageSize: 20 }"
+    >
+      <template #toolbar>
+        <a-button type="primary"> \u64CD\u4F5C\u6309\u94AE </a-button>
+      </template>
+    </BasicTable>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicTable } from '/@/components/Table';
+  import { getBasicColumns, getBasicData } from './tableData';
+
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      return {
+        columns: getBasicColumns(),
+        data: getBasicData(),
+      };
+    },
+  });
+</script>
+

template \u793A\u4F8B

\u6240\u6709\u53EF\u8C03\u7528\u51FD\u6570\u89C1\u4E0B\u65B9 Methods \u8BF4\u660E

<template>
+  <div class="p-4">
+    <BasicTable
+      :canResize="false"
+      title="RefTable\u793A\u4F8B"
+      titleHelpMessage="\u4F7F\u7528Ref\u8C03\u7528\u8868\u683C\u5185\u65B9\u6CD5"
+      ref="tableRef"
+      :api="api"
+      :columns="columns"
+      rowKey="id"
+      :rowSelection="{ type: 'checkbox' }"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { BasicTable, TableActionType } from '/@/components/Table';
+  import { getBasicColumns, getBasicShortColumns } from './tableData';
+  import { demoListApi } from '/@/api/demo/table';
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      const tableRef = ref<Nullable<TableActionType>>(null);
+
+      function getTableAction() {
+        const tableAction = unref(tableRef);
+        if (!tableAction) {
+          throw new Error('tableAction is null');
+        }
+        return tableAction;
+      }
+      function changeLoading() {
+        getTableAction().setLoading(true);
+        setTimeout(() => {
+          getTableAction().setLoading(false);
+        }, 1000);
+      }
+      return {
+        tableRef,
+        api: demoListApi,
+        columns: getBasicColumns(),
+        changeLoading,
+      };
+    },
+  });
+</script>
+

BasicColumn \u548C tableAction \u901A\u8FC7\u6743\u9650\u548C\u4E1A\u52A1\u63A7\u5236\u663E\u793A\u9690\u85CF\u7684\u793A\u4F8B

<template>
+  <div class="p-4">
+    <BasicTable @register="registerTable">
+      <template #action="{ record }">
+        <TableAction
+          :actions="[
+            {
+              label: '\u7F16\u8F91',
+              onClick: handleEdit.bind(null, record),
+              auth: 'other', // \u6839\u636E\u6743\u9650\u63A7\u5236\u662F\u5426\u663E\u793A: \u65E0\u6743\u9650\uFF0C\u4E0D\u663E\u793A
+            },
+            {
+              label: '\u5220\u9664',
+              icon: 'ic:outline-delete-outline',
+              onClick: handleDelete.bind(null, record),
+              auth: 'super', // \u6839\u636E\u6743\u9650\u63A7\u5236\u662F\u5426\u663E\u793A: \u6709\u6743\u9650\uFF0C\u4F1A\u663E\u793A
+            },
+          ]"
+          :dropDownActions="[
+            {
+              label: '\u542F\u7528',
+              popConfirm: {
+                title: '\u662F\u5426\u542F\u7528\uFF1F',
+                confirm: handleOpen.bind(null, record),
+              },
+              ifShow: (_action) => {
+                return record.status !== 'enable'; // \u6839\u636E\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A: \u975Eenable\u72B6\u6001\u7684\u4E0D\u663E\u793A\u542F\u7528\u6309\u94AE
+              },
+            },
+            {
+              label: '\u7981\u7528',
+              popConfirm: {
+                title: '\u662F\u5426\u7981\u7528\uFF1F',
+                confirm: handleOpen.bind(null, record),
+              },
+              ifShow: () => {
+                return record.status === 'enable'; // \u6839\u636E\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A: enable\u72B6\u6001\u7684\u663E\u793A\u7981\u7528\u6309\u94AE
+              },
+            },
+            {
+              label: '\u540C\u65F6\u63A7\u5236',
+              popConfirm: {
+                title: '\u662F\u5426\u52A8\u6001\u663E\u793A\uFF1F',
+                confirm: handleOpen.bind(null, record),
+              },
+              auth: 'super', // \u540C\u65F6\u6839\u636E\u6743\u9650\u548C\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A
+              ifShow: () => {
+                return true; // \u6839\u636E\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A
+              },
+            },
+          ]"
+        />
+      </template>
+    </BasicTable>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
+
+  import { demoListApi } from '/@/api/demo/table';
+  const columns: BasicColumn[] = [
+    {
+      title: '\u59D3\u540D',
+      dataIndex: 'name',
+      auth: 'test', // \u6839\u636E\u6743\u9650\u63A7\u5236\u662F\u5426\u663E\u793A: \u65E0\u6743\u9650\uFF0C\u4E0D\u663E\u793A
+    },
+    {
+      title: '\u5730\u5740',
+      dataIndex: 'address',
+      auth: 'super', // \u540C\u65F6\u6839\u636E\u6743\u9650\u63A7\u5236\u662F\u5426\u663E\u793A
+      ifShow: (_column) => {
+        return true; // \u6839\u636E\u4E1A\u52A1\u63A7\u5236\u662F\u5426\u663E\u793A
+      },
+    },
+  ];
+  export default defineComponent({
+    components: { BasicTable, TableAction },
+    setup() {
+      const [registerTable] = useTable({
+        title: 'TableAction\u7EC4\u4EF6\u53CA\u56FA\u5B9A\u5217\u793A\u4F8B',
+        api: demoListApi,
+        columns: columns,
+        bordered: true,
+        actionColumn: {
+          width: 250,
+          title: 'Action',
+          dataIndex: 'action',
+          slots: { customRender: 'action' },
+        },
+      });
+      function handleEdit(record: Recordable) {
+        console.log('\u70B9\u51FB\u4E86\u7F16\u8F91', record);
+      }
+      function handleDelete(record: Recordable) {
+        console.log('\u70B9\u51FB\u4E86\u5220\u9664', record);
+      }
+      function handleOpen(record: Recordable) {
+        console.log('\u70B9\u51FB\u4E86\u542F\u7528', record);
+      }
+      return {
+        registerTable,
+        handleEdit,
+        handleDelete,
+        handleOpen,
+      };
+    },
+  });
+</script>
+

useTable

\u4F7F\u7528\u7EC4\u4EF6\u81EA\u5E26\u7684 useTable \u53EF\u4EE5\u65B9\u4FBF\u4F7F\u7528\u8868\u5355

\u4E0B\u9762\u662F\u4E00\u4E2A\u4F7F\u7528\u7B80\u5355\u8868\u683C\u7684\u793A\u4F8B\uFF0C

<template>
+  <BasicTable @register="registerTable" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTable, useTable } from '/@/components/Table';
+  import { getBasicColumns, getBasicShortColumns } from './tableData';
+  import { demoListApi } from '/@/api/demo/table';
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      const [
+        registerTable,
+        {
+          setLoading,
+        },
+      ] = useTable({
+        api: demoListApi,
+        columns: getBasicColumns(),
+      });
+
+      function changeLoading() {
+        setLoading(true);
+        setTimeout(() => {
+          setLoading(false);
+        }, 1000);
+      }
+      }
+      return {
+        registerTable,
+        changeLoading,
+      };
+    },
+  });
+</script>
+

Usage

\u7528\u4E8E\u8C03\u7528 Table \u5185\u90E8\u65B9\u6CD5\u53CA table \u53C2\u6570\u914D\u7F6E

// \u8868\u683C\u7684props\u4E5F\u53EF\u4EE5\u76F4\u63A5\u6CE8\u518C\u5230useTable\u5185\u90E8
+const [register, methods] = useTable(props);
+

register

register \u7528\u4E8E\u6CE8\u518C useTable\uFF0C\u5982\u679C\u9700\u8981\u4F7F\u7528useTable\u63D0\u4F9B\u7684 api\uFF0C\u5FC5\u987B\u5C06 register \u4F20\u5165\u7EC4\u4EF6\u7684 onRegister

<template>
+  <BasicTable @register="register" />
+</template>
+<script>
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register] = useTable();
+      return { register };
+    },
+  });
+</script>
+

Methods

setProps

\u7C7B\u578B\uFF1A(props: Partial<BasicTableProps>) => void

\u8BF4\u660E: \u7528\u4E8E\u8BBE\u7F6E\u8868\u683C\u53C2\u6570

reload

\u7C7B\u578B\uFF1A(opt?: FetchParams) => Promise<void>

\u8BF4\u660E: \u5237\u65B0\u8868\u683C

redoHeight

\u7C7B\u578B\uFF1A() => void

\u8BF4\u660E: \u91CD\u65B0\u8BA1\u7B97\u8868\u683C\u9AD8\u5EA6

setLoading

\u7C7B\u578B\uFF1A(loading: boolean) => void

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u683C loading \u72B6\u6001

getDataSource

\u83B7\u53D6\u8868\u683C\u6570\u636E

\u7C7B\u578B\uFF1A<T = Recordable>() => T[]

\u8BF4\u660E: \u83B7\u53D6\u8868\u683C\u6570\u636E

getRawDataSource

\u83B7\u53D6\u540E\u7AEF\u63A5\u53E3\u539F\u59CB\u6570\u636E

\u7C7B\u578B\uFF1A<T = Recordable>() => T

\u8BF4\u660E: \u83B7\u53D6\u540E\u7AEF\u63A5\u53E3\u539F\u59CB\u6570\u636E

getColumns

\u7C7B\u578B\uFF1A(opt?: GetColumnsParams) => BasicColumn[]

\u8BF4\u660E: \u83B7\u53D6\u8868\u683C\u6570\u636E

setColumns

\u7C7B\u578B\uFF1A(columns: BasicColumn[] | string[]) => void

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u5934\u6570\u636E

setTableData

\u7C7B\u578B\uFF1A<T = Recordable>(values: T[]) => void

\u8BF4\u660E: \u8BBE\u7F6E\u8868\u683C\u6570\u636E

setPagination

\u7C7B\u578B\uFF1A(info: Partial<PaginationProps>) => void

\u8BF4\u660E: \u8BBE\u7F6E\u5206\u9875\u4FE1\u606F

deleteSelectRowByKey

\u7C7B\u578B\uFF1A(key: string) => void

\u8BF4\u660E: \u6839\u636E key \u5220\u9664\u53D6\u6D88\u9009\u4E2D\u884C

getSelectRowKeys

\u7C7B\u578B\uFF1A() => string[]

\u8BF4\u660E: \u83B7\u53D6\u9009\u4E2D\u884C\u7684 keys

getSelectRows

\u7C7B\u578B\uFF1A<T = Recordable>() => T[]

\u8BF4\u660E: \u83B7\u53D6\u9009\u4E2D\u884C\u7684 rows

clearSelectedRowKeys

\u7C7B\u578B\uFF1A() => void

\u8BF4\u660E: \u6E05\u7A7A\u9009\u4E2D\u884C

setSelectedRowKeys

\u7C7B\u578B\uFF1A(rowKeys: string[] | number[]) => void

\u8BF4\u660E: \u8BBE\u7F6E\u9009\u4E2D\u884C

getPaginationRef

\u7C7B\u578B\uFF1A() => PaginationProps | boolean

\u8BF4\u660E: \u83B7\u53D6\u5F53\u524D\u5206\u9875\u4FE1\u606F

getShowPagination

\u7C7B\u578B\uFF1A() => boolean

\u8BF4\u660E: \u83B7\u53D6\u5F53\u524D\u662F\u5426\u663E\u793A\u5206\u9875

setShowPagination

\u7C7B\u578B\uFF1A(show: boolean) => Promise<void>

\u8BF4\u660E: \u8BBE\u7F6E\u5F53\u524D\u662F\u5426\u663E\u793A\u5206\u9875

getRowSelection

\u7C7B\u578B\uFF1A() => TableRowSelection<Recordable>

\u8BF4\u660E: \u83B7\u53D6\u52FE\u9009\u6846\u4FE1\u606F

updateTableData

\u7C7B\u578B\uFF1A(index: number, key: string, value: any)=>void

\u8BF4\u660E: \u66F4\u65B0\u8868\u683C\u6570\u636E

updateTableDataRecord

\u7C7B\u578B\uFF1A (rowKey: string | number, record: Recordable) => Recordable | void

\u8BF4\u660E\uFF1A \u6839\u636E\u552F\u4E00\u7684 rowKey \u66F4\u65B0\u6307\u5B9A\u884C\u7684\u6570\u636E.\u53EF\u7528\u4E8E\u4E0D\u5237\u65B0\u6574\u4E2A\u8868\u683C\u800C\u5C40\u90E8\u66F4\u65B0\u6570\u636E

deleteTableDataRecord

\u7C7B\u578B\uFF1A (rowKey: string | number | string[] | number[]) => void

\u8BF4\u660E\uFF1A \u6839\u636E\u552F\u4E00\u7684rowKey \u52A8\u6001\u5220\u9664\u6307\u5B9A\u884C\u7684\u6570\u636E.\u53EF\u7528\u4E8E\u4E0D\u5237\u65B0\u6574\u4E2A\u8868\u683C\u800C\u5C40\u90E8\u66F4\u65B0\u6570\u636E

insertTableDataRecord

\u7C7B\u578B\uFF1A (record: Recordable, index?: number) => Recordable | void

\u8BF4\u660E\uFF1A \u53EF\u6839\u636E\u4F20\u5165\u7684 index \u503C\u51B3\u5B9A\u63D2\u5165\u6570\u636E\u884C\u7684\u4F4D\u7F6E\uFF0C\u4E0D\u4F20\u5219\u662F\u987A\u5E8F\u63D2\u5165\uFF0C\u53EF\u7528\u4E8E\u4E0D\u5237\u65B0\u6574\u4E2A\u8868\u683C\u800C\u5C40\u90E8\u66F4\u65B0\u6570\u636E

getForm

\u7C7B\u578B\uFF1A() => FormActionType

\u8BF4\u660E: \u5982\u679C\u5F00\u542F\u4E86\u641C\u7D22\u533A\u57DF\u3002\u53EF\u4EE5\u901A\u8FC7\u8BE5\u51FD\u6570\u83B7\u53D6\u8868\u5355\u5BF9\u8C61\u51FD\u6570\u8FDB\u884C\u64CD\u4F5C

expandAll

\u7C7B\u578B\uFF1A() => void

\u8BF4\u660E: \u5C55\u5F00\u6811\u5F62\u8868\u683C

collapseAll

\u7C7B\u578B\uFF1A() => void

\u8BF4\u660E: \u6298\u53E0\u6811\u5F62\u8868\u683C

Props

\u6E29\u99A8\u63D0\u9192

  • \u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv table
  • \u6CE8\u610F\uFF1AdefaultExpandAllRows\u3001defaultExpandedRowKeys \u5C5E\u6027\u5728basicTable\u4E2D\u4E0D\u53D7\u652F\u6301\uFF0C\u5E76\u4E14\u5728antv table v2.2.0\u4E4B\u540E\u4E5F\u88AB\u79FB\u9664\u3002
\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
clickToRowSelectbooleantrue-\u70B9\u51FB\u884C\u662F\u5426\u9009\u4E2D checkbox \u6216\u8005 radio\u3002\u9700\u8981\u5F00\u542F
sortFn(sortInfo: SorterResult<any>) => any--\u81EA\u5B9A\u4E49\u6392\u5E8F\u65B9\u6CD5\u3002\u89C1\u4E0B\u65B9\u5168\u5C40\u914D\u7F6E\u8BF4\u660E
filterFn(sortInfo: Partial<Recordable<string[]>>) => any--\u81EA\u5B9A\u4E49\u8FC7\u6EE4\u65B9\u6CD5\u3002\u89C1\u4E0B\u65B9\u5168\u5C40\u914D\u7F6E\u8BF4\u660E
showTableSettingbooleanfalse-\u663E\u793A\u8868\u683C\u8BBE\u7F6E\u5DE5\u5177
tableSettingTableSetting--\u8868\u683C\u8BBE\u7F6E\u5DE5\u5177\u914D\u7F6E\uFF0C\u89C1\u4E0B\u65B9 TableSetting
stripedbooleantrue-\u6591\u9A6C\u7EB9
insetbooleanfalse-\u53D6\u6D88\u8868\u683C\u7684\u9ED8\u8BA4 padding
autoCreateKeybooleantrue-\u662F\u5426\u81EA\u52A8\u751F\u6210 key
showSummarybooleanfalse-\u662F\u5426\u663E\u793A\u5408\u8BA1\u884C
summaryDataany[]--\u81EA\u5B9A\u4E49\u5408\u8BA1\u6570\u636E\u3002\u5982\u679C\u6709\u5219\u663E\u793A\u8BE5\u6570\u636E
emptyDataIsShowTablebooleantrue-\u5728\u542F\u7528\u641C\u7D22\u8868\u5355\u7684\u524D\u63D0\u4E0B\uFF0C\u662F\u5426\u5728\u8868\u683C\u6CA1\u6709\u6570\u636E\u7684\u65F6\u5019\u663E\u793A\u8868\u683C
summaryFunc(...arg) => any[]--\u8BA1\u7B97\u5408\u8BA1\u884C\u7684\u65B9\u6CD5
canRowDragbooleanfalse-\u662F\u5426\u53EF\u62D6\u62FD\u884C\u6392\u5E8F
canColDragbooleanfalse-\u662F\u5426\u53EF\u62D6\u62FD\u5217
isTreeTablebooleanfalse-\u662F\u5426\u6811\u8868
api(...arg: any) => Promise<any>--\u8BF7\u6C42\u63A5\u53E3\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5C06src/api\u5185\u7684\u51FD\u6570\u76F4\u63A5\u4F20\u5165
beforeFetch(T)=>T--\u8BF7\u6C42\u4E4B\u524D\u5BF9\u53C2\u6570\u8FDB\u884C\u5904\u7406
afterFetch(T)=>T--\u8BF7\u6C42\u4E4B\u540E\u5BF9\u8FD4\u56DE\u503C\u8FDB\u884C\u5904\u7406
handleSearchInfoFn(T)=>T--\u5F00\u542F\u8868\u5355\u540E\uFF0C\u5728\u8BF7\u6C42\u4E4B\u524D\u5904\u7406\u641C\u7D22\u6761\u4EF6\u53C2\u6570
fetchSettingFetchSetting--\u63A5\u53E3\u8BF7\u6C42\u914D\u7F6E\uFF0C\u53EF\u4EE5\u914D\u7F6E\u8BF7\u6C42\u7684\u5B57\u6BB5\u548C\u54CD\u5E94\u7684\u5B57\u6BB5\u540D\uFF0C\u89C1\u4E0B\u65B9\u5168\u5C40\u914D\u7F6E\u8BF4\u660E
immediatebooleantrue-\u7EC4\u4EF6\u52A0\u8F7D\u540E\u662F\u5426\u7ACB\u5373\u8BF7\u6C42\u63A5\u53E3\uFF0C\u5728 api \u6709\u4F20\u7684\u60C5\u51B5\u4E0B\uFF0C\u5982\u679C\u4E3A false\uFF0C\u9700\u8981\u81EA\u884C\u4F7F\u7528 reload \u52A0\u8F7D\u8868\u683C\u6570\u636E
searchInfoany--\u989D\u5916\u7684\u8BF7\u6C42\u53C2\u6570
useSearchFormbooleanfalse-\u4F7F\u7528\u641C\u7D22\u8868\u5355
formConfigany--\u8868\u5355\u914D\u7F6E\uFF0C\u53C2\u8003\u8868\u5355\u7EC4\u4EF6\u7684 Props
columnsany--\u8868\u5355\u5217\u4FE1\u606F BasicColumn[]
showIndexColumnbooleanture-\u662F\u5426\u663E\u793A\u5E8F\u53F7\u5217
indexColumnPropsany--\u5E8F\u53F7\u5217\u914D\u7F6E BasicColumn
actionColumnany--\u8868\u683C\u53F3\u4FA7\u64CD\u4F5C\u5217\u914D\u7F6E BasicColumn
ellipsisbooleantrue-\u6587\u672C\u8D85\u8FC7\u5BBD\u5EA6\u662F\u5426\u663E\u793A...
canResizebooleantrue-\u662F\u5426\u53EF\u4EE5\u81EA\u9002\u5E94\u9AD8\u5EA6(\u5982\u679C\u7F6E\u4E8EPageWrapper\u7EC4\u4EF6\u5185\uFF0C\u8BF7\u52FF\u542F\u7528PageWrapper\u7684fixedHeight\u5C5E\u6027\uFF0C\u4E8C\u8005\u4E0D\u53EF\u540C\u65F6\u4F7F\u7528)
clearSelectOnPageChangebooleanfalse-\u5207\u6362\u9875\u7801\u662F\u5426\u91CD\u7F6E\u52FE\u9009\u72B6\u6001
resizeHeightOffsetnumber0-\u8868\u683C\u81EA\u9002\u5E94\u9AD8\u5EA6\u8BA1\u7B97\u7ED3\u679C\u4F1A\u51CF\u53BB\u8FD9\u4E2A\u503C
rowSelectionany--\u9009\u62E9\u5217\u914D\u7F6E
titlestring--\u8868\u683C\u6807\u9898
titleHelpMessagestring \uFF5C string[]--\u8868\u683C\u6807\u9898\u53F3\u4FA7\u6E29\u99A8\u63D0\u9192
maxHeightnumber--\u8868\u683C\u6700\u5927\u9AD8\u5EA6\uFF0C\u8D85\u51FA\u4F1A\u663E\u793A\u6EDA\u52A8\u6761
dataSourceany[]--\u8868\u683C\u6570\u636E\uFF0C\u975E api \u52A0\u8F7D\u60C5\u51B5
borderedbooleanfalse-\u662F\u5426\u663E\u793A\u8868\u683C\u8FB9\u6846
paginationany--\u5206\u9875\u4FE1\u606F\u914D\u7F6E\uFF0C\u4E3A false \u4E0D\u663E\u793A\u5206\u9875
loadingbooleanfalse-\u8868\u683C loading \u72B6\u6001
scrollany--\u53C2\u8003\u5B98\u65B9\u6587\u6863 scroll
beforeEditSubmit({record: Recordable,index: number,key: string | number,value: any}) => Promise<any>--\u5355\u5143\u683C\u7F16\u8F91\u72B6\u6001\u63D0\u4EA4\u56DE\u8C03\uFF0C\u8FD4\u56DEfalse\u5C06\u963B\u6B62\u5355\u5143\u683C\u63D0\u4EA4\u6570\u636E\u5230table\u3002\u8BE5\u56DE\u8C03\u5728\u884C\u7F16\u8F91\u6A21\u5F0F\u4E0B\u65E0\u6548\u30022.7.2

TableSetting

{
+  // \u662F\u5426\u663E\u793A\u5237\u65B0\u6309\u94AE
+  redo?: boolean;
+  // \u662F\u5426\u663E\u793A\u5C3A\u5BF8\u8C03\u6574\u6309\u94AE
+  size?: boolean;
+  // \u662F\u5426\u663E\u793A\u5B57\u6BB5\u8C03\u6574\u6309\u94AE
+  setting?: boolean;
+  // \u662F\u5426\u663E\u793A\u5168\u5C4F\u6309\u94AE
+  fullScreen?: boolean;
+}
+

BasicColumn

\u9664 \u53C2\u8003\u5B98\u65B9 Column \u914D\u7F6E\u5916\uFF0C\u6269\u5C55\u4EE5\u4E0B\u53C2\u6570

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
defaultHiddenbooleanfalse-\u9ED8\u8BA4\u9690\u85CF\uFF0C\u53EF\u5728\u5217\u914D\u7F6E\u663E\u793A
helpMessagestring\uFF5Cstring[]--\u5217\u5934\u53F3\u4FA7\u5E2E\u52A9\u6587\u672C
editboolean--\u662F\u5426\u5F00\u542F\u5355\u5143\u683C\u7F16\u8F91
editRowboolean--\u662F\u5426\u5F00\u542F\u884C\u7F16\u8F91
editablebooleanfalse-\u662F\u5426\u5904\u4E8E\u7F16\u8F91\u72B6\u6001
editComponentComponentTypeInput-\u7F16\u8F91\u7EC4\u4EF6
editComponentPropsany--\u5BF9\u5E94\u7F16\u8F91\u7EC4\u4EF6\u7684 props
editRule((text: string, record: Recordable) => Promise<string>)--\u5BF9\u5E94\u7F16\u8F91\u7EC4\u4EF6\u7684\u8868\u5355\u6821\u9A8C
editValueMap(value: any) => string--\u5BF9\u5E94\u5355\u5143\u683C\u503C\u679A\u4E3E
onEditRow\uFF08\uFF09=>void--\u89E6\u53D1\u884C\u7F16\u8F91
formatCellFormat--\u5355\u5143\u683C\u683C\u5F0F\u5316
authRoleEnum \uFF5C RoleEnum[] \uFF5C string \uFF5C string[]--\u6839\u636E\u6743\u9650\u7F16\u7801\u6765\u63A7\u5236\u5F53\u524D\u5217\u662F\u5426\u663E\u793A
ifShowboolean \uFF5C ((action: ActionItem) => boolean)--\u6839\u636E\u4E1A\u52A1\u72B6\u6001\u6765\u63A7\u5236\u5F53\u524D\u5217\u662F\u5426\u663E\u793A

EditComponentType

export type ComponentType =
+  | 'Input'
+  | 'InputNumber'
+  | 'Select'
+  | 'ApiSelect'
+  | 'Checkbox'
+  | 'Switch'
+  | 'DatePicker'  // v2.5.0 \u4EE5\u4E0A
+  | 'TimePicker'; // v2.5.0 \u4EE5\u4E0A
+

CellFormat

export type CellFormat =
+  | string
+  | ((text: string, record: Recordable, index: number) => string | number)
+  | Map<string | number, any>;
+

\u4E8B\u4EF6

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u4E8B\u4EF6\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 event \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv table

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
fetch-successFunction({items,total})\u63A5\u53E3\u8BF7\u6C42\u6210\u529F\u540E\u89E6\u53D1
fetch-errorFunction(error)\u9519\u8BEF\u4FE1\u606F
selection-changeFunction({keys\uFF0Crows})\u52FE\u9009\u4E8B\u4EF6\u89E6\u53D1
row-clickFunction(record, index, event)\u884C\u70B9\u51FB\u89E6\u53D1
row-dbClickFunction(record, index, event)\u884C\u53CC\u51FB\u89E6\u53D1
row-contextmenuFunction(record, index, event)\u884C\u53F3\u952E\u89E6\u53D1
row-mouseenterFunction(record, index, event)\u884C\u79FB\u5165\u89E6\u53D1
row-mouseleaveFunction(record, index, event)\u884C\u79FB\u51FA\u89E6\u53D1
edit-endFunction({record, index, key, value})\u5355\u5143\u683C\u7F16\u8F91\u5B8C\u6210\u89E6\u53D1
edit-cancelFunction({record, index, key, value})\u5355\u5143\u683C\u53D6\u6D88\u7F16\u8F91\u89E6\u53D1
edit-row-endFunction()\u884C\u7F16\u8F91\u7ED3\u675F\u89E6\u53D1
edit-changeFunction({column,value,record})\u5355\u5143\u683C\u7F16\u8F91\u7EC4\u4EF6\u7684 value \u53D1\u751F\u53D8\u5316\u65F6\u89E6\u53D1

edit-change \u8BF4\u660E

\u4ECE\u7248\u672C 2.4.2 \u8D77\uFF0C\u5BF9\u4E8E edit-change \u4E8B\u4EF6\uFF0Crecord \u4E2D\u7684 editValueRefs \u88C5\u8F7D\u4E86\u5F53\u524D\u884C\u7684\u6240\u6709\u7F16\u8F91\u7EC4\u4EF6\uFF08\u5982\u679C\u6709\u7684\u8BDD\uFF09\u7684\u503C\u7684 ref \u5BF9\u8C61\uFF0C\u53EF\u7528\u4E8E\u5904\u7406\u540C\u4E00\u884C\u4E2D\u7684\u7F16\u8F91\u7EC4\u4EF6\u7684\u8054\u52A8\u3002\u8BF7\u770B\u4E0B\u9762\u7684\u4F8B\u5B50

      function onEditChange({ column, record }) {
+        // \u5F53\u540C\u4E00\u884C\u7684\u5355\u4EF7\u6216\u8005\u6570\u91CF\u53D1\u751F\u53D8\u5316\u65F6\uFF0C\u66F4\u65B0\u5408\u8BA1\u91D1\u989D\uFF08\u4E09\u4E2A\u6570\u636E\u5747\u4E3A\u5F53\u524D\u884C\u7F16\u8F91\u7EC4\u4EF6\u7684\u503C\uFF09
+        if (column.dataIndex === 'qty' || column.dataIndex === 'price') {
+          const { editValueRefs: { total, qty, price } } = record;
+          total.value = unref(qty) * unref(price);
+        }
+      }
+

Slots

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 slot \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv table

\u540D\u79F0\u8BF4\u660E\u7248\u672C
tableTitle\u8868\u683C\u9876\u90E8\u5DE6\u4FA7\u533A\u57DF
toolbar\u8868\u683C\u9876\u90E8\u53F3\u4FA7\u533A\u57DF
expandedRowRender\u5C55\u5F00\u884C\u533A\u57DF
headerTop\u8868\u683C\u9876\u90E8\u533A\u57DF\uFF08\u6807\u9898\u4E0A\u65B9\uFF092.6.1

Form-Slots

\u5F53\u5F00\u542F form \u8868\u5355\u540E\u3002\u4EE5form-xxxx\u4E3A\u524D\u7F00\u7684 slot \u4F1A\u88AB\u89C6\u4E3A form \u7684 slot

xxxx \u4E3A form \u7EC4\u4EF6\u7684 slot\u3002\u5177\u4F53\u53C2\u8003form \u7EC4\u4EF6\u6587\u6863

e.g

form-submitBefore
+

ColumnSetting\u7EC4\u4EF6

\u5B57\u6BB5\u8C03\u6574\u7EC4\u4EF6

\u63D0\u4F9B\u4E86\u53EF\u89C6\u5316\u64CD\u4F5C\u8868\u683C\u6BCF\u4E00\u5217\u7684\u662F\u5426\u5C55\u793A\u3001\u4F4D\u7F6E\u3001\u56FA\u5B9A\uFF1B\u5305\u62EC\u5E8F\u53F7\u5217\u3001\u52FE\u9009\u5217\u3002\u4F1A\u54CD\u5E94tableMethods\u4E2DsetColumns\u548CsetProps\u65B9\u6CD5\u7684\u66F4\u6539\u5185\u5BB9\u3002

\u503C\u5F97\u6CE8\u610F\u7684\u662F

\u5E8F\u53F7\u5217\u548C\u52FE\u9009\u5217\u662F\u5728table\u7684props\u4E2D\u5B9A\u4E49\u7684\uFF0C\u5BF9\u5E94\u7684\u5B57\u6BB5\u5206\u522B\u662FshowIndexColumn\u3001rowSelection\u3002\u56E0\u6B64\u5728\u52A8\u6001\u6539\u53D8\u8868\u683C\u5217\u914D\u7F6E\u7684\u65F6\u5019\uFF0C\u5EFA\u8BAE\u4F7F\u7528setProps\u65B9\u6CD5\uFF0C\u5E76\u663E\u5F0F\u5730\u8BBE\u7F6E\u8FD9\u4E24\u4E2A\u5B57\u6BB5\u7684\u503C\u6765\u4FDD\u8BC1\u8FBE\u5230\u9884\u671F\u6548\u679C

// ...
+const [registerTable, { setProps }] = useTable({...})
+
+setProps({
+  columns: [], // \u8868\u683C\u7684\u5217\u914D\u7F6E BasicColumn[]
+  showIndexColumn: false, // \u662F\u5426\u5C55\u793A\u5E8F\u53F7\u5217
+  rowSelection: false // \u52FE\u9009\u5217\u914D\u7F6E
+})
+

\u5185\u7F6E\u7EC4\u4EF6\uFF08\u53EA\u80FD\u7528\u4E8E\u8868\u683C\u5185\u90E8\uFF09

TableAction

\u7528\u4E8E\u8868\u683C\u53F3\u4FA7\u64CD\u4F5C\u5217\u6E32\u67D3

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
actionsActionItem[]--\u53F3\u4FA7\u64CD\u4F5C\u5217\u6309\u94AE\u5217\u8868
dropDownActionsActionItem[]--\u53F3\u4FA7\u64CD\u4F5C\u5217\u66F4\u591A\u4E0B\u62C9\u6309\u94AE\u5217\u8868
stopButtonPropagationbooleanfalsetrue/false\u662F\u5426\u963B\u6B62\u64CD\u4F5C\u6309\u94AE\u7684click\u4E8B\u4EF6\u5192\u6CE12.5.0

ActionItem

export interface ActionItem {
+  // \u6309\u94AE\u6587\u672C
+  label: string;
+  // \u662F\u5426\u7981\u7528
+  disabled?: boolean;
+  // \u6309\u94AE\u989C\u8272
+  color?: 'success' | 'error' | 'warning';
+  // \u6309\u94AE\u7C7B\u578B
+  type?: string;
+  // button\u7EC4\u4EF6props
+  props?: any;
+  // \u6309\u94AE\u56FE\u6807
+  icon?: string;
+  // \u6C14\u6CE1\u786E\u8BA4\u6846
+  popConfirm?: PopConfirm;
+  // \u662F\u5426\u663E\u793A\u5206\u9694\u7EBF\uFF0Cv2.0.0+
+  divider?: boolean;
+  // \u6839\u636E\u6743\u9650\u7F16\u7801\u6765\u63A7\u5236\u5F53\u524D\u5217\u662F\u5426\u663E\u793A\uFF0Cv2.4.0+
+  auth?: RoleEnum | RoleEnum[] | string | string[];
+  // \u6839\u636E\u4E1A\u52A1\u72B6\u6001\u6765\u63A7\u5236\u5F53\u524D\u5217\u662F\u5426\u663E\u793A\uFF0Cv2.4.0+
+  ifShow?: boolean | ((action: ActionItem) => boolean);
+  // \u70B9\u51FB\u56DE\u8C03
+  onClick?: Fn;
+  // Tooltip\u914D\u7F6E\uFF0C2.5.3\u4EE5\u4E0A\u7248\u672C\u652F\u6301\uFF0C\u53EF\u4EE5\u914D\u7F6E\u4E3Astring\uFF0C\u6216\u8005\u5B8C\u6574\u7684tooltip\u5C5E\u6027
+  tooltip?: string | TooltipProps
+}
+

\u6709\u5173TooltipProps\u7684\u8BF4\u660E\uFF0C\u8BF7\u53C2\u8003tooltip

PopConfirm

export interface PopConfirm {
+  title: string;
+  okText?: string;
+  cancelText?: string;
+  confirm: Fn;
+  cancel?: Fn;
+  icon?: string;
+}
+

TableImg

\u7528\u4E8E\u6E32\u67D3\u5355\u5143\u683C\u56FE\u7247,\u652F\u6301\u56FE\u7247\u9884\u89C8

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
imgListstring[]--\u56FE\u7247\u5730\u5740\u5217\u8868
sizenumber--\u56FE\u7247\u5927\u5C0F
simpleShowbooleanfalsetrue/false\u7B80\u5355\u663E\u793A\u6A21\u5F0F\uFF08\u53EA\u663E\u793A\u7B2C\u4E00\u5F20\u56FE\u7247\uFF092.5.0
showBadgebooleantruetrue/false\u7B80\u5355\u6A21\u5F0F\u4E0B\u662F\u5426\u663E\u793A\u8BA1\u6570Badge2.5.0
marginnumber4-\u5E38\u89C4\u6A21\u5F0F\u4E0B\u7684\u56FE\u7247\u95F4\u8DDD2.5.0
srcPrefixstring--\u5728\u6BCF\u4E00\u4E2A\u56FE\u7247src\u524D\u63D2\u5165\u7684\u5185\u5BB92.5.0

\u5168\u5C40\u914D\u7F6E

\u5728componentsSettings \u53EF\u4EE5\u914D\u7F6E\u5168\u5C40\u53C2\u6570\u3002\u7528\u4E8E\u7EDF\u4E00\u6574\u4E2A\u9879\u76EE\u7684\u98CE\u683C\u3002\u53EF\u4EE5\u901A\u8FC7 props \u4F20\u503C\u8986\u76D6

__VP_STATIC_END__`,148),e=[o];function c(l,u,d,r,i,k){return s(),a("div",null,e)}var b=n(p,[["render",c]]);export{m as __pageData,b as default}; diff --git a/assets/components_time.md.7f2d3fd3.js b/assets/components_time.md.7f2d3fd3.js new file mode 100644 index 00000000..6634014f --- /dev/null +++ b/assets/components_time.md.7f2d3fd3.js @@ -0,0 +1,22 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Time","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/time.md","lastUpdated":1694442156385}',p={},e=t(`

Time

\u76F8\u5BF9\u65F6\u95F4\u7EC4\u4EF6

Usage

<template>
+  <Time :value="time" />
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs } from 'vue';
+  import { Time } from '/@/components/Time';
+
+  export default defineComponent({
+    components: { Time },
+    setup() {
+      const now = new Date().getTime();
+      const state = reactive({
+        time: now - 60 * 3 * 1000,
+      });
+      return {
+        ...toRefs(state),
+        now,
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valuestring,Date,number--\u65F6\u95F4\u503C
stepnumber60-\u5237\u65B0\u65F6\u95F4
modestringrelative-\u6A21\u5F0F\uFF0Cdate:\u65E5\u671F\uFF0Cdatetime:\u65F6\u95F4\u6233\uFF0Crelative:\u76F8\u5BF9\u65F6\u95F4
`,6),o=[e];function c(u,l,i,k,r,d){return a(),s("div",null,o)}var g=n(p,[["render",c]]);export{h as __pageData,g as default}; diff --git a/assets/components_time.md.7f2d3fd3.lean.js b/assets/components_time.md.7f2d3fd3.lean.js new file mode 100644 index 00000000..208cb98a --- /dev/null +++ b/assets/components_time.md.7f2d3fd3.lean.js @@ -0,0 +1,22 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"Time","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"}],"relativePath":"components/time.md","lastUpdated":1694442156385}',p={},e=t(`__VP_STATIC_START__

Time

\u76F8\u5BF9\u65F6\u95F4\u7EC4\u4EF6

Usage

<template>
+  <Time :value="time" />
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs } from 'vue';
+  import { Time } from '/@/components/Time';
+
+  export default defineComponent({
+    components: { Time },
+    setup() {
+      const now = new Date().getTime();
+      const state = reactive({
+        time: now - 60 * 3 * 1000,
+      });
+      return {
+        ...toRefs(state),
+        now,
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valuestring,Date,number--\u65F6\u95F4\u503C
stepnumber60-\u5237\u65B0\u65F6\u95F4
modestringrelative-\u6A21\u5F0F\uFF0Cdate:\u65E5\u671F\uFF0Cdatetime:\u65F6\u95F4\u6233\uFF0Crelative:\u76F8\u5BF9\u65F6\u95F4
__VP_STATIC_END__`,6),o=[e];function c(u,l,i,k,r,d){return a(),s("div",null,o)}var g=n(p,[["render",c]]);export{h as __pageData,g as default}; diff --git a/assets/components_tinymce.md.9b9a1b3a.js b/assets/components_tinymce.md.9b9a1b3a.js new file mode 100644 index 00000000..783402dc --- /dev/null +++ b/assets/components_tinymce.md.9b9a1b3a.js @@ -0,0 +1,20 @@ +import{_ as n,f as a,e as t,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Tinymce","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"}],"relativePath":"components/tinymce.md","lastUpdated":1694442156385}',e={},p=s(`

Tinymce

\u5BCC\u6587\u672C\u7EC4\u4EF6\u4F4D\u4E8E src/components/TinyMce

\u5BCC\u6587\u672C\u7EC4\u4EF6\u4F7F\u7528\u7684\u662F CDN \u65B9\u5F0F\u5F15\u5165

\u53EF\u5728 /@/components/TinyMce/src/Editor.vue \u66F4\u6539\u4E0B\u9762 CDN \u5730\u5740

const CDN_URL = 'https://cdn.bootcdn.net/ajax/libs/tinymce/5.5.1';
+

Usage

<template>
+  <Tinymce v-model="value" @change="handleChange" width="100%" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { Tinymce } from '/@/components/Tinymce/index';
+
+  export default defineComponent({
+    components: { Tinymce },
+    setup() {
+      const value = ref('hello world!');
+      function handleChange(value: string) {
+        console.log(value);
+      }
+      return { handleChange, value };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
optionsany{}tinymce \u7684\u914D\u7F6E\u9879
value(v-model)string-\u53CC\u5411\u7ED1\u5B9A\u503C
heightnumber , string400\u9AD8\u5EA6
widthnumber , stringauto\u5BBD\u5EA6
toolbarstring[]-\u5DE5\u5177\u680F
pluginsstring[]-\u63D2\u4EF6
showImageUploadbooleantrue\u662F\u5426\u663E\u793A\u4E0A\u4F20\u6309\u94AE

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8FD4\u56DE\u503C\u8BF4\u660E
change(str:string)=>{}\u5BCC\u6587\u672C\u5185\u5BB9\u6539\u53D8\u89E6\u53D1\u4E8B\u4EF6
`,9),o=[p];function c(l,u,r,d,i,k){return t(),a("div",null,o)}var m=n(e,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_tinymce.md.9b9a1b3a.lean.js b/assets/components_tinymce.md.9b9a1b3a.lean.js new file mode 100644 index 00000000..4349a81e --- /dev/null +++ b/assets/components_tinymce.md.9b9a1b3a.lean.js @@ -0,0 +1,20 @@ +import{_ as n,f as a,e as t,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Tinymce","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"}],"relativePath":"components/tinymce.md","lastUpdated":1694442156385}',e={},p=s(`__VP_STATIC_START__

Tinymce

\u5BCC\u6587\u672C\u7EC4\u4EF6\u4F4D\u4E8E src/components/TinyMce

\u5BCC\u6587\u672C\u7EC4\u4EF6\u4F7F\u7528\u7684\u662F CDN \u65B9\u5F0F\u5F15\u5165

\u53EF\u5728 /@/components/TinyMce/src/Editor.vue \u66F4\u6539\u4E0B\u9762 CDN \u5730\u5740

const CDN_URL = 'https://cdn.bootcdn.net/ajax/libs/tinymce/5.5.1';
+

Usage

<template>
+  <Tinymce v-model="value" @change="handleChange" width="100%" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { Tinymce } from '/@/components/Tinymce/index';
+
+  export default defineComponent({
+    components: { Tinymce },
+    setup() {
+      const value = ref('hello world!');
+      function handleChange(value: string) {
+        console.log(value);
+      }
+      return { handleChange, value };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
optionsany{}tinymce \u7684\u914D\u7F6E\u9879
value(v-model)string-\u53CC\u5411\u7ED1\u5B9A\u503C
heightnumber , string400\u9AD8\u5EA6
widthnumber , stringauto\u5BBD\u5EA6
toolbarstring[]-\u5DE5\u5177\u680F
pluginsstring[]-\u63D2\u4EF6
showImageUploadbooleantrue\u662F\u5426\u663E\u793A\u4E0A\u4F20\u6309\u94AE

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8FD4\u56DE\u503C\u8BF4\u660E
change(str:string)=>{}\u5BCC\u6587\u672C\u5185\u5BB9\u6539\u53D8\u89E6\u53D1\u4E8B\u4EF6
__VP_STATIC_END__`,9),o=[p];function c(l,u,r,d,i,k){return t(),a("div",null,o)}var m=n(e,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_transition.md.7b6dcd29.js b/assets/components_transition.md.7b6dcd29.js new file mode 100644 index 00000000..7ab2f678 --- /dev/null +++ b/assets/components_transition.md.7b6dcd29.js @@ -0,0 +1,95 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const v='{"title":"Transition","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"}],"relativePath":"components/transition.md","lastUpdated":1694442156385}',p={},o=t(`

Transition

\u7528\u4E8E\u9875\u9762/\u7EC4\u4EF6\u5207\u6362\u52A8\u753B

Usage

<template>
+  <div class="p-4">
+    <div class="flex">
+      <Select
+        :options="options"
+        v-model:value="value"
+        placeholder="\u9009\u62E9\u52A8\u753B"
+        :style="{ width: '150px' }"
+      />
+      <a-button type="primary" class="ml-4" @click="start"> start </a-button>
+    </div>
+    <component :is="\`\${value}Transition\`">
+      <div class="box" v-show="show"></div>
+    </component>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { Select } from 'ant-design-vue';
+  import {
+    FadeTransition,
+    ScaleTransition,
+    SlideYTransition,
+    ScrollYTransition,
+    SlideYReverseTransition,
+    ScrollYReverseTransition,
+    SlideXTransition,
+    ScrollXTransition,
+    SlideXReverseTransition,
+    ScrollXReverseTransition,
+    ScaleRotateTransition,
+    ExpandXTransition,
+    ExpandTransition,
+  } from '/@/components/Transition/index';
+
+  const transitionList = [
+    'Fade',
+    'Scale',
+    'SlideY',
+    'ScrollY',
+    'SlideYReverse',
+    'ScrollYReverse',
+    'SlideX',
+    'ScrollX',
+    'SlideXReverse',
+    'ScrollXReverse',
+    'ScaleRotate',
+    'ExpandX',
+    'Expand',
+  ];
+  const options = transitionList.map((item) => ({
+    label: item,
+    value: item,
+    key: item,
+  }));
+
+  export default defineComponent({
+    components: {
+      Select,
+      FadeTransition,
+      ScaleTransition,
+      SlideYTransition,
+      ScrollYTransition,
+      SlideYReverseTransition,
+      ScrollYReverseTransition,
+      SlideXTransition,
+      ScrollXTransition,
+      SlideXReverseTransition,
+      ScrollXReverseTransition,
+      ScaleRotateTransition,
+      ExpandXTransition,
+      ExpandTransition,
+    },
+    setup() {
+      const value = ref('Fade');
+      const show = ref(true);
+      function start() {
+        show.value = false;
+        setTimeout(() => {
+          show.value = true;
+        }, 300);
+      }
+      return { options, value, start, show };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .box {
+    width: 150px;
+    height: 150px;
+    margin-top: 20px;
+    background: pink;
+  }
+</style>
+
`,4),e=[o];function c(u,l,i,k,r,g){return a(),s("div",null,e)}var m=n(p,[["render",c]]);export{v as __pageData,m as default}; diff --git a/assets/components_transition.md.7b6dcd29.lean.js b/assets/components_transition.md.7b6dcd29.lean.js new file mode 100644 index 00000000..16d3d5b4 --- /dev/null +++ b/assets/components_transition.md.7b6dcd29.lean.js @@ -0,0 +1,95 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const v='{"title":"Transition","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"}],"relativePath":"components/transition.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

Transition

\u7528\u4E8E\u9875\u9762/\u7EC4\u4EF6\u5207\u6362\u52A8\u753B

Usage

<template>
+  <div class="p-4">
+    <div class="flex">
+      <Select
+        :options="options"
+        v-model:value="value"
+        placeholder="\u9009\u62E9\u52A8\u753B"
+        :style="{ width: '150px' }"
+      />
+      <a-button type="primary" class="ml-4" @click="start"> start </a-button>
+    </div>
+    <component :is="\`\${value}Transition\`">
+      <div class="box" v-show="show"></div>
+    </component>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { Select } from 'ant-design-vue';
+  import {
+    FadeTransition,
+    ScaleTransition,
+    SlideYTransition,
+    ScrollYTransition,
+    SlideYReverseTransition,
+    ScrollYReverseTransition,
+    SlideXTransition,
+    ScrollXTransition,
+    SlideXReverseTransition,
+    ScrollXReverseTransition,
+    ScaleRotateTransition,
+    ExpandXTransition,
+    ExpandTransition,
+  } from '/@/components/Transition/index';
+
+  const transitionList = [
+    'Fade',
+    'Scale',
+    'SlideY',
+    'ScrollY',
+    'SlideYReverse',
+    'ScrollYReverse',
+    'SlideX',
+    'ScrollX',
+    'SlideXReverse',
+    'ScrollXReverse',
+    'ScaleRotate',
+    'ExpandX',
+    'Expand',
+  ];
+  const options = transitionList.map((item) => ({
+    label: item,
+    value: item,
+    key: item,
+  }));
+
+  export default defineComponent({
+    components: {
+      Select,
+      FadeTransition,
+      ScaleTransition,
+      SlideYTransition,
+      ScrollYTransition,
+      SlideYReverseTransition,
+      ScrollYReverseTransition,
+      SlideXTransition,
+      ScrollXTransition,
+      SlideXReverseTransition,
+      ScrollXReverseTransition,
+      ScaleRotateTransition,
+      ExpandXTransition,
+      ExpandTransition,
+    },
+    setup() {
+      const value = ref('Fade');
+      const show = ref(true);
+      function start() {
+        show.value = false;
+        setTimeout(() => {
+          show.value = true;
+        }, 300);
+      }
+      return { options, value, start, show };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .box {
+    width: 150px;
+    height: 150px;
+    margin-top: 20px;
+    background: pink;
+  }
+</style>
+
__VP_STATIC_END__`,4),e=[o];function c(u,l,i,k,r,g){return a(),s("div",null,e)}var m=n(p,[["render",c]]);export{v as __pageData,m as default}; diff --git a/assets/components_tree.md.5610236b.js b/assets/components_tree.md.5610236b.js new file mode 100644 index 00000000..273e9a25 --- /dev/null +++ b/assets/components_tree.md.5610236b.js @@ -0,0 +1,74 @@ +import{_ as n,f as t,e as s,N as a}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Slots","slug":"slots"},{"level":2,"title":"Methods","slug":"methods"}],"relativePath":"components/tree.md","lastUpdated":1694442156385}',p={},e=a(`

Tree

\u5BF9 antv \u7684 tree \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5

Usage

<template>
+  <BasicTree :treeData="treeData" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTree } from '/@/components/Tree/index';
+  import { treeData } from './data';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { TreeItem } from '/@/components/Tree/index';
+
+  export const treeData: TreeItem[] = [
+    {
+      title: 'parent 1',
+      key: '0-0',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '0-0-0' },
+        {
+          title: 'leaf',
+          key: '0-0-1',
+          children: [
+            { title: 'leaf', key: '0-0-0-0' },
+            { title: 'leaf', key: '0-0-0-1' },
+          ],
+        },
+      ],
+    },
+    {
+      title: 'parent 2',
+      key: '1-1',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '1-1-0' },
+        { title: 'leaf', key: '1-1-1' },
+      ],
+    },
+    {
+      title: 'parent 3',
+      key: '2-2',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '2-2-0' },
+        { title: 'leaf', key: '2-2-1' },
+      ],
+    },
+  ];
+  export default defineComponent({
+    components: { BasicTree, CollapseContainer },
+    setup() {
+      return { treeData };
+    },
+  });
+</script>
+

Props

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv tree

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
treeDataTreeItem[]--\u6811\u7EC4\u4EF6\u6570\u636E
rightMenuListContextMenuItem[]--\u53F3\u952E\u83DC\u5355\u5217\u8868
checkedKeysstring[]--\u52FE\u9009\u7684\u8282\u70B9
selectedKeysstring[]--\u9009\u4E2D\u7684\u8282\u70B9
expandedKeysstring[]--\u5C55\u5F00\u7684\u8282\u70B9
actionListActionItem[]--\u9F20\u6807\u79FB\u52A8\u4E0A\u53BB\u53F3\u8FB9\u64CD\u4F5C\u6309\u94AE\u5217\u8868
titlestring--\u5B9A\u5236\u6807\u9898\u5B57\u7B26\u4E32
toolbarboolean--\u662F\u5426\u663E\u793A\u5DE5\u5177\u680F
searchboolean--\u663E\u793A\u641C\u7D22\u6846
clickRowToExpandboolean--\u662F\u5426\u5728\u70B9\u51FB\u884C\u65F6\u81EA\u52A8\u5C55\u5F00
beforeRightClick(node, event)=>ContextMenuItem[]--\u53F3\u952E\u70B9\u51FB\u56DE\u8C03\uFF0C\u53EF\u8FD4\u56DE\u53F3\u952E\u83DC\u5355\u5217\u8868\u6570\u636E\u6765\u751F\u6210\u53F3\u952E\u83DC\u5355
rightMenuListContextMenuItem[]--\u53F3\u952E\u83DC\u5355\u5217\u8868\u6570\u636E
defaultExpandLevelstring \uFF5C number--\u521D\u6B21\u6E32\u67D3\u540E\u9ED8\u8BA4\u5C55\u5F00\u7684\u5C42\u7EA72.4.1
defaultExpandAllbooleanfalsetrue/false\u521D\u6B21\u6E32\u67D3\u540E\u9ED8\u8BA4\u5168\u90E82.4.1
searchValue(v-model)string--\u5F53\u524D\u641C\u7D22\u8BCD2.7.1

\u6CE8\u610F

defaultExpandLevel\u3001defaultExpandAll \u4EC5\u5728\u521D\u6B21\u6E32\u67D3\u65F6\u751F\u6548\u3002\u5982\u679CbasicTree\u662F\u5728\u521B\u5EFA\u5B8C\u6BD5\u4E4B\u540E\u624D\u8BBE\u7F6E\u7684treeData(\u5982\u5F02\u6B65\u6570\u636E)\uFF0C\u9700\u8981\u5728\u66F4\u65B0\u540E\u81EA\u5DF1\u8C03\u7528basicTree\u63D0\u4F9B\u7684expandAll\u3001filterByLevel\u6765\u6267\u884C\u5C55\u5F00

ActionItem

{
+  // \u6E32\u67D3\u7684\u56FE\u6807
+  render: (record: any) => any;
+  // \u662F\u5426\u663E\u793A
+  show?: boolean | ((record: Recordable) => boolean);
+}
+

ContextMenuItem

{
+  // \u6587\u672C
+  label: string;
+  // \u56FE\u6807
+  icon?: string;
+  // \u662F\u5426\u7981\u7528
+  disabled?: boolean;
+  // \u4E8B\u4EF6
+  handler?: (...arg) => any;
+  // \u662F\u5426\u663E\u793A\u5206\u9694\u7EBF
+  divider?: boolean;
+  // \u5B50\u7EA7\u83DC\u5355\u6570\u636E
+  children?: ContextMenuItem[];
+}
+

Slots

\u6E29\u99A8\u63D0\u9192

\u5B98\u65B9\u6587\u6863\u5185\u7684 slot \u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv tree

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
checkAll(checkAll: boolean) => void\u9009\u62E9\u6240\u6709
expandAll(expandAll: boolean) => void\u5C55\u5F00\u6240\u6709
setExpandedKeys(keys: Keys) => void\u8BBE\u7F6E\u5C55\u5F00\u8282\u70B9
getExpandedKeys() => Keys\u83B7\u53D6\u5C55\u5F00\u8282\u70B9
setSelectedKeys(keys: Keys) => void\u8BBE\u7F6E\u9009\u4E2D\u8282\u70B9
getSelectedKeys() => Keys\u83B7\u53D6\u9009\u4E2D\u8282\u70B9
setCheckedKeys(keys: CheckKeys) => void\u8BBE\u7F6E\u52FE\u9009\u8282\u70B9
getCheckedKeys() => CheckKeys\u83B7\u53D6\u52FE\u9009\u8282\u70B9
filterByLevel(level: number) => void\u663E\u793A\u6307\u5B9A\u7B49\u7EA7
insertNodeByKey(opt: InsertNodeParams) => void\u63D2\u5165\u5B50\u8282\u70B9\u5230\u6307\u5B9A\u8282\u70B9\u5185
deleteNodeByKey(key: string) => void\u6839\u636E key \u5220\u9664\u8282\u70B9
updateNodeByKey(key: string, node: Omit<TreeItem, 'key'>) => void\u6839\u636E key \u66F4\u65B0\u8282\u70B9
setSearchValue(value: string) => void\u8BBE\u7F6E\u5F53\u524D\u641C\u7D22\u8BCD\uFF08v2.7.1\uFF09
getSearchValue() => string\u83B7\u53D6\u5F53\u524D\u641C\u7D22\u8BCD(v2.7.1)
`,16),o=[e];function c(r,l,d,k,i,u){return s(),t("div",null,o)}var h=n(p,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/components_tree.md.5610236b.lean.js b/assets/components_tree.md.5610236b.lean.js new file mode 100644 index 00000000..710157d7 --- /dev/null +++ b/assets/components_tree.md.5610236b.lean.js @@ -0,0 +1,74 @@ +import{_ as n,f as t,e as s,N as a}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Tree","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Slots","slug":"slots"},{"level":2,"title":"Methods","slug":"methods"}],"relativePath":"components/tree.md","lastUpdated":1694442156385}',p={},e=a(`__VP_STATIC_START__

Tree

\u5BF9 antv \u7684 tree \u7EC4\u4EF6\u8FDB\u884C\u5C01\u88C5

Usage

<template>
+  <BasicTree :treeData="treeData" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTree } from '/@/components/Tree/index';
+  import { treeData } from './data';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { TreeItem } from '/@/components/Tree/index';
+
+  export const treeData: TreeItem[] = [
+    {
+      title: 'parent 1',
+      key: '0-0',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '0-0-0' },
+        {
+          title: 'leaf',
+          key: '0-0-1',
+          children: [
+            { title: 'leaf', key: '0-0-0-0' },
+            { title: 'leaf', key: '0-0-0-1' },
+          ],
+        },
+      ],
+    },
+    {
+      title: 'parent 2',
+      key: '1-1',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '1-1-0' },
+        { title: 'leaf', key: '1-1-1' },
+      ],
+    },
+    {
+      title: 'parent 3',
+      key: '2-2',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '2-2-0' },
+        { title: 'leaf', key: '2-2-1' },
+      ],
+    },
+  ];
+  export default defineComponent({
+    components: { BasicTree, CollapseContainer },
+    setup() {
+      return { treeData };
+    },
+  });
+</script>
+

Props

\u6E29\u99A8\u63D0\u9192

\u9664\u4EE5\u4E0B\u53C2\u6570\u5916\uFF0C\u5B98\u65B9\u6587\u6863\u5185\u7684 props \u4E5F\u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv tree

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E\u7248\u672C
treeDataTreeItem[]--\u6811\u7EC4\u4EF6\u6570\u636E
rightMenuListContextMenuItem[]--\u53F3\u952E\u83DC\u5355\u5217\u8868
checkedKeysstring[]--\u52FE\u9009\u7684\u8282\u70B9
selectedKeysstring[]--\u9009\u4E2D\u7684\u8282\u70B9
expandedKeysstring[]--\u5C55\u5F00\u7684\u8282\u70B9
actionListActionItem[]--\u9F20\u6807\u79FB\u52A8\u4E0A\u53BB\u53F3\u8FB9\u64CD\u4F5C\u6309\u94AE\u5217\u8868
titlestring--\u5B9A\u5236\u6807\u9898\u5B57\u7B26\u4E32
toolbarboolean--\u662F\u5426\u663E\u793A\u5DE5\u5177\u680F
searchboolean--\u663E\u793A\u641C\u7D22\u6846
clickRowToExpandboolean--\u662F\u5426\u5728\u70B9\u51FB\u884C\u65F6\u81EA\u52A8\u5C55\u5F00
beforeRightClick(node, event)=>ContextMenuItem[]--\u53F3\u952E\u70B9\u51FB\u56DE\u8C03\uFF0C\u53EF\u8FD4\u56DE\u53F3\u952E\u83DC\u5355\u5217\u8868\u6570\u636E\u6765\u751F\u6210\u53F3\u952E\u83DC\u5355
rightMenuListContextMenuItem[]--\u53F3\u952E\u83DC\u5355\u5217\u8868\u6570\u636E
defaultExpandLevelstring \uFF5C number--\u521D\u6B21\u6E32\u67D3\u540E\u9ED8\u8BA4\u5C55\u5F00\u7684\u5C42\u7EA72.4.1
defaultExpandAllbooleanfalsetrue/false\u521D\u6B21\u6E32\u67D3\u540E\u9ED8\u8BA4\u5168\u90E82.4.1
searchValue(v-model)string--\u5F53\u524D\u641C\u7D22\u8BCD2.7.1

\u6CE8\u610F

defaultExpandLevel\u3001defaultExpandAll \u4EC5\u5728\u521D\u6B21\u6E32\u67D3\u65F6\u751F\u6548\u3002\u5982\u679CbasicTree\u662F\u5728\u521B\u5EFA\u5B8C\u6BD5\u4E4B\u540E\u624D\u8BBE\u7F6E\u7684treeData(\u5982\u5F02\u6B65\u6570\u636E)\uFF0C\u9700\u8981\u5728\u66F4\u65B0\u540E\u81EA\u5DF1\u8C03\u7528basicTree\u63D0\u4F9B\u7684expandAll\u3001filterByLevel\u6765\u6267\u884C\u5C55\u5F00

ActionItem

{
+  // \u6E32\u67D3\u7684\u56FE\u6807
+  render: (record: any) => any;
+  // \u662F\u5426\u663E\u793A
+  show?: boolean | ((record: Recordable) => boolean);
+}
+

ContextMenuItem

{
+  // \u6587\u672C
+  label: string;
+  // \u56FE\u6807
+  icon?: string;
+  // \u662F\u5426\u7981\u7528
+  disabled?: boolean;
+  // \u4E8B\u4EF6
+  handler?: (...arg) => any;
+  // \u662F\u5426\u663E\u793A\u5206\u9694\u7EBF
+  divider?: boolean;
+  // \u5B50\u7EA7\u83DC\u5355\u6570\u636E
+  children?: ContextMenuItem[];
+}
+

Slots

\u6E29\u99A8\u63D0\u9192

\u5B98\u65B9\u6587\u6863\u5185\u7684 slot \u90FD\u652F\u6301\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 antv tree

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
checkAll(checkAll: boolean) => void\u9009\u62E9\u6240\u6709
expandAll(expandAll: boolean) => void\u5C55\u5F00\u6240\u6709
setExpandedKeys(keys: Keys) => void\u8BBE\u7F6E\u5C55\u5F00\u8282\u70B9
getExpandedKeys() => Keys\u83B7\u53D6\u5C55\u5F00\u8282\u70B9
setSelectedKeys(keys: Keys) => void\u8BBE\u7F6E\u9009\u4E2D\u8282\u70B9
getSelectedKeys() => Keys\u83B7\u53D6\u9009\u4E2D\u8282\u70B9
setCheckedKeys(keys: CheckKeys) => void\u8BBE\u7F6E\u52FE\u9009\u8282\u70B9
getCheckedKeys() => CheckKeys\u83B7\u53D6\u52FE\u9009\u8282\u70B9
filterByLevel(level: number) => void\u663E\u793A\u6307\u5B9A\u7B49\u7EA7
insertNodeByKey(opt: InsertNodeParams) => void\u63D2\u5165\u5B50\u8282\u70B9\u5230\u6307\u5B9A\u8282\u70B9\u5185
deleteNodeByKey(key: string) => void\u6839\u636E key \u5220\u9664\u8282\u70B9
updateNodeByKey(key: string, node: Omit<TreeItem, 'key'>) => void\u6839\u636E key \u66F4\u65B0\u8282\u70B9
setSearchValue(value: string) => void\u8BBE\u7F6E\u5F53\u524D\u641C\u7D22\u8BCD\uFF08v2.7.1\uFF09
getSearchValue() => string\u83B7\u53D6\u5F53\u524D\u641C\u7D22\u8BCD(v2.7.1)
__VP_STATIC_END__`,16),o=[e];function c(r,l,d,k,i,u){return s(),t("div",null,o)}var h=n(p,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/components_upload.md.afb4c8e8.js b/assets/components_upload.md.afb4c8e8.js new file mode 100644 index 00000000..376d3f32 --- /dev/null +++ b/assets/components_upload.md.afb4c8e8.js @@ -0,0 +1,31 @@ +import{_ as n,f as t,e as a,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Upload","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Config","slug":"config"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"}],"relativePath":"components/upload.md","lastUpdated":1694442156385}',p={},o=s(`

Upload

\u6587\u4EF6\u4E0A\u4F20\u7EC4\u4EF6

Usage

<template>
+  <BasicUpload :maxSize="20" :maxNumber="10" @change="handleChange" :api="uploadApi" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicUpload } from '/@/components/Upload';
+  import { uploadApi } from '/@/api/sys/upload';
+
+  export default defineComponent({
+    components: { BasicUpload },
+    setup() {
+      return {
+        uploadApi,
+        handleChange: (list: string[]) => {
+          createMessage.info(\`\u5DF2\u4E0A\u4F20\u6587\u4EF6\${JSON.stringify(list)}\`);
+        },
+      };
+    },
+  });
+</script>
+

Config

.env.development \u548C .env.production \u914D\u7F6E\u5F00\u53D1\u548C\u751F\u4EA7\u7684\u6587\u4EF6\u4E0A\u4F20\u5730\u5740

# .env.development
+
+VITE_PROXY=[["/upload","http://localhost:3001/upload"]]
+
+# \u5982\u679C\u6CA1\u6709\u8DE8\u57DF\u95EE\u9898\uFF0C\u5219\u76F4\u63A5\u4F7F\u7528\u771F\u5B9E\u4E0A\u4F20\u5730\u5740
+VITE_GLOB_UPLOAD_URL=/upload
+
+# .env.production
+VITE_GLOB_UPLOAD_URL=/upload
+
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valuestring[]--\u5DF2\u4E0A\u4F20\u7684\u6587\u4EF6\u5217\u8868\uFF0C\u652F\u6301v-model
showPreviewNumberbooleantrue-\u662F\u5426\u663E\u793A\u9884\u89C8\u6570\u91CF
emptyHidePreviewbooleanfalse-\u6CA1\u6709\u4E0A\u4F20\u6587\u4EF6\u65F6\u662F\u5426\u9690\u85CF\u9884\u89C8
helpTextstring--\u5E2E\u52A9\u6587\u672C
maxSizenumber2-\u5355\u4E2A\u6587\u4EF6\u6700\u5927\u4F53\u79EF\uFF0C\u5355\u4F4D M
maxNumbernumberInfinity-\u6700\u5927\u4E0A\u4F20\u6570\u91CF\uFF0CInfinity \u5219\u4E0D\u9650\u5236
acceptstring[]--\u9650\u5236\u4E0A\u4F20\u683C\u5F0F\uFF0C\u53EF\u4F7F\u7528\u6587\u4EF6\u540E\u7F00\u540D(\u70B9\u53F7\u53EF\u9009)\u6216MIME\u5B57\u7B26\u4E32\u3002\u4F8B\u5982 ['.doc,','docx','application/msword','image/*']
multipleboolean--\u5F00\u542F\u591A\u6587\u4EF6\u4E0A\u4F20
uploadParamsany--\u4E0A\u4F20\u643A\u5E26\u7684\u53C2\u6570
apiFn--\u4E0A\u4F20\u63A5\u53E3\uFF0C\u4E3A\u4E0A\u9762\u914D\u7F6E\u7684\u63A5\u53E3

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8FD4\u56DE\u503C\u8BF4\u660E\u7248\u672C
change(fileList)=>void\u6587\u4EF6\u5217\u8868\u5185\u5BB9\u6539\u53D8\u89E6\u53D1\u4E8B\u4EF6
delete(record)=>void\u5728\u4E0A\u4F20\u5217\u8868\u4E2D\u5220\u9664\u6587\u4EF6\u7684\u4E8B\u4EF6
preview-delete(url:string)=>void\u5728\u9884\u89C8\u5217\u8868\u4E2D\u5220\u9664\u6587\u4EF6\u7684\u4E8B\u4EF62.5.3
`,11),e=[o];function c(d,l,u,i,r,k){return a(),t("div",null,e)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_upload.md.afb4c8e8.lean.js b/assets/components_upload.md.afb4c8e8.lean.js new file mode 100644 index 00000000..c0161cc3 --- /dev/null +++ b/assets/components_upload.md.afb4c8e8.lean.js @@ -0,0 +1,31 @@ +import{_ as n,f as t,e as a,N as s}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"Upload","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Config","slug":"config"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Events","slug":"events"}],"relativePath":"components/upload.md","lastUpdated":1694442156385}',p={},o=s(`__VP_STATIC_START__

Upload

\u6587\u4EF6\u4E0A\u4F20\u7EC4\u4EF6

Usage

<template>
+  <BasicUpload :maxSize="20" :maxNumber="10" @change="handleChange" :api="uploadApi" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicUpload } from '/@/components/Upload';
+  import { uploadApi } from '/@/api/sys/upload';
+
+  export default defineComponent({
+    components: { BasicUpload },
+    setup() {
+      return {
+        uploadApi,
+        handleChange: (list: string[]) => {
+          createMessage.info(\`\u5DF2\u4E0A\u4F20\u6587\u4EF6\${JSON.stringify(list)}\`);
+        },
+      };
+    },
+  });
+</script>
+

Config

.env.development \u548C .env.production \u914D\u7F6E\u5F00\u53D1\u548C\u751F\u4EA7\u7684\u6587\u4EF6\u4E0A\u4F20\u5730\u5740

# .env.development
+
+VITE_PROXY=[["/upload","http://localhost:3001/upload"]]
+
+# \u5982\u679C\u6CA1\u6709\u8DE8\u57DF\u95EE\u9898\uFF0C\u5219\u76F4\u63A5\u4F7F\u7528\u771F\u5B9E\u4E0A\u4F20\u5730\u5740
+VITE_GLOB_UPLOAD_URL=/upload
+
+# .env.production
+VITE_GLOB_UPLOAD_URL=/upload
+
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
valuestring[]--\u5DF2\u4E0A\u4F20\u7684\u6587\u4EF6\u5217\u8868\uFF0C\u652F\u6301v-model
showPreviewNumberbooleantrue-\u662F\u5426\u663E\u793A\u9884\u89C8\u6570\u91CF
emptyHidePreviewbooleanfalse-\u6CA1\u6709\u4E0A\u4F20\u6587\u4EF6\u65F6\u662F\u5426\u9690\u85CF\u9884\u89C8
helpTextstring--\u5E2E\u52A9\u6587\u672C
maxSizenumber2-\u5355\u4E2A\u6587\u4EF6\u6700\u5927\u4F53\u79EF\uFF0C\u5355\u4F4D M
maxNumbernumberInfinity-\u6700\u5927\u4E0A\u4F20\u6570\u91CF\uFF0CInfinity \u5219\u4E0D\u9650\u5236
acceptstring[]--\u9650\u5236\u4E0A\u4F20\u683C\u5F0F\uFF0C\u53EF\u4F7F\u7528\u6587\u4EF6\u540E\u7F00\u540D(\u70B9\u53F7\u53EF\u9009)\u6216MIME\u5B57\u7B26\u4E32\u3002\u4F8B\u5982 ['.doc,','docx','application/msword','image/*']
multipleboolean--\u5F00\u542F\u591A\u6587\u4EF6\u4E0A\u4F20
uploadParamsany--\u4E0A\u4F20\u643A\u5E26\u7684\u53C2\u6570
apiFn--\u4E0A\u4F20\u63A5\u53E3\uFF0C\u4E3A\u4E0A\u9762\u914D\u7F6E\u7684\u63A5\u53E3

Events

\u4E8B\u4EF6\u56DE\u8C03\u53C2\u6570\u8FD4\u56DE\u503C\u8BF4\u660E\u7248\u672C
change(fileList)=>void\u6587\u4EF6\u5217\u8868\u5185\u5BB9\u6539\u53D8\u89E6\u53D1\u4E8B\u4EF6
delete(record)=>void\u5728\u4E0A\u4F20\u5217\u8868\u4E2D\u5220\u9664\u6587\u4EF6\u7684\u4E8B\u4EF6
preview-delete(url:string)=>void\u5728\u9884\u89C8\u5217\u8868\u4E2D\u5220\u9664\u6587\u4EF6\u7684\u4E8B\u4EF62.5.3
__VP_STATIC_END__`,11),e=[o];function c(d,l,u,i,r,k){return a(),t("div",null,e)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/components_verify.md.736f36cd.js b/assets/components_verify.md.736f36cd.js new file mode 100644 index 00000000..9d21170a --- /dev/null +++ b/assets/components_verify.md.736f36cd.js @@ -0,0 +1,46 @@ +import{_ as t,f as n,e as a,N as s}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"BasicDragVerify","description":"","frontmatter":{},"headers":[{"level":2,"title":"BasicDragVerify","slug":"basicdragverify-1"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":3,"title":"Methods","slug":"methods"},{"level":2,"title":"RotateDragVerify","slug":"rotatedragverify"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"props","slug":"props-1"},{"level":3,"title":"Methods","slug":"methods-1"}],"relativePath":"components/verify.md","lastUpdated":1694442156385}',p={},e=s(`

BasicDragVerify

\u62D6\u52A8\u6821\u9A8C\u7EC4\u4EF6

BasicDragVerify

Usage

<template>
+  <div class="p-10">
+    <BasicDragVerify @success="handleSuccess" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicDragVerify, DragVerifyActionType, PassingData } from '/@/components/Verify/index';
+  export default defineComponent({
+    components: { BasicDragVerify },
+    setup() {
+      function handleSuccess(data: PassingData) {
+        const { time } = data;
+        createMessage.success(\`\u6821\u9A8C\u6210\u529F,\u8017\u65F6\${time}\u79D2\`);
+      }
+      return {
+        handleSuccess,
+        handleBtnClick,
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
valueboolean-\u662F\u5426\u901A\u8FC7
textstring\u8BF7\u6309\u4F4F\u6ED1\u5757\u62D6\u52A8\u672A\u62D6\u52A8\u65F6\u5019\u663E\u793A\u6587\u5B57
successTextstring\u9A8C\u8BC1\u901A\u8FC7\u9A8C\u8BC1\u6210\u529F\u540E\u663E\u793A\u6587\u672C
heightstring\uFF5Cstring40\u9AD8\u5EA6
widthstring\uFF5Cstring260\u5BBD\u5EA6
circlebooleanfalse\u662F\u5426\u5706\u89D2
wrapStyleany-\u5916\u5C42\u5BB9\u5668\u6837\u5F0F
contentStyleany-\u4E3B\u4F53\u5185\u5BB9\u6837\u5F0F
barStyleany-bar \u6837\u5F0F
actionStyleany-\u62D6\u62FD\u6309\u94AE\u6837\u5F0F

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
resume()=>{}\u8FD8\u539F\u521D\u59CB\u503C

RotateDragVerify

\u56FE\u7247\u8FD8\u539F\u6B63\u65B9\u5411\u6821\u9A8C\u7EC4\u4EF6

Usage

<template>
+  <div class="p-10">
+    <RotateDragVerify :src="img" ref="el" @success="handleSuccess" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { RotateDragVerify } from '/@/components/Verify/index';
+
+  import img from '/@/assets/images/header.jpg';
+  export default defineComponent({
+    components: { RotateDragVerify },
+    setup() {
+      const handleSuccess = () => {
+        console.log('success!');
+      };
+      return {
+        handleSuccess,
+        img,
+      };
+    },
+  });
+</script>
+

props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
srcstring-\u56FE\u7247\u5730\u5740
imgWidthnumber-\u56FE\u7247\u5BBD\u5EA6
imgWrapStyleany-\u56FE\u7247\u5916\u5C42\u5BB9\u5668\u6837\u5F0F
minDegreenumber-\u6700\u5C0F\u65CB\u8F6C\u89D2\u5EA6
maxDegreenumber-\u6700\u5927\u65CB\u8F6C\u89D2\u5EA6
diffDegreenumber-\u8BEF\u5DEE\u89D2\u5EA6
valueboolean-\u662F\u5426\u901A\u8FC7
textstring\u8BF7\u6309\u4F4F\u6ED1\u5757\u62D6\u52A8\u672A\u62D6\u52A8\u65F6\u5019\u663E\u793A\u6587\u5B57
successTextstring\u9A8C\u8BC1\u901A\u8FC7\u9A8C\u8BC1\u6210\u529F\u540E\u663E\u793A\u6587\u672C
heightstring\uFF5Cstring40\u9AD8\u5EA6
widthstring\uFF5Cstring260\u5BBD\u5EA6
circlebooleanfalse\u662F\u5426\u5706\u89D2
wrapStyleany-\u5916\u5C42\u5BB9\u5668\u6837\u5F0F
contentStyleany-\u4E3B\u4F53\u5185\u5BB9\u6837\u5F0F
barStyleany-bar \u6837\u5F0F
actionStyleany-\u62D6\u62FD\u6309\u94AE\u6837\u5F0F

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
resumeFunction\u8FD8\u539F\u521D\u59CB\u503C
`,17),o=[e];function c(d,l,u,r,i,k){return a(),n("div",null,o)}var y=t(p,[["render",c]]);export{h as __pageData,y as default}; diff --git a/assets/components_verify.md.736f36cd.lean.js b/assets/components_verify.md.736f36cd.lean.js new file mode 100644 index 00000000..28731df1 --- /dev/null +++ b/assets/components_verify.md.736f36cd.lean.js @@ -0,0 +1,46 @@ +import{_ as t,f as n,e as a,N as s}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"BasicDragVerify","description":"","frontmatter":{},"headers":[{"level":2,"title":"BasicDragVerify","slug":"basicdragverify-1"},{"level":3,"title":"Usage","slug":"usage"},{"level":3,"title":"Props","slug":"props"},{"level":3,"title":"Methods","slug":"methods"},{"level":2,"title":"RotateDragVerify","slug":"rotatedragverify"},{"level":3,"title":"Usage","slug":"usage-1"},{"level":3,"title":"props","slug":"props-1"},{"level":3,"title":"Methods","slug":"methods-1"}],"relativePath":"components/verify.md","lastUpdated":1694442156385}',p={},e=s(`__VP_STATIC_START__

BasicDragVerify

\u62D6\u52A8\u6821\u9A8C\u7EC4\u4EF6

BasicDragVerify

Usage

<template>
+  <div class="p-10">
+    <BasicDragVerify @success="handleSuccess" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicDragVerify, DragVerifyActionType, PassingData } from '/@/components/Verify/index';
+  export default defineComponent({
+    components: { BasicDragVerify },
+    setup() {
+      function handleSuccess(data: PassingData) {
+        const { time } = data;
+        createMessage.success(\`\u6821\u9A8C\u6210\u529F,\u8017\u65F6\${time}\u79D2\`);
+      }
+      return {
+        handleSuccess,
+        handleBtnClick,
+      };
+    },
+  });
+</script>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
valueboolean-\u662F\u5426\u901A\u8FC7
textstring\u8BF7\u6309\u4F4F\u6ED1\u5757\u62D6\u52A8\u672A\u62D6\u52A8\u65F6\u5019\u663E\u793A\u6587\u5B57
successTextstring\u9A8C\u8BC1\u901A\u8FC7\u9A8C\u8BC1\u6210\u529F\u540E\u663E\u793A\u6587\u672C
heightstring\uFF5Cstring40\u9AD8\u5EA6
widthstring\uFF5Cstring260\u5BBD\u5EA6
circlebooleanfalse\u662F\u5426\u5706\u89D2
wrapStyleany-\u5916\u5C42\u5BB9\u5668\u6837\u5F0F
contentStyleany-\u4E3B\u4F53\u5185\u5BB9\u6837\u5F0F
barStyleany-bar \u6837\u5F0F
actionStyleany-\u62D6\u62FD\u6309\u94AE\u6837\u5F0F

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
resume()=>{}\u8FD8\u539F\u521D\u59CB\u503C

RotateDragVerify

\u56FE\u7247\u8FD8\u539F\u6B63\u65B9\u5411\u6821\u9A8C\u7EC4\u4EF6

Usage

<template>
+  <div class="p-10">
+    <RotateDragVerify :src="img" ref="el" @success="handleSuccess" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { RotateDragVerify } from '/@/components/Verify/index';
+
+  import img from '/@/assets/images/header.jpg';
+  export default defineComponent({
+    components: { RotateDragVerify },
+    setup() {
+      const handleSuccess = () => {
+        console.log('success!');
+      };
+      return {
+        handleSuccess,
+        img,
+      };
+    },
+  });
+</script>
+

props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u8BF4\u660E
srcstring-\u56FE\u7247\u5730\u5740
imgWidthnumber-\u56FE\u7247\u5BBD\u5EA6
imgWrapStyleany-\u56FE\u7247\u5916\u5C42\u5BB9\u5668\u6837\u5F0F
minDegreenumber-\u6700\u5C0F\u65CB\u8F6C\u89D2\u5EA6
maxDegreenumber-\u6700\u5927\u65CB\u8F6C\u89D2\u5EA6
diffDegreenumber-\u8BEF\u5DEE\u89D2\u5EA6
valueboolean-\u662F\u5426\u901A\u8FC7
textstring\u8BF7\u6309\u4F4F\u6ED1\u5757\u62D6\u52A8\u672A\u62D6\u52A8\u65F6\u5019\u663E\u793A\u6587\u5B57
successTextstring\u9A8C\u8BC1\u901A\u8FC7\u9A8C\u8BC1\u6210\u529F\u540E\u663E\u793A\u6587\u672C
heightstring\uFF5Cstring40\u9AD8\u5EA6
widthstring\uFF5Cstring260\u5BBD\u5EA6
circlebooleanfalse\u662F\u5426\u5706\u89D2
wrapStyleany-\u5916\u5C42\u5BB9\u5668\u6837\u5F0F
contentStyleany-\u4E3B\u4F53\u5185\u5BB9\u6837\u5F0F
barStyleany-bar \u6837\u5F0F
actionStyleany-\u62D6\u62FD\u6309\u94AE\u6837\u5F0F

Methods

\u540D\u79F0\u56DE\u8C03\u53C2\u6570\u8BF4\u660E
resumeFunction\u8FD8\u539F\u521D\u59CB\u503C
__VP_STATIC_END__`,17),o=[e];function c(d,l,u,r,i,k){return a(),n("div",null,o)}var y=t(p,[["render",c]]);export{h as __pageData,y as default}; diff --git a/assets/components_virtual-scroll.md.9822fe6f.js b/assets/components_virtual-scroll.md.9822fe6f.js new file mode 100644 index 00000000..d3328b3a --- /dev/null +++ b/assets/components_virtual-scroll.md.9822fe6f.js @@ -0,0 +1,60 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"VirtualScroll","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/virtual-scroll.md","lastUpdated":1694442156385}',p={},o=t(`

VirtualScroll

\u865A\u62DF\u6EDA\u52A8\u7EC4\u4EF6\uFF08\u7528\u4E8E\u5927\u91CF\u6570\u636E\u7EAF\u5C55\u793A\u65F6\u4F7F\u7528\uFF09

Usage

<template>
+  <div class="p-4 virtual-scroll-demo">
+    <Divider>\u57FA\u7840\u6EDA\u52A8\u793A\u4F8B</Divider>
+    <div class="virtual-scroll-demo-wrap">
+      <VirtualScroll :itemHeight="41" :items="data" :height="300" :width="300">
+        <template v-slot="{ item }">
+          <div class="virtual-scroll-demo__item">{{ item.title }}</div>
+        </template>
+      </VirtualScroll>
+    </div>
+
+    <Divider>\u5373\u4F7F\u4E0D\u53EF\u89C1\uFF0C\u4E5F\u9884\u5148\u52A0\u8F7D50\u6761\u6570\u636E\uFF0C\u9632\u6B62\u7A7A\u767D</Divider>
+    <div class="virtual-scroll-demo-wrap">
+      <VirtualScroll :itemHeight="41" :items="data" :height="300" :width="300" :bench="50">
+        <template v-slot="{ item }">
+          <div class="virtual-scroll-demo__item">{{ item.title }}</div>
+        </template>
+      </VirtualScroll>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { VirtualScroll } from '/@/components/VirtualScroll/index';
+
+  import { Divider } from 'ant-design-vue';
+  const data: any[] = (() => {
+    const arr: any[] = [];
+    for (let index = 1; index < 20000; index++) {
+      arr.push({
+        title: '\u5217\u8868\u9879' + index,
+      });
+    }
+    return arr;
+  })();
+  export default defineComponent({
+    components: { VirtualScroll, Divider },
+    setup() {
+      return { data: data };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .virtual-scroll-demo {
+    &-wrap {
+      display: flex;
+      margin: 0 30%;
+      background: #fff;
+      justify-content: center;
+    }
+
+    /deep/ &__item {
+      height: 40px;
+      padding: 0 20px;
+      line-height: 40px;
+      border-bottom: 1px solid #ddd;
+    }
+  }
+</style>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
heightstring\uFF5Cnumber--\u9AD8\u5EA6
widthstring\uFF5Cnumber--\u5BBD\u5EA6
maxHeightstring\uFF5Cnumber--\u6700\u5927\u9AD8\u5EA6
maxWidthstring\uFF5Cnumber--\u6700\u5927\u5BBD\u5EA6
minHeightstring\uFF5Cnumber--\u6700\u5C0F\u9AD8\u5EA6
minWidthstring\uFF5Cnumber--\u6700\u5C0F\u5BBD\u5EA6
itemHeightstring\uFF5Cnumber--\u6BCF\u4E2A\u9009\u9879\u9AD8\u5EA6\uFF0C\u5FC5\u4F20
itemsany[]--\u9009\u9879\u5217\u8868

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4
`,8),e=[o];function c(l,u,k,i,r,d){return s(),a("div",null,e)}var h=n(p,[["render",c]]);export{m as __pageData,h as default}; diff --git a/assets/components_virtual-scroll.md.9822fe6f.lean.js b/assets/components_virtual-scroll.md.9822fe6f.lean.js new file mode 100644 index 00000000..75f74a57 --- /dev/null +++ b/assets/components_virtual-scroll.md.9822fe6f.lean.js @@ -0,0 +1,60 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"VirtualScroll","description":"","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage"},{"level":2,"title":"Props","slug":"props"},{"level":2,"title":"Slots","slug":"slots"}],"relativePath":"components/virtual-scroll.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

VirtualScroll

\u865A\u62DF\u6EDA\u52A8\u7EC4\u4EF6\uFF08\u7528\u4E8E\u5927\u91CF\u6570\u636E\u7EAF\u5C55\u793A\u65F6\u4F7F\u7528\uFF09

Usage

<template>
+  <div class="p-4 virtual-scroll-demo">
+    <Divider>\u57FA\u7840\u6EDA\u52A8\u793A\u4F8B</Divider>
+    <div class="virtual-scroll-demo-wrap">
+      <VirtualScroll :itemHeight="41" :items="data" :height="300" :width="300">
+        <template v-slot="{ item }">
+          <div class="virtual-scroll-demo__item">{{ item.title }}</div>
+        </template>
+      </VirtualScroll>
+    </div>
+
+    <Divider>\u5373\u4F7F\u4E0D\u53EF\u89C1\uFF0C\u4E5F\u9884\u5148\u52A0\u8F7D50\u6761\u6570\u636E\uFF0C\u9632\u6B62\u7A7A\u767D</Divider>
+    <div class="virtual-scroll-demo-wrap">
+      <VirtualScroll :itemHeight="41" :items="data" :height="300" :width="300" :bench="50">
+        <template v-slot="{ item }">
+          <div class="virtual-scroll-demo__item">{{ item.title }}</div>
+        </template>
+      </VirtualScroll>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { VirtualScroll } from '/@/components/VirtualScroll/index';
+
+  import { Divider } from 'ant-design-vue';
+  const data: any[] = (() => {
+    const arr: any[] = [];
+    for (let index = 1; index < 20000; index++) {
+      arr.push({
+        title: '\u5217\u8868\u9879' + index,
+      });
+    }
+    return arr;
+  })();
+  export default defineComponent({
+    components: { VirtualScroll, Divider },
+    setup() {
+      return { data: data };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .virtual-scroll-demo {
+    &-wrap {
+      display: flex;
+      margin: 0 30%;
+      background: #fff;
+      justify-content: center;
+    }
+
+    /deep/ &__item {
+      height: 40px;
+      padding: 0 20px;
+      line-height: 40px;
+      border-bottom: 1px solid #ddd;
+    }
+  }
+</style>
+

Props

\u5C5E\u6027\u7C7B\u578B\u9ED8\u8BA4\u503C\u53EF\u9009\u503C\u8BF4\u660E
heightstring\uFF5Cnumber--\u9AD8\u5EA6
widthstring\uFF5Cnumber--\u5BBD\u5EA6
maxHeightstring\uFF5Cnumber--\u6700\u5927\u9AD8\u5EA6
maxWidthstring\uFF5Cnumber--\u6700\u5927\u5BBD\u5EA6
minHeightstring\uFF5Cnumber--\u6700\u5C0F\u9AD8\u5EA6
minWidthstring\uFF5Cnumber--\u6700\u5C0F\u5BBD\u5EA6
itemHeightstring\uFF5Cnumber--\u6BCF\u4E2A\u9009\u9879\u9AD8\u5EA6\uFF0C\u5FC5\u4F20
itemsany[]--\u9009\u9879\u5217\u8868

Slots

\u540D\u79F0\u8BF4\u660E
default\u9ED8\u8BA4
__VP_STATIC_END__`,8),e=[o];function c(l,u,k,i,r,d){return s(),a("div",null,e)}var h=n(p,[["render",c]]);export{m as __pageData,h as default}; diff --git a/assets/dep_cors.md.b89b8af2.js b/assets/dep_cors.md.b89b8af2.js new file mode 100644 index 00000000..0774d1d8 --- /dev/null +++ b/assets/dep_cors.md.b89b8af2.js @@ -0,0 +1 @@ +import{_ as t,f as e,e as o,N as s}from"./plugin-vue_export-helper.147b70e9.js";const u='{"title":"\u8DE8\u57DF\u5904\u7406","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4EA7\u751F\u539F\u56E0","slug":"\u4EA7\u751F\u539F\u56E0"},{"level":2,"title":"\u89E3\u51B3\u65B9\u5F0F","slug":"\u89E3\u51B3\u65B9\u5F0F"}],"relativePath":"dep/cors.md","lastUpdated":1694442156385}',r={},a=s('

\u8DE8\u57DF\u5904\u7406

\u4EA7\u751F\u539F\u56E0

\u8DE8\u57DF\u4EA7\u751F\u7684\u539F\u56E0\u662F\u7531\u4E8E\u524D\u7AEF\u5730\u5740\u4E0E\u540E\u53F0\u63A5\u53E3\u4E0D\u662F\u540C\u6E90\uFF0C\u4ECE\u800C\u5BFC\u81F4 ajax \u4E0D\u80FD\u53D1\u9001

\u975E\u540C\u6E90\u4EA7\u751F\u7684\u95EE\u9898

  1. Cookie\u3001LocalStorage \u548C IndexDB \u65E0\u6CD5\u83B7\u53D6
  2. DOM \u65E0\u6CD5\u83B7\u5F97
  3. AJAX \u8BF7\u6C42\u4E0D\u80FD\u53D1\u9001

\u540C\u6E90\u6761\u4EF6

\u534F\u8BAE\uFF0C\u7AEF\u53E3\uFF0C\u4E3B\u673A \u4E09\u8005\u76F8\u540C\u5373\u4E3A\u540C\u6E90

\u53CD\u4E4B\uFF0C\u5176\u4E2D\u53EA\u8981 \u67D0\u4E00\u4E2A \u4E0D\u4E00\u6837\u5219\u4E3A\u4E0D\u540C\u6E90

\u89E3\u51B3\u65B9\u5F0F

\u672C\u5730\u5F00\u53D1\u8DE8\u57DF

\u672C\u5730\u5F00\u53D1\u4E00\u822C\u4F7F\u7528\u4E0B\u9762 3 \u79CD\u65B9\u5F0F\u8FDB\u884C\u5904\u7406

  1. vite \u7684 proxy \u8FDB\u884C\u4EE3\u7406
  2. \u540E\u53F0\u5F00\u542F cors
  3. \u4F7F\u7528 nginx \u8F6C\u53D1\u8BF7\u6C42

\u9879\u76EE\u5185\u90E8\u81EA\u5E26\u7B2C\u4E00\u79CD\u65B9\u5F0F\uFF0C\u5177\u4F53\u53EF\u4EE5\u53C2\u8003\u670D\u52A1\u7AEF\u4EA4\u4E92-\u672C\u5730\u5F00\u53D1\u73AF\u5883\u63A5\u53E3\u5730\u5740\u4FEE\u6539

\u751F\u4EA7\u73AF\u5883\u8DE8\u57DF

\u751F\u4EA7\u73AF\u5883\u4E00\u822C\u4F7F\u7528\u4E0B\u9762 2 \u79CD\u65B9\u5F0F\u8FDB\u884C\u5904\u7406

  1. \u540E\u53F0\u5F00\u542F cors
  2. \u4F7F\u7528 nginx \u8F6C\u53D1\u8BF7\u6C42

\u540E\u53F0\u5F00\u542F cors \u4E0D\u9700\u8981\u524D\u7AEF\u505A\u4EFB\u4F55\u6539\u52A8

nginx \u914D\u7F6E\u6587\u4EF6\u53EF\u4EE5\u67E5\u770Bnginx \u914D\u7F6E

',15),i=[a];function l(n,c,p,d,h,_){return o(),e("div",null,i)}var f=t(r,[["render",l]]);export{u as __pageData,f as default}; diff --git a/assets/dep_cors.md.b89b8af2.lean.js b/assets/dep_cors.md.b89b8af2.lean.js new file mode 100644 index 00000000..52a299d0 --- /dev/null +++ b/assets/dep_cors.md.b89b8af2.lean.js @@ -0,0 +1 @@ +import{_ as t,f as e,e as o,N as s}from"./plugin-vue_export-helper.147b70e9.js";const u='{"title":"\u8DE8\u57DF\u5904\u7406","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4EA7\u751F\u539F\u56E0","slug":"\u4EA7\u751F\u539F\u56E0"},{"level":2,"title":"\u89E3\u51B3\u65B9\u5F0F","slug":"\u89E3\u51B3\u65B9\u5F0F"}],"relativePath":"dep/cors.md","lastUpdated":1694442156385}',r={},a=s('',15),i=[a];function l(n,c,p,d,h,_){return o(),e("div",null,i)}var f=t(r,[["render",l]]);export{u as __pageData,f as default}; diff --git a/assets/dep_dark.md.1af318f6.js b/assets/dep_dark.md.1af318f6.js new file mode 100644 index 00000000..3af61989 --- /dev/null +++ b/assets/dep_dark.md.1af318f6.js @@ -0,0 +1,26 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"\u9ED1\u6697\u4E3B\u9898","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4ECB\u7ECD","slug":"\u4ECB\u7ECD"},{"level":2,"title":"\u539F\u7406","slug":"\u539F\u7406"},{"level":2,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":2,"title":"\u5207\u6362","slug":"\u5207\u6362"}],"relativePath":"dep/dark.md","lastUpdated":1694442156385}',p={},e=t(`

\u9ED1\u6697\u4E3B\u9898

\u4ECB\u7ECD

\u9879\u76EE\u5DF2\u7ECF\u5185\u7F6E\u4E86\u9ED1\u6697\u4E3B\u9898\u5207\u6362\uFF0C\u53EA\u9700\u914D\u7F6E\u81EA\u5DF1\u9700\u8981\u7684\u989C\u8272\u53D8\u91CF\uFF0C\u5373\u53EF\u5728\u9879\u76EE\u4E2D\u4F7F\u7528

\u539F\u7406

\u901A\u8FC7 vite-plugin-theme \u63D2\u4EF6\uFF0C\u5C06\u6240\u6709\u7684\u989C\u8272\u53D8\u91CF\u62BD\u53D6\u5230\u72EC\u7ACB\u7684 css \u6587\u4EF6\uFF0C\u5E76\u4E14\u5168\u90E8\u5728 html \u4E0A\u9762\u52A0\u4E0A css \u9009\u62E9\u5668\u3002\u901A\u8FC7\u6539\u53D8 html \u6807\u7B7E\u7684 data-theme \u5C5E\u6027\u6765\u8FDB\u884C\u9ED1\u6697\u4E3B\u9898\u5207\u6362

\u914D\u7F6E

\u9ED1\u6697\u4E3B\u9898\u989C\u8272\u914D\u7F6E\u901A\u8FC7 vite-plugin-theme \u5B9E\u73B0\uFF0C\u5177\u4F53\u4EE3\u7801\u5728 build/vite/plugin/theme

antdDarkThemePlugin({
+  darkModifyVars: {
+    ...generateModifyVars(true),
+    'text-color': '#c9d1d9',
+    'text-color-base': '#c9d1d9',
+    'component-background': '#151515',
+    'text-color-secondary': '#8b949e',
+    'border-color-base': '#303030',
+    'item-active-bg': '#111b26',
+    'app-content-background': 'rgb(255 255 255 / 4%)',
+  },
+});
+

\u5207\u6362

\u53EA\u9700\u8981\u4F7F\u7528 vite-plugin-theme \u63D0\u4F9B\u7684\u51FD\u6570\u6765\u8FDB\u884C\u5207\u6362\u5373\u53EF

import { darkCssIsReady, loadDarkThemeCss } from 'vite-plugin-theme/es/client';
+
+export async function updateDarkTheme(mode: string | null = 'light') {
+  const htmlRoot = document.getElementById('htmlRoot');
+  if (mode === 'dark') {
+    if (import.meta.env.PROD && !darkCssIsReady) {
+      await loadDarkThemeCss();
+    }
+    htmlRoot?.setAttribute('data-theme', 'dark');
+  } else {
+    htmlRoot?.setAttribute('data-theme', 'light');
+  }
+}
+
`,11),o=[e];function c(r,l,i,u,k,d){return a(),s("div",null,o)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/dep_dark.md.1af318f6.lean.js b/assets/dep_dark.md.1af318f6.lean.js new file mode 100644 index 00000000..698505cd --- /dev/null +++ b/assets/dep_dark.md.1af318f6.lean.js @@ -0,0 +1,26 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"\u9ED1\u6697\u4E3B\u9898","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4ECB\u7ECD","slug":"\u4ECB\u7ECD"},{"level":2,"title":"\u539F\u7406","slug":"\u539F\u7406"},{"level":2,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":2,"title":"\u5207\u6362","slug":"\u5207\u6362"}],"relativePath":"dep/dark.md","lastUpdated":1694442156385}',p={},e=t(`__VP_STATIC_START__

\u9ED1\u6697\u4E3B\u9898

\u4ECB\u7ECD

\u9879\u76EE\u5DF2\u7ECF\u5185\u7F6E\u4E86\u9ED1\u6697\u4E3B\u9898\u5207\u6362\uFF0C\u53EA\u9700\u914D\u7F6E\u81EA\u5DF1\u9700\u8981\u7684\u989C\u8272\u53D8\u91CF\uFF0C\u5373\u53EF\u5728\u9879\u76EE\u4E2D\u4F7F\u7528

\u539F\u7406

\u901A\u8FC7 vite-plugin-theme \u63D2\u4EF6\uFF0C\u5C06\u6240\u6709\u7684\u989C\u8272\u53D8\u91CF\u62BD\u53D6\u5230\u72EC\u7ACB\u7684 css \u6587\u4EF6\uFF0C\u5E76\u4E14\u5168\u90E8\u5728 html \u4E0A\u9762\u52A0\u4E0A css \u9009\u62E9\u5668\u3002\u901A\u8FC7\u6539\u53D8 html \u6807\u7B7E\u7684 data-theme \u5C5E\u6027\u6765\u8FDB\u884C\u9ED1\u6697\u4E3B\u9898\u5207\u6362

\u914D\u7F6E

\u9ED1\u6697\u4E3B\u9898\u989C\u8272\u914D\u7F6E\u901A\u8FC7 vite-plugin-theme \u5B9E\u73B0\uFF0C\u5177\u4F53\u4EE3\u7801\u5728 build/vite/plugin/theme

antdDarkThemePlugin({
+  darkModifyVars: {
+    ...generateModifyVars(true),
+    'text-color': '#c9d1d9',
+    'text-color-base': '#c9d1d9',
+    'component-background': '#151515',
+    'text-color-secondary': '#8b949e',
+    'border-color-base': '#303030',
+    'item-active-bg': '#111b26',
+    'app-content-background': 'rgb(255 255 255 / 4%)',
+  },
+});
+

\u5207\u6362

\u53EA\u9700\u8981\u4F7F\u7528 vite-plugin-theme \u63D0\u4F9B\u7684\u51FD\u6570\u6765\u8FDB\u884C\u5207\u6362\u5373\u53EF

import { darkCssIsReady, loadDarkThemeCss } from 'vite-plugin-theme/es/client';
+
+export async function updateDarkTheme(mode: string | null = 'light') {
+  const htmlRoot = document.getElementById('htmlRoot');
+  if (mode === 'dark') {
+    if (import.meta.env.PROD && !darkCssIsReady) {
+      await loadDarkThemeCss();
+    }
+    htmlRoot?.setAttribute('data-theme', 'dark');
+  } else {
+    htmlRoot?.setAttribute('data-theme', 'light');
+  }
+}
+
__VP_STATIC_END__`,11),o=[e];function c(r,l,i,u,k,d){return a(),s("div",null,o)}var m=n(p,[["render",c]]);export{g as __pageData,m as default}; diff --git a/assets/dep_i18n.md.4b3c47ca.js b/assets/dep_i18n.md.4b3c47ca.js new file mode 100644 index 00000000..3211e89a --- /dev/null +++ b/assets/dep_i18n.md.4b3c47ca.js @@ -0,0 +1,120 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";var p="/images/i18n.png";const m='{"title":"\u56FD\u9645\u5316","description":"","frontmatter":{},"headers":[{"level":2,"title":"I18n-ally \u63D2\u4EF6","slug":"i18n-ally-\u63D2\u4EF6"},{"level":2,"title":"\u914D\u7F6E\u9ED8\u8BA4\u8BED\u8A00","slug":"\u914D\u7F6E\u9ED8\u8BA4\u8BED\u8A00"},{"level":2,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":3,"title":"\u8BED\u8A00\u6587\u4EF6","slug":"\u8BED\u8A00\u6587\u4EF6"},{"level":3,"title":"\u8BED\u8A00\u5BFC\u5165\u903B\u8F91\u8BF4\u660E","slug":"\u8BED\u8A00\u5BFC\u5165\u903B\u8F91\u8BF4\u660E"},{"level":2,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":2,"title":"\u5207\u6362\u8BED\u8A00","slug":"\u5207\u6362\u8BED\u8A00"},{"level":2,"title":"\u65B0\u589E","slug":"\u65B0\u589E"},{"level":3,"title":"\u8BED\u8A00\u6587\u4EF6","slug":"\u8BED\u8A00\u6587\u4EF6-1"},{"level":3,"title":"\u65B0\u589E\u8BED\u8A00","slug":"\u65B0\u589E\u8BED\u8A00"},{"level":2,"title":"\u8FDC\u7A0B\u8BFB\u53D6\u8BED\u8A00\u6570\u636E","slug":"\u8FDC\u7A0B\u8BFB\u53D6\u8BED\u8A00\u6570\u636E"},{"level":3,"title":"setupI18n \u51FD\u6570","slug":"setupi18n-\u51FD\u6570"},{"level":3,"title":"changeLocale \u51FD\u6570","slug":"changelocale-\u51FD\u6570"}],"relativePath":"dep/i18n.md","lastUpdated":1694442156385}',e={},o=t('

\u56FD\u9645\u5316

\u5982\u679C\u4F60\u4F7F\u7528\u7684 vscode \u5F00\u53D1\u5DE5\u5177\uFF0C\u5219\u63A8\u8350\u5B89\u88C5 I18n-ally \u8FD9\u4E2A\u63D2\u4EF6

I18n-ally \u63D2\u4EF6

\u5B89\u88C5\u4E86\u8BE5\u63D2\u4EF6\u540E\uFF0C\u4F60\u7684\u4EE3\u7801\u5185\u53EF\u4EE5\u5B9E\u65F6\u770B\u5230\u5BF9\u5E94\u7684\u8BED\u8A00\u5185\u5BB9

\u914D\u7F6E\u9ED8\u8BA4\u8BED\u8A00

\u5728 src/settings/localeSetting.ts \u5185\u53EF\u4EE5\u914D\u7F6E\u9ED8\u8BA4\u8BED\u8A00

export const LOCALE: { [key: string]: LocaleType } = {
+  ZH_CN: 'zh_CN',
+  EN_US: 'en',
+};
+
+export const localeSetting: LocaleSetting = {
+  // \u662F\u5426\u663E\u793A\u8BED\u8A00\u9009\u62E9\u5668
+  showPicker: true,
+  // \u5F53\u524D\u8BED\u8A00
+  locale: LOCALE.ZH_CN,
+  // \u9ED8\u8BA4\u8BED\u8A00
+  fallback: LOCALE.ZH_CN,
+  // \u5141\u8BB8\u7684\u8BED\u8A00
+  availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US],
+};
+
+// \u914D\u7F6E\u8BED\u8A00\u5217\u8868
+export const localeList: DropMenu[] = [
+  {
+    text: '\u7B80\u4F53\u4E2D\u6587',
+    event: 'zh_CN',
+  },
+  {
+    text: 'English',
+    event: 'en',
+  },
+];
+

\u914D\u7F6E

\u5728 src/locales/setupI18n.ts \u5185\u5F15\u5165\u7684 i18n \u8FD9\u4E2A\u65E0\u9700\u4FEE\u6539

\u8BED\u8A00\u6587\u4EF6

\u5728 src/locales/lang/ \u53EF\u4EE5\u914D\u7F6E\u5177\u4F53\u7684\u8BED\u8A00

# locales/lang/
+
+# \u4E2D\u6587\u8BED\u8A00
+zh_CN:
+  component: \u7EC4\u4EF6\u76F8\u5173
+  layout: \u5E03\u5C40\u76F8\u5173
+  routes: \u8DEF\u7531\u83DC\u5355\u76F8\u5173
+  sys: \u7CFB\u7EDF\u9875\u9762\u76F8\u5173
+
+en: \u540C\u4E0A
+
+

\u8BED\u8A00\u5BFC\u5165\u903B\u8F91\u8BF4\u660E

  1. \u521D\u59CB\u5316

\u5728 src/locales/setupI18n \u5185\u7684\u6839\u8BED\u8A00\u6587\u4EF6\u53EF\u4EE5\u770B\u5230

const defaultLocal = await import(\`./lang/\${locale}.ts\`);
+

\u8FD9\u4F1A\u5BFC\u5165 src/locales/lang/{lang}.ts \u6587\u4EF6\u8BED\u8A00\u5305\uFF0C\u6B64\u6587\u4EF6\u4F1A\u5BFC\u5165\u5BF9\u5E94\u8BED\u8A00\u4E0B\u7684\u6240\u6709\u6587\u4EF6\u3002

import { genMessage } from '../helper';
+import antdLocale from 'ant-design-vue/es/locale/zh_CN';
+import momentLocale from 'moment/dist/locale/zh-cn';
+
+const modules = import.meta.globEager('./zh_CN/**/*.ts');
+export default {
+  message: {
+    ...genMessage(modules, 'zh_CN'),
+    antdLocale,
+  },
+  momentLocale,
+  momentLocaleName: 'zh-cn',
+};
+

\u5E76\u5C06\u5176\u6309\u76F8\u5E94\u7684\u76EE\u5F55\u7ED3\u6784\u8F6C\u5316\u4E3A\u591A\u5C42\u7EA7\u7684

\u4F8B:

lang/zh_CN/components/modal.ts \u7684\u6587\u4EF6\u5185\u5BB9\u4E3A

{
+  title: '\u6807\u9898';
+}
+

\u5219\u5728\u4F7F\u7528\u7684\u4F7F\u7528\u76F4\u63A5\u4F7F\u7528 t('components.modal.title') \u8FDB\u884C\u83B7\u53D6\u3002

\u8FD9\u6837\u505A\u7684\u597D\u5904\u5728\u4E8E\u66F4\u5BB9\u6613\u7BA1\u7406\u5927\u578B\u9879\u76EE\u7684\u591A\u8BED\u8A00\u3002\u5982\u679C\u4E0D\u9700\u8981\u5206\u6A21\u5757\u5212\u5206\uFF0C\u53EF\u4EE5\u76F4\u63A5\u81EA\u5DF1\u624B\u52A8\u5BFC\u5165\u5373\u53EF\u3002

\u4F7F\u7528

\u5F15\u5165\u9879\u76EE\u81EA\u5E26\u7684 useI18n \u6CE8\u610F\u4E0D\u8981\u5F15\u5165 vue-i18n \u7684 useI18n

import { useI18n } from '/@/hooks/web/useI18n';
+
+const { t } = useI18n();
+
+const title = t('components.modal.title');
+

\u5207\u6362\u8BED\u8A00

\u5207\u6362\u8BED\u8A00\u9700\u8981\u4F7F\u7528 src/locales/useLocale.ts

import { useLocale } from '/@/locales/useLocale';
+
+const { changeLocale } = useLocale();
+
+changeLocale('en');
+

\u65B0\u589E

\u8BED\u8A00\u6587\u4EF6

\u5728 src/locales/lang/ \u589E\u52A0\u5BF9\u5E94\u8BED\u8A00\u7684\u6587\u4EF6\u5373\u53EF

\u65B0\u589E\u8BED\u8A00

\u76EE\u524D\u9879\u76EE\u81EA\u5E26\u7684\u8BED\u8A00\u53EA\u6709 zh_CN \u548C en \u4E24\u79CD

\u5982\u679C\u9700\u8981\u65B0\u589E\uFF0C\u6309\u4EE5\u4E0B\u64CD\u4F5C\u5373\u53EF

  1. \u5728 src/locales/lang/ \u4E0B\u65B0\u589E\u76F8\u5E94\u7684\u8BED\u8A00\u76EE\u5F55\u53CA\u8BED\u8A00\u6587\u4EF6\u5E76\u5F15\u5165 \u5F15\u5165 ant-design-vue \u548C moment \u5BF9\u5E94\u7684\u8BED\u8A00\u5305
  2. \u5728 types/config.d.ts \u5185\u52A0\u4E0A\u9884\u89C8\u7C7B\u578B\u5B9A\u4E49
  3. \u5728 src/settings/localeSetting.ts \u4FEE\u6539\u8BED\u8A00\u914D\u7F6E

\u8FDC\u7A0B\u8BFB\u53D6\u8BED\u8A00\u6570\u636E

\u76EE\u524D\u9879\u76EE\u4F1A\u5728 src/main.ts \u5185\u7B49\u5F85 setupI18n \u8FD9\u4E2A\u51FD\u6570\u6267\u884C\u5B8C\u4E4B\u540E\u624D\u4F1A\u6E32\u67D3\u754C\u9762\uFF0C\u6240\u4EE5\u53EA\u9700\u5728 setupI18n \u5185\u53D1\u9001 ajax \u8BF7\u6C42\uFF0C\u5C06\u5BF9\u5E94\u7684\u6570\u636E\u8BBE\u7F6E\u5230 i18n \u5B9E\u4F8B\u4E0A\u5373\u53EF

// src/main.ts
+await setupI18n(app);
+
+app.mount('#app', true);
+

setupI18n \u51FD\u6570

\u4EE3\u7801: src/locales/setupI18n/

\u5982\u4E0B\u6240\u793A\uFF0C\u8FD9\u91CC\u4F1A\u5148\u8BBE\u7F6E\u4E00\u4E2A\u9ED8\u8BA4\u8BED\u8A00\uFF0C\u9ED8\u8BA4\u8BED\u8A00\u53EF\u4EE5\u8BBE\u7F6E\u5728\u672C\u5730\uFF0C\u4E5F\u53EF\u4EE5\u5728\u8FD9\u91CC\u7B49\u5F85\u63A5\u53E3\u8FD4\u56DE\u9ED8\u8BA4\u8BED\u8A00

// setup i18n instance with glob
+export async function setupI18n(app: App) {
+  const options = await createI18nOptions();
+  i18n = createI18n(options) as I18n;
+  app.use(i18n);
+}
+
+async function createI18nOptions(): Promise<I18nOptions> {
+  const locale = localeStore.getLocale;
+
+  // \u8FD9\u91CC\u6539\u6210\u63A5\u53E3\u83B7\u53D6
+  const defaultLocal = await import(\`./lang/\${locale}.ts\`);
+  const message = defaultLocal.default?.message ?? {};
+
+  return {
+    legacy: false,
+    locale,
+    fallbackLocale: fallback,
+    messages: {
+      [locale]: message,
+    },
+    availableLocales: availableLocales,
+    sync: true,
+    silentTranslationWarn: true,
+    missingWarn: false,
+    silentFallbackWarn: true,
+  };
+}
+

changeLocale \u51FD\u6570

\u4EE3\u7801: src/locales/useLocale/

\u5F53\u624B\u52A8\u5207\u6362\u8BED\u8A00\u7684\u65F6\u5019\u4F1A\u89E6\u53D1 useLocale \u51FD\u6570\uFF0CuseLocale \u4E5F\u662F\u5F02\u6B65\u51FD\u6570\uFF0C\u53EA\u9700\u7B49\u5F85\u63A5\u53E3\u8FD4\u56DE\u54CD\u5E94\u7684\u6570\u636E\u540E\uFF0C\u518D\u8FDB\u884C\u8BBE\u7F6E\u5373\u53EF

async function changeLocale(locale: LocaleType) {
+  const globalI18n = i18n.global;
+  const currentLocale = unref(globalI18n.locale);
+  if (currentLocale === locale) return locale;
+
+  if (loadLocalePool.includes(locale)) {
+    setI18nLanguage(locale);
+    return locale;
+  }
+  // \u8FD9\u91CC\u6539\u6210\u63A5\u53E3\u83B7\u53D6
+  const langModule = ((await import(\`./lang/\${locale}.ts\`)) as any).default as LangModule;
+  if (!langModule) return;
+
+  const { message, momentLocale, momentLocaleName } = langModule;
+
+  globalI18n.setLocaleMessage(locale, message);
+  moment.updateLocale(momentLocaleName, momentLocale);
+  loadLocalePool.push(locale);
+
+  setI18nLanguage(locale);
+  return locale;
+}
+
`,49),c=[o];function l(u,i,r,k,d,g){return a(),s("div",null,c)}var f=n(e,[["render",l]]);export{m as __pageData,f as default}; diff --git a/assets/dep_i18n.md.4b3c47ca.lean.js b/assets/dep_i18n.md.4b3c47ca.lean.js new file mode 100644 index 00000000..6023f501 --- /dev/null +++ b/assets/dep_i18n.md.4b3c47ca.lean.js @@ -0,0 +1,120 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";var p="/images/i18n.png";const m='{"title":"\u56FD\u9645\u5316","description":"","frontmatter":{},"headers":[{"level":2,"title":"I18n-ally \u63D2\u4EF6","slug":"i18n-ally-\u63D2\u4EF6"},{"level":2,"title":"\u914D\u7F6E\u9ED8\u8BA4\u8BED\u8A00","slug":"\u914D\u7F6E\u9ED8\u8BA4\u8BED\u8A00"},{"level":2,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":3,"title":"\u8BED\u8A00\u6587\u4EF6","slug":"\u8BED\u8A00\u6587\u4EF6"},{"level":3,"title":"\u8BED\u8A00\u5BFC\u5165\u903B\u8F91\u8BF4\u660E","slug":"\u8BED\u8A00\u5BFC\u5165\u903B\u8F91\u8BF4\u660E"},{"level":2,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":2,"title":"\u5207\u6362\u8BED\u8A00","slug":"\u5207\u6362\u8BED\u8A00"},{"level":2,"title":"\u65B0\u589E","slug":"\u65B0\u589E"},{"level":3,"title":"\u8BED\u8A00\u6587\u4EF6","slug":"\u8BED\u8A00\u6587\u4EF6-1"},{"level":3,"title":"\u65B0\u589E\u8BED\u8A00","slug":"\u65B0\u589E\u8BED\u8A00"},{"level":2,"title":"\u8FDC\u7A0B\u8BFB\u53D6\u8BED\u8A00\u6570\u636E","slug":"\u8FDC\u7A0B\u8BFB\u53D6\u8BED\u8A00\u6570\u636E"},{"level":3,"title":"setupI18n \u51FD\u6570","slug":"setupi18n-\u51FD\u6570"},{"level":3,"title":"changeLocale \u51FD\u6570","slug":"changelocale-\u51FD\u6570"}],"relativePath":"dep/i18n.md","lastUpdated":1694442156385}',e={},o=t('__VP_STATIC_START__

\u56FD\u9645\u5316

\u5982\u679C\u4F60\u4F7F\u7528\u7684 vscode \u5F00\u53D1\u5DE5\u5177\uFF0C\u5219\u63A8\u8350\u5B89\u88C5 I18n-ally \u8FD9\u4E2A\u63D2\u4EF6

I18n-ally \u63D2\u4EF6

\u5B89\u88C5\u4E86\u8BE5\u63D2\u4EF6\u540E\uFF0C\u4F60\u7684\u4EE3\u7801\u5185\u53EF\u4EE5\u5B9E\u65F6\u770B\u5230\u5BF9\u5E94\u7684\u8BED\u8A00\u5185\u5BB9

\u914D\u7F6E\u9ED8\u8BA4\u8BED\u8A00

\u5728 src/settings/localeSetting.ts \u5185\u53EF\u4EE5\u914D\u7F6E\u9ED8\u8BA4\u8BED\u8A00

export const LOCALE: { [key: string]: LocaleType } = {
+  ZH_CN: 'zh_CN',
+  EN_US: 'en',
+};
+
+export const localeSetting: LocaleSetting = {
+  // \u662F\u5426\u663E\u793A\u8BED\u8A00\u9009\u62E9\u5668
+  showPicker: true,
+  // \u5F53\u524D\u8BED\u8A00
+  locale: LOCALE.ZH_CN,
+  // \u9ED8\u8BA4\u8BED\u8A00
+  fallback: LOCALE.ZH_CN,
+  // \u5141\u8BB8\u7684\u8BED\u8A00
+  availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US],
+};
+
+// \u914D\u7F6E\u8BED\u8A00\u5217\u8868
+export const localeList: DropMenu[] = [
+  {
+    text: '\u7B80\u4F53\u4E2D\u6587',
+    event: 'zh_CN',
+  },
+  {
+    text: 'English',
+    event: 'en',
+  },
+];
+

\u914D\u7F6E

\u5728 src/locales/setupI18n.ts \u5185\u5F15\u5165\u7684 i18n \u8FD9\u4E2A\u65E0\u9700\u4FEE\u6539

\u8BED\u8A00\u6587\u4EF6

\u5728 src/locales/lang/ \u53EF\u4EE5\u914D\u7F6E\u5177\u4F53\u7684\u8BED\u8A00

# locales/lang/
+
+# \u4E2D\u6587\u8BED\u8A00
+zh_CN:
+  component: \u7EC4\u4EF6\u76F8\u5173
+  layout: \u5E03\u5C40\u76F8\u5173
+  routes: \u8DEF\u7531\u83DC\u5355\u76F8\u5173
+  sys: \u7CFB\u7EDF\u9875\u9762\u76F8\u5173
+
+en: \u540C\u4E0A
+
+

\u8BED\u8A00\u5BFC\u5165\u903B\u8F91\u8BF4\u660E

  1. \u521D\u59CB\u5316

\u5728 src/locales/setupI18n \u5185\u7684\u6839\u8BED\u8A00\u6587\u4EF6\u53EF\u4EE5\u770B\u5230

const defaultLocal = await import(\`./lang/\${locale}.ts\`);
+

\u8FD9\u4F1A\u5BFC\u5165 src/locales/lang/{lang}.ts \u6587\u4EF6\u8BED\u8A00\u5305\uFF0C\u6B64\u6587\u4EF6\u4F1A\u5BFC\u5165\u5BF9\u5E94\u8BED\u8A00\u4E0B\u7684\u6240\u6709\u6587\u4EF6\u3002

import { genMessage } from '../helper';
+import antdLocale from 'ant-design-vue/es/locale/zh_CN';
+import momentLocale from 'moment/dist/locale/zh-cn';
+
+const modules = import.meta.globEager('./zh_CN/**/*.ts');
+export default {
+  message: {
+    ...genMessage(modules, 'zh_CN'),
+    antdLocale,
+  },
+  momentLocale,
+  momentLocaleName: 'zh-cn',
+};
+

\u5E76\u5C06\u5176\u6309\u76F8\u5E94\u7684\u76EE\u5F55\u7ED3\u6784\u8F6C\u5316\u4E3A\u591A\u5C42\u7EA7\u7684

\u4F8B:

lang/zh_CN/components/modal.ts \u7684\u6587\u4EF6\u5185\u5BB9\u4E3A

{
+  title: '\u6807\u9898';
+}
+

\u5219\u5728\u4F7F\u7528\u7684\u4F7F\u7528\u76F4\u63A5\u4F7F\u7528 t('components.modal.title') \u8FDB\u884C\u83B7\u53D6\u3002

\u8FD9\u6837\u505A\u7684\u597D\u5904\u5728\u4E8E\u66F4\u5BB9\u6613\u7BA1\u7406\u5927\u578B\u9879\u76EE\u7684\u591A\u8BED\u8A00\u3002\u5982\u679C\u4E0D\u9700\u8981\u5206\u6A21\u5757\u5212\u5206\uFF0C\u53EF\u4EE5\u76F4\u63A5\u81EA\u5DF1\u624B\u52A8\u5BFC\u5165\u5373\u53EF\u3002

\u4F7F\u7528

\u5F15\u5165\u9879\u76EE\u81EA\u5E26\u7684 useI18n \u6CE8\u610F\u4E0D\u8981\u5F15\u5165 vue-i18n \u7684 useI18n

import { useI18n } from '/@/hooks/web/useI18n';
+
+const { t } = useI18n();
+
+const title = t('components.modal.title');
+

\u5207\u6362\u8BED\u8A00

\u5207\u6362\u8BED\u8A00\u9700\u8981\u4F7F\u7528 src/locales/useLocale.ts

import { useLocale } from '/@/locales/useLocale';
+
+const { changeLocale } = useLocale();
+
+changeLocale('en');
+

\u65B0\u589E

\u8BED\u8A00\u6587\u4EF6

\u5728 src/locales/lang/ \u589E\u52A0\u5BF9\u5E94\u8BED\u8A00\u7684\u6587\u4EF6\u5373\u53EF

\u65B0\u589E\u8BED\u8A00

\u76EE\u524D\u9879\u76EE\u81EA\u5E26\u7684\u8BED\u8A00\u53EA\u6709 zh_CN \u548C en \u4E24\u79CD

\u5982\u679C\u9700\u8981\u65B0\u589E\uFF0C\u6309\u4EE5\u4E0B\u64CD\u4F5C\u5373\u53EF

  1. \u5728 src/locales/lang/ \u4E0B\u65B0\u589E\u76F8\u5E94\u7684\u8BED\u8A00\u76EE\u5F55\u53CA\u8BED\u8A00\u6587\u4EF6\u5E76\u5F15\u5165 \u5F15\u5165 ant-design-vue \u548C moment \u5BF9\u5E94\u7684\u8BED\u8A00\u5305
  2. \u5728 types/config.d.ts \u5185\u52A0\u4E0A\u9884\u89C8\u7C7B\u578B\u5B9A\u4E49
  3. \u5728 src/settings/localeSetting.ts \u4FEE\u6539\u8BED\u8A00\u914D\u7F6E

\u8FDC\u7A0B\u8BFB\u53D6\u8BED\u8A00\u6570\u636E

\u76EE\u524D\u9879\u76EE\u4F1A\u5728 src/main.ts \u5185\u7B49\u5F85 setupI18n \u8FD9\u4E2A\u51FD\u6570\u6267\u884C\u5B8C\u4E4B\u540E\u624D\u4F1A\u6E32\u67D3\u754C\u9762\uFF0C\u6240\u4EE5\u53EA\u9700\u5728 setupI18n \u5185\u53D1\u9001 ajax \u8BF7\u6C42\uFF0C\u5C06\u5BF9\u5E94\u7684\u6570\u636E\u8BBE\u7F6E\u5230 i18n \u5B9E\u4F8B\u4E0A\u5373\u53EF

// src/main.ts
+await setupI18n(app);
+
+app.mount('#app', true);
+

setupI18n \u51FD\u6570

\u4EE3\u7801: src/locales/setupI18n/

\u5982\u4E0B\u6240\u793A\uFF0C\u8FD9\u91CC\u4F1A\u5148\u8BBE\u7F6E\u4E00\u4E2A\u9ED8\u8BA4\u8BED\u8A00\uFF0C\u9ED8\u8BA4\u8BED\u8A00\u53EF\u4EE5\u8BBE\u7F6E\u5728\u672C\u5730\uFF0C\u4E5F\u53EF\u4EE5\u5728\u8FD9\u91CC\u7B49\u5F85\u63A5\u53E3\u8FD4\u56DE\u9ED8\u8BA4\u8BED\u8A00

// setup i18n instance with glob
+export async function setupI18n(app: App) {
+  const options = await createI18nOptions();
+  i18n = createI18n(options) as I18n;
+  app.use(i18n);
+}
+
+async function createI18nOptions(): Promise<I18nOptions> {
+  const locale = localeStore.getLocale;
+
+  // \u8FD9\u91CC\u6539\u6210\u63A5\u53E3\u83B7\u53D6
+  const defaultLocal = await import(\`./lang/\${locale}.ts\`);
+  const message = defaultLocal.default?.message ?? {};
+
+  return {
+    legacy: false,
+    locale,
+    fallbackLocale: fallback,
+    messages: {
+      [locale]: message,
+    },
+    availableLocales: availableLocales,
+    sync: true,
+    silentTranslationWarn: true,
+    missingWarn: false,
+    silentFallbackWarn: true,
+  };
+}
+

changeLocale \u51FD\u6570

\u4EE3\u7801: src/locales/useLocale/

\u5F53\u624B\u52A8\u5207\u6362\u8BED\u8A00\u7684\u65F6\u5019\u4F1A\u89E6\u53D1 useLocale \u51FD\u6570\uFF0CuseLocale \u4E5F\u662F\u5F02\u6B65\u51FD\u6570\uFF0C\u53EA\u9700\u7B49\u5F85\u63A5\u53E3\u8FD4\u56DE\u54CD\u5E94\u7684\u6570\u636E\u540E\uFF0C\u518D\u8FDB\u884C\u8BBE\u7F6E\u5373\u53EF

async function changeLocale(locale: LocaleType) {
+  const globalI18n = i18n.global;
+  const currentLocale = unref(globalI18n.locale);
+  if (currentLocale === locale) return locale;
+
+  if (loadLocalePool.includes(locale)) {
+    setI18nLanguage(locale);
+    return locale;
+  }
+  // \u8FD9\u91CC\u6539\u6210\u63A5\u53E3\u83B7\u53D6
+  const langModule = ((await import(\`./lang/\${locale}.ts\`)) as any).default as LangModule;
+  if (!langModule) return;
+
+  const { message, momentLocale, momentLocaleName } = langModule;
+
+  globalI18n.setLocaleMessage(locale, message);
+  moment.updateLocale(momentLocaleName, momentLocale);
+  loadLocalePool.push(locale);
+
+  setI18nLanguage(locale);
+  return locale;
+}
+
__VP_STATIC_END__`,49),c=[o];function l(u,i,r,k,d,g){return a(),s("div",null,c)}var f=n(e,[["render",l]]);export{m as __pageData,f as default}; diff --git a/assets/dep_icon.md.055c1c13.js b/assets/dep_icon.md.055c1c13.js new file mode 100644 index 00000000..527cf116 --- /dev/null +++ b/assets/dep_icon.md.055c1c13.js @@ -0,0 +1,163 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";var p="/images/genIcon.png",o="/images/selectIconSet.png",e="/images/outDir.png";const v='{"title":"\u56FE\u6807","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u7EC4\u4EF6\u5E93\u56FE\u6807","slug":"\u7EC4\u4EF6\u5E93\u56FE\u6807"},{"level":2,"title":"Svg Sprite \u56FE\u6807","slug":"svg-sprite-\u56FE\u6807"},{"level":3,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":2,"title":"Iconify \u56FE\u6807","slug":"iconify-\u56FE\u6807"},{"level":2,"title":"\u56FE\u6807\u9009\u62E9\u5668","slug":"\u56FE\u6807\u9009\u62E9\u5668"},{"level":3,"title":"\u56FE\u6807\u96C6\u9884\u751F\u6210","slug":"\u56FE\u6807\u96C6\u9884\u751F\u6210"},{"level":3,"title":"\u751F\u6210","slug":"\u751F\u6210"},{"level":3,"title":"\u4F18\u7F3A\u70B9","slug":"\u4F18\u7F3A\u70B9"}],"relativePath":"dep/icon.md","lastUpdated":1694442156385}',c={},l=t(`

\u56FE\u6807

\u9879\u76EE\u4E2D\u6709\u4EE5\u4E0B\u591A\u79CD\u56FE\u6807\u4F7F\u7528\u65B9\u5F0F\u3002

\u7EC4\u4EF6\u5E93\u56FE\u6807

\u4F7F\u7528 ant-design-vue \u63D0\u4F9B\u7684\u56FE\u6807

<template>
+  <StarOutlined />
+  <StarFilled />
+  <StarTwoTone twoToneColor="#eb2f96" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { StarOutlined, StarFilled, StarTwoTone } from '@ant-design/icons-vue';
+  export default defineComponent({
+    components: { StarOutlined, StarFilled, StarTwoTone },
+  });
+</script>
+

Svg Sprite \u56FE\u6807

\u4F7F\u7528

\u5C06\u9700\u8981\u7684 svg \u56FE\u6807\u653E\u5230src/assets/icons\u5185

\u4F8B: test.svg

  1. \u4F7F\u7528SvgIcon\u7EC4\u4EF6\u8FDB\u884C\u5C55\u793A
<template>
+  <SvgIcon name="test" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { SvgIcon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { SvgIcon },
+  });
+</script>
+
  1. \u4F7F\u7528Icon\u7EC4\u4EF6\u8FDB\u884C\u5C55\u793A

\u4EE5 \uFF5Csvg \u7ED3\u5C3E\u4F1A\u81EA\u52A8\u4F7F\u7528SvgIcon\u7EC4\u4EF6

<template>
+  <Icon name="test|svg" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Icon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { Icon },
+  });
+</script>
+

Iconify \u56FE\u6807

\u4F7F\u7528\u65B9\u5F0F\u8BF7\u53C2\u8003 Icon \u7EC4\u4EF6

\u9879\u76EE\u4E2D\u4F7F\u7528\u5230\u7684\u662F vite-plugin-purge-icons \u8FD9\u4E2A\u63D2\u4EF6\u6765\u8FDB\u884C\u56FE\u6807\u5B9E\u73B0\u3002

  1. \u5B89\u88C5\u4F9D\u8D56

+yarn add @iconify/iconify
+
+yarn add @iconify/json @purge-icons/generated -D
+
+
  1. \u5728 vite.config.ts\u5185\u5F15\u5165\u63D2\u4EF6
import PurgeIcons from 'vite-plugin-purge-icons';
+
+export default {
+  plugins: [PurgeIcons()],
+};
+
  1. \u7F16\u5199 Icon \u7EC4\u4EF6

\u5B8C\u6574\u4EE3\u7801 src/components/Icon/src/Icon.vue

<template>
+  <SvgIcon :size="size" :name="getSvgIcon" v-if="isSvgIcon" :class="[$attrs.class]" :spin="spin" />
+  <span
+    v-else
+    ref="elRef"
+    :class="[$attrs.class, 'app-iconify anticon', spin && 'app-iconify-spin']"
+    :style="getWrapStyle"
+  ></span>
+</template>
+<script lang="ts">
+  import type { PropType } from 'vue';
+  import {
+    defineComponent,
+    ref,
+    watch,
+    onMounted,
+    nextTick,
+    unref,
+    computed,
+    CSSProperties,
+  } from 'vue';
+
+  import SvgIcon from './SvgIcon.vue';
+  import Iconify from '@purge-icons/generated';
+  import { isString } from '/@/utils/is';
+  import { propTypes } from '/@/utils/propTypes';
+
+  const SVG_END_WITH_FLAG = '|svg';
+  export default defineComponent({
+    name: 'GIcon',
+    components: { SvgIcon },
+    props: {
+      // icon name
+      icon: propTypes.string,
+      // icon color
+      color: propTypes.string,
+      // icon size
+      size: {
+        type: [String, Number] as PropType<string | number>,
+        default: 16,
+      },
+      spin: propTypes.bool.def(false),
+      prefix: propTypes.string.def(''),
+    },
+    setup(props) {
+      const elRef = ref<ElRef>(null);
+
+      const isSvgIcon = computed(() => props.icon?.endsWith(SVG_END_WITH_FLAG));
+      const getSvgIcon = computed(() => props.icon.replace(SVG_END_WITH_FLAG, ''));
+      const getIconRef = computed(() => \`\${props.prefix ? props.prefix + ':' : ''}\${props.icon}\`);
+
+      const update = async () => {
+        if (unref(isSvgIcon)) return;
+
+        const el = unref(elRef);
+        if (!el) return;
+
+        await nextTick();
+        const icon = unref(getIconRef);
+        if (!icon) return;
+
+        const svg = Iconify.renderSVG(icon, {});
+        if (svg) {
+          el.textContent = '';
+          el.appendChild(svg);
+        } else {
+          const span = document.createElement('span');
+          span.className = 'iconify';
+          span.dataset.icon = icon;
+          el.textContent = '';
+          el.appendChild(span);
+        }
+      };
+
+      const getWrapStyle = computed((): CSSProperties => {
+        const { size, color } = props;
+        let fs = size;
+        if (isString(size)) {
+          fs = parseInt(size, 10);
+        }
+
+        return {
+          fontSize: \`\${fs}px\`,
+          color: color,
+          display: 'inline-flex',
+        };
+      });
+
+      watch(() => props.icon, update, { flush: 'post' });
+
+      onMounted(update);
+
+      return { elRef, getWrapStyle, isSvgIcon, getSvgIcon };
+    },
+  });
+</script>
+<style lang="less">
+  .app-iconify {
+    display: inline-block;
+    // vertical-align: middle;
+
+    &-spin {
+      svg {
+        animation: loadingCircle 1s infinite linear;
+      }
+    }
+  }
+
+  span.iconify {
+    display: block;
+    min-width: 1em;
+    min-height: 1em;
+    background-color: @iconify-bg-color;
+    border-radius: 100%;
+  }
+</style>
+

\u56FE\u6807\u9009\u62E9\u5668

\u56FE\u6807\u96C6\u9884\u751F\u6210

\u7531\u4E8E\u56FE\u6807\u9009\u62E9\u5668\u8FD9\u4E2A\u6BD4\u8F83\u7279\u6B8A\u7684\u5B58\u5728\uFF0C\u9879\u76EE\u4F1A\u6253\u5305\u4E00\u4E9B\u6BD4\u8F83\u591A\u7684\u56FE\u6807\uFF0C\u56FE\u6807\u9009\u62E9\u5668\u7684\u56FE\u6807\u9700\u8981\u4E8B\u5148\u6307\u5B9A\u5E76\u751F\u6210\u76F8\u5E94\u7684\u6587\u4EF6\u3002

\u751F\u6210

  • \u6267\u884C\u56FE\u6807\u751F\u6210\u547D\u4EE4
yarn gen:icon
+
  • \u8FD9\u91CC\u4F1A\u8BA9\u4F60\u9009\u62E9\u672C\u5730\u8FD8\u662F\u5728\u7EBF\u751F\u6210\uFF0C\u4E24\u79CD\u65B9\u5F0F\u5404\u6709\u5229\u5F0A\u3002\u5982\u4E0B\u56FE\u6240\u793A

local \u8868\u793A\u672C\u5730\uFF0Conline \u8868\u793A\u5728\u7EBF\uFF0C\u56DE\u8F66\u786E\u8BA4

  • \u9009\u62E9\u4F60\u8981\u751F\u6210\u7684\u56FE\u6807\u96C6,\u56DE\u8F66\u786E\u8BA4

  • \u9009\u62E9\u56FE\u6807\u8F93\u51FA\u7684\u76EE\u5F55(\u9879\u76EE\u9ED8\u8BA4 src/components/Icon/data)\uFF0C\u53EF\u4EE5\u76F4\u63A5\u56DE\u8F66\u9009\u62E9\u9ED8\u8BA4

\u5230\u8FD9\u91CC\u56FE\u6807\u96C6\u5DF2\u7ECF\u751F\u6210\u5B8C\u6210\u4E86\uFF0C\u6B64\u65F6\u4F60\u7684\u56FE\u6807\u9009\u62E9\u5668\u5DF2\u7ECF\u662F\u4F60\u6240\u9009\u7684\u7684\u56FE\u6807\u96C6\u7684\u56FE\u6807\u4E86\u3002

\u6CE8\u610F\u4E0D\u8981\u9891\u7E41\u66F4\u65B0

\u5982\u679C\u524D\u9762\u9009\u62E9\u7684\u662F\u672C\u5730\u751F\u6210\u7684\u8BDD\uFF0C\u9891\u7E41\u66F4\u6362\u56FE\u6807\u96C6\uFF0C\u53EF\u80FD\u4F1A\u5BFC\u81F4\u56FE\u6807\u4E22\u5931\u6216\u8005\u663E\u793A\u4E0D\u51FA\u6765

\u4F18\u7F3A\u70B9

  • \u5728\u7EBF\u56FE\u6807(\u9879\u76EE\u9ED8\u8BA4,\u63A8\u8350)

\u8BE5\u65B9\u5F0F\u4F1A\u5728\u56FE\u6807\u9009\u62E9\u5668\u4F7F\u7528\u5230\u56FE\u6807\u7684\u65F6\u5019\u8FDB\u884C\u5728\u7EBF\u8BF7\u6C42,\u7136\u540E\u7F13\u5B58\u5BF9\u5E94\u7684\u56FE\u6807\u5230\u6D4F\u89C8\u5668\u3002\u53EF\u4EE5\u6709\u6548\u51CF\u5C11\u4EE3\u7801\u6253\u5305\u4F53\u79EF\u3002

\u5982\u679C\u4F60\u7684\u9879\u76EE\u53EF\u4EE5\u8BBF\u95EE\u5916\u7F51\uFF0C\u5EFA\u8BAE\u53EF\u4EE5\u4F7F\u7528\u8FD9\u79CD\u65B9\u5F0F

\u7F3A\u70B9\uFF1A \u5728\u5C40\u57DF\u7F51\u6216\u8005\u65E0\u6CD5\u8BBF\u95EE\u5230\u5916\u7F51\u7684\u73AF\u5883\u4E2D\u56FE\u6807\u663E\u793A\u4E0D\u51FA\u6765

  • \u672C\u5730\u56FE\u6807

\u8BE5\u65B9\u5F0F\u4F1A\u5728\u6253\u5305\u7684\u65F6\u5019\u5C06\u56FE\u6807\u9009\u62E9\u5668\u7684\u56FE\u6807\u5168\u90E8\u6253\u5305\u5230 js \u5185\u3002\u5728\u4F7F\u7528\u7684\u65F6\u5019\u4E0D\u4F1A\u989D\u5916\u7684\u8BF7\u6C42\u5728\u7EBF\u56FE\u6807

\u7F3A\u70B9\uFF1A \u6253\u5305\u4F53\u79EF\u4F1A\u504F\u5927\uFF0C\u5177\u4F53\u7684\u4F53\u79EF\u589E\u52A0\u5F97\u770B\u524D\u9762\u9009\u62E9\u56FE\u6807\u96C6\u7684\u65F6\u5019\u9009\u62E9\u7684\u56FE\u6807\u6570\u91CF\u7684\u591A\u5C11\u51B3\u5B9A

',47),u=[l];function i(k,r,g,d,y,f){return a(),s("div",null,u)}var h=n(c,[["render",i]]);export{v as __pageData,h as default}; diff --git a/assets/dep_icon.md.055c1c13.lean.js b/assets/dep_icon.md.055c1c13.lean.js new file mode 100644 index 00000000..988c00bf --- /dev/null +++ b/assets/dep_icon.md.055c1c13.lean.js @@ -0,0 +1,163 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";var p="/images/genIcon.png",o="/images/selectIconSet.png",e="/images/outDir.png";const v='{"title":"\u56FE\u6807","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u7EC4\u4EF6\u5E93\u56FE\u6807","slug":"\u7EC4\u4EF6\u5E93\u56FE\u6807"},{"level":2,"title":"Svg Sprite \u56FE\u6807","slug":"svg-sprite-\u56FE\u6807"},{"level":3,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":2,"title":"Iconify \u56FE\u6807","slug":"iconify-\u56FE\u6807"},{"level":2,"title":"\u56FE\u6807\u9009\u62E9\u5668","slug":"\u56FE\u6807\u9009\u62E9\u5668"},{"level":3,"title":"\u56FE\u6807\u96C6\u9884\u751F\u6210","slug":"\u56FE\u6807\u96C6\u9884\u751F\u6210"},{"level":3,"title":"\u751F\u6210","slug":"\u751F\u6210"},{"level":3,"title":"\u4F18\u7F3A\u70B9","slug":"\u4F18\u7F3A\u70B9"}],"relativePath":"dep/icon.md","lastUpdated":1694442156385}',c={},l=t(`__VP_STATIC_START__

\u56FE\u6807

\u9879\u76EE\u4E2D\u6709\u4EE5\u4E0B\u591A\u79CD\u56FE\u6807\u4F7F\u7528\u65B9\u5F0F\u3002

\u7EC4\u4EF6\u5E93\u56FE\u6807

\u4F7F\u7528 ant-design-vue \u63D0\u4F9B\u7684\u56FE\u6807

<template>
+  <StarOutlined />
+  <StarFilled />
+  <StarTwoTone twoToneColor="#eb2f96" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { StarOutlined, StarFilled, StarTwoTone } from '@ant-design/icons-vue';
+  export default defineComponent({
+    components: { StarOutlined, StarFilled, StarTwoTone },
+  });
+</script>
+

Svg Sprite \u56FE\u6807

\u4F7F\u7528

\u5C06\u9700\u8981\u7684 svg \u56FE\u6807\u653E\u5230src/assets/icons\u5185

\u4F8B: test.svg

  1. \u4F7F\u7528SvgIcon\u7EC4\u4EF6\u8FDB\u884C\u5C55\u793A
<template>
+  <SvgIcon name="test" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { SvgIcon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { SvgIcon },
+  });
+</script>
+
  1. \u4F7F\u7528Icon\u7EC4\u4EF6\u8FDB\u884C\u5C55\u793A

\u4EE5 \uFF5Csvg \u7ED3\u5C3E\u4F1A\u81EA\u52A8\u4F7F\u7528SvgIcon\u7EC4\u4EF6

<template>
+  <Icon name="test|svg" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Icon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { Icon },
+  });
+</script>
+

Iconify \u56FE\u6807

\u4F7F\u7528\u65B9\u5F0F\u8BF7\u53C2\u8003 Icon \u7EC4\u4EF6

\u9879\u76EE\u4E2D\u4F7F\u7528\u5230\u7684\u662F vite-plugin-purge-icons \u8FD9\u4E2A\u63D2\u4EF6\u6765\u8FDB\u884C\u56FE\u6807\u5B9E\u73B0\u3002

  1. \u5B89\u88C5\u4F9D\u8D56

+yarn add @iconify/iconify
+
+yarn add @iconify/json @purge-icons/generated -D
+
+
  1. \u5728 vite.config.ts\u5185\u5F15\u5165\u63D2\u4EF6
import PurgeIcons from 'vite-plugin-purge-icons';
+
+export default {
+  plugins: [PurgeIcons()],
+};
+
  1. \u7F16\u5199 Icon \u7EC4\u4EF6

\u5B8C\u6574\u4EE3\u7801 src/components/Icon/src/Icon.vue

<template>
+  <SvgIcon :size="size" :name="getSvgIcon" v-if="isSvgIcon" :class="[$attrs.class]" :spin="spin" />
+  <span
+    v-else
+    ref="elRef"
+    :class="[$attrs.class, 'app-iconify anticon', spin && 'app-iconify-spin']"
+    :style="getWrapStyle"
+  ></span>
+</template>
+<script lang="ts">
+  import type { PropType } from 'vue';
+  import {
+    defineComponent,
+    ref,
+    watch,
+    onMounted,
+    nextTick,
+    unref,
+    computed,
+    CSSProperties,
+  } from 'vue';
+
+  import SvgIcon from './SvgIcon.vue';
+  import Iconify from '@purge-icons/generated';
+  import { isString } from '/@/utils/is';
+  import { propTypes } from '/@/utils/propTypes';
+
+  const SVG_END_WITH_FLAG = '|svg';
+  export default defineComponent({
+    name: 'GIcon',
+    components: { SvgIcon },
+    props: {
+      // icon name
+      icon: propTypes.string,
+      // icon color
+      color: propTypes.string,
+      // icon size
+      size: {
+        type: [String, Number] as PropType<string | number>,
+        default: 16,
+      },
+      spin: propTypes.bool.def(false),
+      prefix: propTypes.string.def(''),
+    },
+    setup(props) {
+      const elRef = ref<ElRef>(null);
+
+      const isSvgIcon = computed(() => props.icon?.endsWith(SVG_END_WITH_FLAG));
+      const getSvgIcon = computed(() => props.icon.replace(SVG_END_WITH_FLAG, ''));
+      const getIconRef = computed(() => \`\${props.prefix ? props.prefix + ':' : ''}\${props.icon}\`);
+
+      const update = async () => {
+        if (unref(isSvgIcon)) return;
+
+        const el = unref(elRef);
+        if (!el) return;
+
+        await nextTick();
+        const icon = unref(getIconRef);
+        if (!icon) return;
+
+        const svg = Iconify.renderSVG(icon, {});
+        if (svg) {
+          el.textContent = '';
+          el.appendChild(svg);
+        } else {
+          const span = document.createElement('span');
+          span.className = 'iconify';
+          span.dataset.icon = icon;
+          el.textContent = '';
+          el.appendChild(span);
+        }
+      };
+
+      const getWrapStyle = computed((): CSSProperties => {
+        const { size, color } = props;
+        let fs = size;
+        if (isString(size)) {
+          fs = parseInt(size, 10);
+        }
+
+        return {
+          fontSize: \`\${fs}px\`,
+          color: color,
+          display: 'inline-flex',
+        };
+      });
+
+      watch(() => props.icon, update, { flush: 'post' });
+
+      onMounted(update);
+
+      return { elRef, getWrapStyle, isSvgIcon, getSvgIcon };
+    },
+  });
+</script>
+<style lang="less">
+  .app-iconify {
+    display: inline-block;
+    // vertical-align: middle;
+
+    &-spin {
+      svg {
+        animation: loadingCircle 1s infinite linear;
+      }
+    }
+  }
+
+  span.iconify {
+    display: block;
+    min-width: 1em;
+    min-height: 1em;
+    background-color: @iconify-bg-color;
+    border-radius: 100%;
+  }
+</style>
+

\u56FE\u6807\u9009\u62E9\u5668

\u56FE\u6807\u96C6\u9884\u751F\u6210

\u7531\u4E8E\u56FE\u6807\u9009\u62E9\u5668\u8FD9\u4E2A\u6BD4\u8F83\u7279\u6B8A\u7684\u5B58\u5728\uFF0C\u9879\u76EE\u4F1A\u6253\u5305\u4E00\u4E9B\u6BD4\u8F83\u591A\u7684\u56FE\u6807\uFF0C\u56FE\u6807\u9009\u62E9\u5668\u7684\u56FE\u6807\u9700\u8981\u4E8B\u5148\u6307\u5B9A\u5E76\u751F\u6210\u76F8\u5E94\u7684\u6587\u4EF6\u3002

\u751F\u6210

  • \u6267\u884C\u56FE\u6807\u751F\u6210\u547D\u4EE4
yarn gen:icon
+
  • \u8FD9\u91CC\u4F1A\u8BA9\u4F60\u9009\u62E9\u672C\u5730\u8FD8\u662F\u5728\u7EBF\u751F\u6210\uFF0C\u4E24\u79CD\u65B9\u5F0F\u5404\u6709\u5229\u5F0A\u3002\u5982\u4E0B\u56FE\u6240\u793A

local \u8868\u793A\u672C\u5730\uFF0Conline \u8868\u793A\u5728\u7EBF\uFF0C\u56DE\u8F66\u786E\u8BA4

  • \u9009\u62E9\u4F60\u8981\u751F\u6210\u7684\u56FE\u6807\u96C6,\u56DE\u8F66\u786E\u8BA4

  • \u9009\u62E9\u56FE\u6807\u8F93\u51FA\u7684\u76EE\u5F55(\u9879\u76EE\u9ED8\u8BA4 src/components/Icon/data)\uFF0C\u53EF\u4EE5\u76F4\u63A5\u56DE\u8F66\u9009\u62E9\u9ED8\u8BA4

\u5230\u8FD9\u91CC\u56FE\u6807\u96C6\u5DF2\u7ECF\u751F\u6210\u5B8C\u6210\u4E86\uFF0C\u6B64\u65F6\u4F60\u7684\u56FE\u6807\u9009\u62E9\u5668\u5DF2\u7ECF\u662F\u4F60\u6240\u9009\u7684\u7684\u56FE\u6807\u96C6\u7684\u56FE\u6807\u4E86\u3002

\u6CE8\u610F\u4E0D\u8981\u9891\u7E41\u66F4\u65B0

\u5982\u679C\u524D\u9762\u9009\u62E9\u7684\u662F\u672C\u5730\u751F\u6210\u7684\u8BDD\uFF0C\u9891\u7E41\u66F4\u6362\u56FE\u6807\u96C6\uFF0C\u53EF\u80FD\u4F1A\u5BFC\u81F4\u56FE\u6807\u4E22\u5931\u6216\u8005\u663E\u793A\u4E0D\u51FA\u6765

\u4F18\u7F3A\u70B9

  • \u5728\u7EBF\u56FE\u6807(\u9879\u76EE\u9ED8\u8BA4,\u63A8\u8350)

\u8BE5\u65B9\u5F0F\u4F1A\u5728\u56FE\u6807\u9009\u62E9\u5668\u4F7F\u7528\u5230\u56FE\u6807\u7684\u65F6\u5019\u8FDB\u884C\u5728\u7EBF\u8BF7\u6C42,\u7136\u540E\u7F13\u5B58\u5BF9\u5E94\u7684\u56FE\u6807\u5230\u6D4F\u89C8\u5668\u3002\u53EF\u4EE5\u6709\u6548\u51CF\u5C11\u4EE3\u7801\u6253\u5305\u4F53\u79EF\u3002

\u5982\u679C\u4F60\u7684\u9879\u76EE\u53EF\u4EE5\u8BBF\u95EE\u5916\u7F51\uFF0C\u5EFA\u8BAE\u53EF\u4EE5\u4F7F\u7528\u8FD9\u79CD\u65B9\u5F0F

\u7F3A\u70B9\uFF1A \u5728\u5C40\u57DF\u7F51\u6216\u8005\u65E0\u6CD5\u8BBF\u95EE\u5230\u5916\u7F51\u7684\u73AF\u5883\u4E2D\u56FE\u6807\u663E\u793A\u4E0D\u51FA\u6765

  • \u672C\u5730\u56FE\u6807

\u8BE5\u65B9\u5F0F\u4F1A\u5728\u6253\u5305\u7684\u65F6\u5019\u5C06\u56FE\u6807\u9009\u62E9\u5668\u7684\u56FE\u6807\u5168\u90E8\u6253\u5305\u5230 js \u5185\u3002\u5728\u4F7F\u7528\u7684\u65F6\u5019\u4E0D\u4F1A\u989D\u5916\u7684\u8BF7\u6C42\u5728\u7EBF\u56FE\u6807

\u7F3A\u70B9\uFF1A \u6253\u5305\u4F53\u79EF\u4F1A\u504F\u5927\uFF0C\u5177\u4F53\u7684\u4F53\u79EF\u589E\u52A0\u5F97\u770B\u524D\u9762\u9009\u62E9\u56FE\u6807\u96C6\u7684\u65F6\u5019\u9009\u62E9\u7684\u56FE\u6807\u6570\u91CF\u7684\u591A\u5C11\u51B3\u5B9A

__VP_STATIC_END__',47),u=[l];function i(k,r,g,d,y,f){return a(),s("div",null,u)}var h=n(c,[["render",i]]);export{v as __pageData,h as default}; diff --git a/assets/dep_lint.md.3f96861c.js b/assets/dep_lint.md.3f96861c.js new file mode 100644 index 00000000..e12cedc1 --- /dev/null +++ b/assets/dep_lint.md.3f96861c.js @@ -0,0 +1,21 @@ +import{_ as e,f as s,e as t,N as a}from"./plugin-vue_export-helper.147b70e9.js";const k='{"title":"Lint","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4ECB\u7ECD","slug":"\u4ECB\u7ECD"},{"level":2,"title":"ESLint","slug":"eslint"},{"level":3,"title":"\u624B\u52A8\u6821\u9A8C\u4EE3\u7801","slug":"\u624B\u52A8\u6821\u9A8C\u4EE3\u7801"},{"level":3,"title":"\u914D\u7F6E\u9879","slug":"\u914D\u7F6E\u9879"},{"level":3,"title":"\u7F16\u8F91\u5668\u914D\u5408","slug":"\u7F16\u8F91\u5668\u914D\u5408"},{"level":2,"title":"CommitLint","slug":"commitlint"},{"level":3,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":3,"title":"Git \u63D0\u4EA4\u89C4\u8303","slug":"git-\u63D0\u4EA4\u89C4\u8303"},{"level":3,"title":"\u5982\u4F55\u5173\u95ED","slug":"\u5982\u4F55\u5173\u95ED"},{"level":3,"title":"\u793A\u4F8B","slug":"\u793A\u4F8B"},{"level":2,"title":"Stylelint","slug":"stylelint"},{"level":3,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E-1"},{"level":3,"title":"\u7F16\u8F91\u5668\u914D\u5408","slug":"\u7F16\u8F91\u5668\u914D\u5408-1"},{"level":2,"title":"Prettier","slug":"prettier"},{"level":3,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E-2"},{"level":3,"title":"\u7F16\u8F91\u5668\u914D\u5408","slug":"\u7F16\u8F91\u5668\u914D\u5408-2"},{"level":2,"title":"Git Hook","slug":"git-hook"},{"level":3,"title":"husky","slug":"husky"},{"level":3,"title":"\u5982\u4F55\u5173\u95ED","slug":"\u5982\u4F55\u5173\u95ED-1"},{"level":3,"title":"\u5982\u4F55\u8DF3\u8FC7\u67D0\u4E00\u4E2A\u68C0\u67E5","slug":"\u5982\u4F55\u8DF3\u8FC7\u67D0\u4E00\u4E2A\u68C0\u67E5"},{"level":3,"title":"lint-staged","slug":"lint-staged"}],"relativePath":"dep/lint.md","lastUpdated":1694442156385}',n={},i=a(`

Lint

\u4ECB\u7ECD

\u4F7F\u7528 lint \u7684\u597D\u5904

\u5177\u5907\u57FA\u672C\u5DE5\u7A0B\u7D20\u517B\u7684\u540C\u5B66\u90FD\u4F1A\u6CE8\u91CD\u7F16\u7801\u89C4\u8303\uFF0C\u800C\u4EE3\u7801\u98CE\u683C\u68C0\u67E5\uFF08Code Linting\uFF0C\u7B80\u79F0 Lint\uFF09\u662F\u4FDD\u969C\u4EE3\u7801\u89C4\u8303\u4E00\u81F4\u6027\u7684\u91CD\u8981\u624B\u6BB5\u3002

\u9075\u5FAA\u76F8\u5E94\u7684\u4EE3\u7801\u89C4\u8303\u6709\u4EE5\u4E0B\u597D\u5904

  • \u8F83\u5C11 bug \u9519\u8BEF\u7387
  • \u9AD8\u6548\u7684\u5F00\u53D1\u6548\u7387
  • \u66F4\u9AD8\u7684\u53EF\u8BFB\u6027

\u9879\u76EE\u5185\u96C6\u6210\u4E86\u4EE5\u4E0B\u51E0\u79CD\u4EE3\u7801\u6821\u9A8C\u65B9\u5F0F

  1. eslint \u7528\u4E8E\u6821\u9A8C\u4EE3\u7801\u683C\u5F0F\u89C4\u8303
  2. commitlint \u7528\u4E8E\u6821\u9A8C git \u63D0\u4EA4\u4FE1\u606F\u89C4\u8303
  3. stylelint \u7528\u4E8E\u6821\u9A8C css/less \u89C4\u8303
  4. prettier \u4EE3\u7801\u683C\u5F0F\u5316

WARNING

lint \u4E0D\u662F\u5FC5\u987B\u7684\uFF0C\u4F46\u662F\u5F88\u6709\u5FC5\u8981\uFF0C\u4E00\u4E2A\u9879\u76EE\u505A\u5927\u4E86\u4EE5\u540E\u6216\u8005\u53C2\u4E0E\u4EBA\u5458\u8FC7\u591A\u540E\uFF0C\u5C31\u4F1A\u51FA\u73B0\u5404\u79CD\u98CE\u683C\u8FE5\u5F02\u7684\u4EE3\u7801\uFF0C\u5BF9\u540E\u7EED\u7684\u7EF4\u62A4\u9020\u6210\u4E86\u4E00\u5B9A\u7684\u9EBB\u70E6

ESLint

ESLint \u662F\u4E00\u4E2A\u4EE3\u7801\u89C4\u8303\u548C\u9519\u8BEF\u68C0\u67E5\u5DE5\u5177\uFF0C\u6709\u4EE5\u4E0B\u51E0\u4E2A\u7279\u6027

  • \u6240\u6709\u4E1C\u897F\u90FD\u662F\u53EF\u4EE5\u63D2\u62D4\u7684\u3002\u4F60\u53EF\u4EE5\u8C03\u7528\u4EFB\u610F\u7684 rule api \u6216\u8005 formatter api \u53BB\u6253\u5305\u6216\u8005\u5B9A\u4E49 rule or formatter\u3002
  • \u4EFB\u610F\u7684 rule \u90FD\u662F\u72EC\u7ACB\u7684
  • \u6CA1\u6709\u7279\u5B9A\u7684 coding style\uFF0C\u4F60\u53EF\u4EE5\u81EA\u5DF1\u914D\u7F6E

\u624B\u52A8\u6821\u9A8C\u4EE3\u7801

# \u6267\u884C\u4E0B\u9762\u4EE3\u7801.\u80FD\u4FEE\u590D\u7684\u4F1A\u81EA\u52A8\u4FEE\u590D\uFF0C\u4E0D\u80FD\u4FEE\u590D\u7684\u9700\u8981\u624B\u52A8\u4FEE\u6539
+yarn run lint:eslint
+

\u914D\u7F6E\u9879

\u9879\u76EE\u7684 eslint \u914D\u7F6E\u4F4D\u4E8E\u6839\u76EE\u5F55\u4E0B .eslintrc.js \u5185\uFF0C\u53EF\u4EE5\u6839\u636E\u56E2\u961F\u81EA\u884C\u4FEE\u6539\u4EE3\u7801\u89C4\u8303

\u7F16\u8F91\u5668\u914D\u5408

\u63A8\u8350\u4F7F\u7528 vscode \u8FDB\u884C\u5F00\u53D1\uFF0Cvscode \u81EA\u5E26 eslint \u63D2\u4EF6\uFF0C\u53EF\u4EE5\u81EA\u52A8\u4FEE\u6539\u4E00\u4E9B\u9519\u8BEF\u3002

\u540C\u65F6\u9879\u76EE\u5185\u4E5F\u81EA\u5E26\u4E86 vscode eslint \u914D\u7F6E\uFF0C\u5177\u4F53\u5728 .vscode/setting.json \u6587\u4EF6\u5939\u5185\u90E8\u3002\u53EA\u8981\u4F7F\u7528 vscode \u5F00\u53D1\u4E0D\u7528\u4EFB\u4F55\u8BBE\u7F6E\u5373\u53EF\u4F7F\u7528

CommitLint

\u5728\u4E00\u4E2A\u56E2\u961F\u4E2D\uFF0C\u6BCF\u4E2A\u4EBA\u7684 git \u7684 commit \u4FE1\u606F\u90FD\u4E0D\u4E00\u6837\uFF0C\u4E94\u82B1\u516B\u95E8\uFF0C\u6CA1\u6709\u4E00\u4E2A\u673A\u5236\u5F88\u96BE\u4FDD\u8BC1\u89C4\u8303\u5316\uFF0C\u5982\u4F55\u624D\u80FD\u89C4\u8303\u5316\u5462\uFF1F\u53EF\u80FD\u4F60\u60F3\u5230\u7684\u662F git \u7684 hook \u673A\u5236\uFF0C\u53BB\u5199 shell \u811A\u672C\u53BB\u5B9E\u73B0\u3002\u8FD9\u5F53\u7136\u53EF\u4EE5\uFF0C\u5176\u5B9E JavaScript \u6709\u4E00\u4E2A\u5F88\u597D\u7684\u5DE5\u5177\u53EF\u4EE5\u5B9E\u73B0\u8FD9\u4E2A\u6A21\u677F\uFF0C\u5B83\u5C31\u662F commitlint\uFF08\u7528\u4E8E\u6821\u9A8C git \u63D0\u4EA4\u4FE1\u606F\u89C4\u8303\uFF09\u3002

\u914D\u7F6E

commit-lint \u7684\u914D\u7F6E\u4F4D\u4E8E\u9879\u76EE\u6839\u76EE\u5F55\u4E0B commitlint.config.js

Git \u63D0\u4EA4\u89C4\u8303

  • \u53C2\u8003 vue \u89C4\u8303 (Angular)

    • feat \u589E\u52A0\u65B0\u529F\u80FD
    • fix \u4FEE\u590D\u95EE\u9898/BUG
    • style \u4EE3\u7801\u98CE\u683C\u76F8\u5173\u65E0\u5F71\u54CD\u8FD0\u884C\u7ED3\u679C\u7684
    • perf \u4F18\u5316/\u6027\u80FD\u63D0\u5347
    • refactor \u91CD\u6784
    • revert \u64A4\u9500\u4FEE\u6539
    • test \u6D4B\u8BD5\u76F8\u5173
    • docs \u6587\u6863/\u6CE8\u91CA
    • chore \u4F9D\u8D56\u66F4\u65B0/\u811A\u624B\u67B6\u914D\u7F6E\u4FEE\u6539\u7B49
    • workflow \u5DE5\u4F5C\u6D41\u6539\u8FDB
    • ci \u6301\u7EED\u96C6\u6210
    • mod \u4E0D\u786E\u5B9A\u5206\u7C7B\u7684\u4FEE\u6539
    • wip \u5F00\u53D1\u4E2D
    • types \u7C7B\u578B\u4FEE\u6539

\u5982\u4F55\u5173\u95ED

\u5728 .husky/commit-msg \u5185\u6CE8\u91CA\u4EE5\u4E0B\u4EE3\u7801\u5373\u53EF

# npx --no-install commitlint --edit "$1"
+

\u793A\u4F8B


+git commit -m 'feat(home): add home page'
+
+

Stylelint

stylelint \u7528\u4E8E\u6821\u9A8C\u9879\u76EE\u5185\u90E8 css \u7684\u98CE\u683C,\u52A0\u4E0A\u7F16\u8F91\u5668\u7684\u81EA\u52A8\u4FEE\u590D\uFF0C\u53EF\u4EE5\u5F88\u597D\u7684\u7EDF\u4E00\u9879\u76EE\u5185\u90E8 css \u98CE\u683C

\u914D\u7F6E

stylelint \u914D\u7F6E\u4F4D\u4E8E\u6839\u76EE\u5F55\u4E0B stylelint.config.js

\u7F16\u8F91\u5668\u914D\u5408

\u5982\u679C\u60A8\u4F7F\u7528\u7684\u662F vscode \u7F16\u8F91\u5668\u7684\u8BDD\uFF0C\u53EA\u9700\u8981\u5B89\u88C5\u4E0B\u9762\u63D2\u4EF6\uFF0C\u5373\u53EF\u5728\u4FDD\u5B58\u7684\u65F6\u5019\u81EA\u52A8\u683C\u5F0F\u5316\u6587\u4EF6\u5185\u90E8 css \u6837\u5F0F

\u63D2\u4EF6

StyleLint

Prettier

prettier \u53EF\u4EE5\u7528\u4E8E\u7EDF\u4E00\u9879\u76EE\u4EE3\u7801\u98CE\u683C\uFF0C\u7EDF\u4E00\u7684\u7F29\u8FDB\uFF0C\u5355\u53CC\u5F15\u53F7\uFF0C\u5C3E\u9017\u53F7\u7B49\u7B49\u98CE\u683C

\u914D\u7F6E

prettier \u914D\u7F6E\u6587\u4EF6\u4F4D\u4E8E\u9879\u76EE\u6839\u76EE\u5F55\u4E0B prettier.config.js

\u7F16\u8F91\u5668\u914D\u5408

\u5982\u679C\u60A8\u4F7F\u7528\u7684\u662F vscode \u7F16\u8F91\u5668\u7684\u8BDD\uFF0C\u53EA\u9700\u8981\u5B89\u88C5\u4E0B\u9762\u63D2\u4EF6\uFF0C\u5373\u53EF\u5728\u4FDD\u5B58\u7684\u65F6\u5019\u81EA\u52A8\u683C\u5F0F\u5316\u6587\u4EF6\u5185\u90E8 js \u683C\u5F0F

\u63D2\u4EF6

Prettier

Git Hook

git hook \u4E00\u822C\u7ED3\u5408\u5404\u79CD lint\uFF0C\u5728 git \u63D0\u4EA4\u4EE3\u7801\u7684\u65F6\u5019\u8FDB\u884C\u4EE3\u7801\u98CE\u683C\u6821\u9A8C\uFF0C\u5982\u679C\u6821\u9A8C\u6CA1\u901A\u8FC7\uFF0C\u5219\u4E0D\u4F1A\u8FDB\u884C\u63D0\u4EA4\u3002\u9700\u8981\u5F00\u53D1\u8005\u81EA\u884C\u4FEE\u6539\u540E\u518D\u6B21\u8FDB\u884C\u63D0\u4EA4

husky

\u6709\u4E00\u4E2A\u95EE\u9898\u5C31\u662F\u6821\u9A8C\u4F1A\u6821\u9A8C\u5168\u90E8\u4EE3\u7801\uFF0C\u4F46\u662F\u6211\u4EEC\u53EA\u60F3\u6821\u9A8C\u6211\u4EEC\u81EA\u5DF1\u63D0\u4EA4\u7684\u4EE3\u7801\uFF0C\u8FD9\u4E2A\u65F6\u5019\u5C31\u53EF\u4EE5\u4F7F\u7528 husky\u3002

\u6700\u6709\u6548\u7684\u89E3\u51B3\u65B9\u6848\u5C31\u662F\u5C06 Lint \u6821\u9A8C\u653E\u5230\u672C\u5730\uFF0C\u5E38\u89C1\u505A\u6CD5\u662F\u4F7F\u7528 husky \u6216\u8005 pre-commit \u5728\u672C\u5730\u63D0\u4EA4\u4E4B\u524D\u5148\u505A\u4E00\u6B21 Lint \u6821\u9A8C\u3002

\u9879\u76EE\u5728 .husky \u5185\u90E8\u5B9A\u4E49\u4E86\u76F8\u5E94\u7684 hooks

\u5982\u4F55\u5173\u95ED

# \u5220\u9664husky\u4F9D\u8D56\u5373\u53EF
+yarn remove huksy
+
+

\u5982\u4F55\u8DF3\u8FC7\u67D0\u4E00\u4E2A\u68C0\u67E5

# \u52A0\u4E0A --no-verify\u5373\u53EF\u8DF3\u8FC7git hook\u6821\u9A8C\uFF08--no-verify \u7B80\u5199\u4E3A -n\uFF09
+git commit -m "xxx" --no-verify
+

lint-staged

\u7528\u4E8E\u81EA\u52A8\u4FEE\u590D\u63D0\u4EA4\u6587\u4EF6\u98CE\u683C\u95EE\u9898

lint-staged \u914D\u7F6E\u4F4D\u4E8E\u9879\u76EE .husky \u76EE\u5F55\u4E0B lintstagedrc.js

module.exports = {
+  // \u5BF9\u6307\u5B9A\u683C\u5F0F\u6587\u4EF6 \u5728\u63D0\u4EA4\u7684\u65F6\u5019\u6267\u884C\u76F8\u5E94\u7684\u4FEE\u590D\u547D\u4EE4
+  '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
+  '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
+  'package.json': ['prettier --write'],
+  '*.vue': ['eslint --fix', 'stylelint --fix', 'prettier --write', 'git add .'],
+  '*.{scss,less,styl,css,html}': ['stylelint --fix', 'prettier --write', 'git add .'],
+  '*.md': ['prettier --write'],
+};
+
`,57),l=[i];function o(r,p,c,d,h,u){return t(),s("div",null,l)}var m=e(n,[["render",o]]);export{k as __pageData,m as default}; diff --git a/assets/dep_lint.md.3f96861c.lean.js b/assets/dep_lint.md.3f96861c.lean.js new file mode 100644 index 00000000..bd521ba1 --- /dev/null +++ b/assets/dep_lint.md.3f96861c.lean.js @@ -0,0 +1,21 @@ +import{_ as e,f as s,e as t,N as a}from"./plugin-vue_export-helper.147b70e9.js";const k='{"title":"Lint","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4ECB\u7ECD","slug":"\u4ECB\u7ECD"},{"level":2,"title":"ESLint","slug":"eslint"},{"level":3,"title":"\u624B\u52A8\u6821\u9A8C\u4EE3\u7801","slug":"\u624B\u52A8\u6821\u9A8C\u4EE3\u7801"},{"level":3,"title":"\u914D\u7F6E\u9879","slug":"\u914D\u7F6E\u9879"},{"level":3,"title":"\u7F16\u8F91\u5668\u914D\u5408","slug":"\u7F16\u8F91\u5668\u914D\u5408"},{"level":2,"title":"CommitLint","slug":"commitlint"},{"level":3,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":3,"title":"Git \u63D0\u4EA4\u89C4\u8303","slug":"git-\u63D0\u4EA4\u89C4\u8303"},{"level":3,"title":"\u5982\u4F55\u5173\u95ED","slug":"\u5982\u4F55\u5173\u95ED"},{"level":3,"title":"\u793A\u4F8B","slug":"\u793A\u4F8B"},{"level":2,"title":"Stylelint","slug":"stylelint"},{"level":3,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E-1"},{"level":3,"title":"\u7F16\u8F91\u5668\u914D\u5408","slug":"\u7F16\u8F91\u5668\u914D\u5408-1"},{"level":2,"title":"Prettier","slug":"prettier"},{"level":3,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E-2"},{"level":3,"title":"\u7F16\u8F91\u5668\u914D\u5408","slug":"\u7F16\u8F91\u5668\u914D\u5408-2"},{"level":2,"title":"Git Hook","slug":"git-hook"},{"level":3,"title":"husky","slug":"husky"},{"level":3,"title":"\u5982\u4F55\u5173\u95ED","slug":"\u5982\u4F55\u5173\u95ED-1"},{"level":3,"title":"\u5982\u4F55\u8DF3\u8FC7\u67D0\u4E00\u4E2A\u68C0\u67E5","slug":"\u5982\u4F55\u8DF3\u8FC7\u67D0\u4E00\u4E2A\u68C0\u67E5"},{"level":3,"title":"lint-staged","slug":"lint-staged"}],"relativePath":"dep/lint.md","lastUpdated":1694442156385}',n={},i=a(`__VP_STATIC_START__

Lint

\u4ECB\u7ECD

\u4F7F\u7528 lint \u7684\u597D\u5904

\u5177\u5907\u57FA\u672C\u5DE5\u7A0B\u7D20\u517B\u7684\u540C\u5B66\u90FD\u4F1A\u6CE8\u91CD\u7F16\u7801\u89C4\u8303\uFF0C\u800C\u4EE3\u7801\u98CE\u683C\u68C0\u67E5\uFF08Code Linting\uFF0C\u7B80\u79F0 Lint\uFF09\u662F\u4FDD\u969C\u4EE3\u7801\u89C4\u8303\u4E00\u81F4\u6027\u7684\u91CD\u8981\u624B\u6BB5\u3002

\u9075\u5FAA\u76F8\u5E94\u7684\u4EE3\u7801\u89C4\u8303\u6709\u4EE5\u4E0B\u597D\u5904

  • \u8F83\u5C11 bug \u9519\u8BEF\u7387
  • \u9AD8\u6548\u7684\u5F00\u53D1\u6548\u7387
  • \u66F4\u9AD8\u7684\u53EF\u8BFB\u6027

\u9879\u76EE\u5185\u96C6\u6210\u4E86\u4EE5\u4E0B\u51E0\u79CD\u4EE3\u7801\u6821\u9A8C\u65B9\u5F0F

  1. eslint \u7528\u4E8E\u6821\u9A8C\u4EE3\u7801\u683C\u5F0F\u89C4\u8303
  2. commitlint \u7528\u4E8E\u6821\u9A8C git \u63D0\u4EA4\u4FE1\u606F\u89C4\u8303
  3. stylelint \u7528\u4E8E\u6821\u9A8C css/less \u89C4\u8303
  4. prettier \u4EE3\u7801\u683C\u5F0F\u5316

WARNING

lint \u4E0D\u662F\u5FC5\u987B\u7684\uFF0C\u4F46\u662F\u5F88\u6709\u5FC5\u8981\uFF0C\u4E00\u4E2A\u9879\u76EE\u505A\u5927\u4E86\u4EE5\u540E\u6216\u8005\u53C2\u4E0E\u4EBA\u5458\u8FC7\u591A\u540E\uFF0C\u5C31\u4F1A\u51FA\u73B0\u5404\u79CD\u98CE\u683C\u8FE5\u5F02\u7684\u4EE3\u7801\uFF0C\u5BF9\u540E\u7EED\u7684\u7EF4\u62A4\u9020\u6210\u4E86\u4E00\u5B9A\u7684\u9EBB\u70E6

ESLint

ESLint \u662F\u4E00\u4E2A\u4EE3\u7801\u89C4\u8303\u548C\u9519\u8BEF\u68C0\u67E5\u5DE5\u5177\uFF0C\u6709\u4EE5\u4E0B\u51E0\u4E2A\u7279\u6027

  • \u6240\u6709\u4E1C\u897F\u90FD\u662F\u53EF\u4EE5\u63D2\u62D4\u7684\u3002\u4F60\u53EF\u4EE5\u8C03\u7528\u4EFB\u610F\u7684 rule api \u6216\u8005 formatter api \u53BB\u6253\u5305\u6216\u8005\u5B9A\u4E49 rule or formatter\u3002
  • \u4EFB\u610F\u7684 rule \u90FD\u662F\u72EC\u7ACB\u7684
  • \u6CA1\u6709\u7279\u5B9A\u7684 coding style\uFF0C\u4F60\u53EF\u4EE5\u81EA\u5DF1\u914D\u7F6E

\u624B\u52A8\u6821\u9A8C\u4EE3\u7801

# \u6267\u884C\u4E0B\u9762\u4EE3\u7801.\u80FD\u4FEE\u590D\u7684\u4F1A\u81EA\u52A8\u4FEE\u590D\uFF0C\u4E0D\u80FD\u4FEE\u590D\u7684\u9700\u8981\u624B\u52A8\u4FEE\u6539
+yarn run lint:eslint
+

\u914D\u7F6E\u9879

\u9879\u76EE\u7684 eslint \u914D\u7F6E\u4F4D\u4E8E\u6839\u76EE\u5F55\u4E0B .eslintrc.js \u5185\uFF0C\u53EF\u4EE5\u6839\u636E\u56E2\u961F\u81EA\u884C\u4FEE\u6539\u4EE3\u7801\u89C4\u8303

\u7F16\u8F91\u5668\u914D\u5408

\u63A8\u8350\u4F7F\u7528 vscode \u8FDB\u884C\u5F00\u53D1\uFF0Cvscode \u81EA\u5E26 eslint \u63D2\u4EF6\uFF0C\u53EF\u4EE5\u81EA\u52A8\u4FEE\u6539\u4E00\u4E9B\u9519\u8BEF\u3002

\u540C\u65F6\u9879\u76EE\u5185\u4E5F\u81EA\u5E26\u4E86 vscode eslint \u914D\u7F6E\uFF0C\u5177\u4F53\u5728 .vscode/setting.json \u6587\u4EF6\u5939\u5185\u90E8\u3002\u53EA\u8981\u4F7F\u7528 vscode \u5F00\u53D1\u4E0D\u7528\u4EFB\u4F55\u8BBE\u7F6E\u5373\u53EF\u4F7F\u7528

CommitLint

\u5728\u4E00\u4E2A\u56E2\u961F\u4E2D\uFF0C\u6BCF\u4E2A\u4EBA\u7684 git \u7684 commit \u4FE1\u606F\u90FD\u4E0D\u4E00\u6837\uFF0C\u4E94\u82B1\u516B\u95E8\uFF0C\u6CA1\u6709\u4E00\u4E2A\u673A\u5236\u5F88\u96BE\u4FDD\u8BC1\u89C4\u8303\u5316\uFF0C\u5982\u4F55\u624D\u80FD\u89C4\u8303\u5316\u5462\uFF1F\u53EF\u80FD\u4F60\u60F3\u5230\u7684\u662F git \u7684 hook \u673A\u5236\uFF0C\u53BB\u5199 shell \u811A\u672C\u53BB\u5B9E\u73B0\u3002\u8FD9\u5F53\u7136\u53EF\u4EE5\uFF0C\u5176\u5B9E JavaScript \u6709\u4E00\u4E2A\u5F88\u597D\u7684\u5DE5\u5177\u53EF\u4EE5\u5B9E\u73B0\u8FD9\u4E2A\u6A21\u677F\uFF0C\u5B83\u5C31\u662F commitlint\uFF08\u7528\u4E8E\u6821\u9A8C git \u63D0\u4EA4\u4FE1\u606F\u89C4\u8303\uFF09\u3002

\u914D\u7F6E

commit-lint \u7684\u914D\u7F6E\u4F4D\u4E8E\u9879\u76EE\u6839\u76EE\u5F55\u4E0B commitlint.config.js

Git \u63D0\u4EA4\u89C4\u8303

  • \u53C2\u8003 vue \u89C4\u8303 (Angular)

    • feat \u589E\u52A0\u65B0\u529F\u80FD
    • fix \u4FEE\u590D\u95EE\u9898/BUG
    • style \u4EE3\u7801\u98CE\u683C\u76F8\u5173\u65E0\u5F71\u54CD\u8FD0\u884C\u7ED3\u679C\u7684
    • perf \u4F18\u5316/\u6027\u80FD\u63D0\u5347
    • refactor \u91CD\u6784
    • revert \u64A4\u9500\u4FEE\u6539
    • test \u6D4B\u8BD5\u76F8\u5173
    • docs \u6587\u6863/\u6CE8\u91CA
    • chore \u4F9D\u8D56\u66F4\u65B0/\u811A\u624B\u67B6\u914D\u7F6E\u4FEE\u6539\u7B49
    • workflow \u5DE5\u4F5C\u6D41\u6539\u8FDB
    • ci \u6301\u7EED\u96C6\u6210
    • mod \u4E0D\u786E\u5B9A\u5206\u7C7B\u7684\u4FEE\u6539
    • wip \u5F00\u53D1\u4E2D
    • types \u7C7B\u578B\u4FEE\u6539

\u5982\u4F55\u5173\u95ED

\u5728 .husky/commit-msg \u5185\u6CE8\u91CA\u4EE5\u4E0B\u4EE3\u7801\u5373\u53EF

# npx --no-install commitlint --edit "$1"
+

\u793A\u4F8B


+git commit -m 'feat(home): add home page'
+
+

Stylelint

stylelint \u7528\u4E8E\u6821\u9A8C\u9879\u76EE\u5185\u90E8 css \u7684\u98CE\u683C,\u52A0\u4E0A\u7F16\u8F91\u5668\u7684\u81EA\u52A8\u4FEE\u590D\uFF0C\u53EF\u4EE5\u5F88\u597D\u7684\u7EDF\u4E00\u9879\u76EE\u5185\u90E8 css \u98CE\u683C

\u914D\u7F6E

stylelint \u914D\u7F6E\u4F4D\u4E8E\u6839\u76EE\u5F55\u4E0B stylelint.config.js

\u7F16\u8F91\u5668\u914D\u5408

\u5982\u679C\u60A8\u4F7F\u7528\u7684\u662F vscode \u7F16\u8F91\u5668\u7684\u8BDD\uFF0C\u53EA\u9700\u8981\u5B89\u88C5\u4E0B\u9762\u63D2\u4EF6\uFF0C\u5373\u53EF\u5728\u4FDD\u5B58\u7684\u65F6\u5019\u81EA\u52A8\u683C\u5F0F\u5316\u6587\u4EF6\u5185\u90E8 css \u6837\u5F0F

\u63D2\u4EF6

StyleLint

Prettier

prettier \u53EF\u4EE5\u7528\u4E8E\u7EDF\u4E00\u9879\u76EE\u4EE3\u7801\u98CE\u683C\uFF0C\u7EDF\u4E00\u7684\u7F29\u8FDB\uFF0C\u5355\u53CC\u5F15\u53F7\uFF0C\u5C3E\u9017\u53F7\u7B49\u7B49\u98CE\u683C

\u914D\u7F6E

prettier \u914D\u7F6E\u6587\u4EF6\u4F4D\u4E8E\u9879\u76EE\u6839\u76EE\u5F55\u4E0B prettier.config.js

\u7F16\u8F91\u5668\u914D\u5408

\u5982\u679C\u60A8\u4F7F\u7528\u7684\u662F vscode \u7F16\u8F91\u5668\u7684\u8BDD\uFF0C\u53EA\u9700\u8981\u5B89\u88C5\u4E0B\u9762\u63D2\u4EF6\uFF0C\u5373\u53EF\u5728\u4FDD\u5B58\u7684\u65F6\u5019\u81EA\u52A8\u683C\u5F0F\u5316\u6587\u4EF6\u5185\u90E8 js \u683C\u5F0F

\u63D2\u4EF6

Prettier

Git Hook

git hook \u4E00\u822C\u7ED3\u5408\u5404\u79CD lint\uFF0C\u5728 git \u63D0\u4EA4\u4EE3\u7801\u7684\u65F6\u5019\u8FDB\u884C\u4EE3\u7801\u98CE\u683C\u6821\u9A8C\uFF0C\u5982\u679C\u6821\u9A8C\u6CA1\u901A\u8FC7\uFF0C\u5219\u4E0D\u4F1A\u8FDB\u884C\u63D0\u4EA4\u3002\u9700\u8981\u5F00\u53D1\u8005\u81EA\u884C\u4FEE\u6539\u540E\u518D\u6B21\u8FDB\u884C\u63D0\u4EA4

husky

\u6709\u4E00\u4E2A\u95EE\u9898\u5C31\u662F\u6821\u9A8C\u4F1A\u6821\u9A8C\u5168\u90E8\u4EE3\u7801\uFF0C\u4F46\u662F\u6211\u4EEC\u53EA\u60F3\u6821\u9A8C\u6211\u4EEC\u81EA\u5DF1\u63D0\u4EA4\u7684\u4EE3\u7801\uFF0C\u8FD9\u4E2A\u65F6\u5019\u5C31\u53EF\u4EE5\u4F7F\u7528 husky\u3002

\u6700\u6709\u6548\u7684\u89E3\u51B3\u65B9\u6848\u5C31\u662F\u5C06 Lint \u6821\u9A8C\u653E\u5230\u672C\u5730\uFF0C\u5E38\u89C1\u505A\u6CD5\u662F\u4F7F\u7528 husky \u6216\u8005 pre-commit \u5728\u672C\u5730\u63D0\u4EA4\u4E4B\u524D\u5148\u505A\u4E00\u6B21 Lint \u6821\u9A8C\u3002

\u9879\u76EE\u5728 .husky \u5185\u90E8\u5B9A\u4E49\u4E86\u76F8\u5E94\u7684 hooks

\u5982\u4F55\u5173\u95ED

# \u5220\u9664husky\u4F9D\u8D56\u5373\u53EF
+yarn remove huksy
+
+

\u5982\u4F55\u8DF3\u8FC7\u67D0\u4E00\u4E2A\u68C0\u67E5

# \u52A0\u4E0A --no-verify\u5373\u53EF\u8DF3\u8FC7git hook\u6821\u9A8C\uFF08--no-verify \u7B80\u5199\u4E3A -n\uFF09
+git commit -m "xxx" --no-verify
+

lint-staged

\u7528\u4E8E\u81EA\u52A8\u4FEE\u590D\u63D0\u4EA4\u6587\u4EF6\u98CE\u683C\u95EE\u9898

lint-staged \u914D\u7F6E\u4F4D\u4E8E\u9879\u76EE .husky \u76EE\u5F55\u4E0B lintstagedrc.js

module.exports = {
+  // \u5BF9\u6307\u5B9A\u683C\u5F0F\u6587\u4EF6 \u5728\u63D0\u4EA4\u7684\u65F6\u5019\u6267\u884C\u76F8\u5E94\u7684\u4FEE\u590D\u547D\u4EE4
+  '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
+  '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
+  'package.json': ['prettier --write'],
+  '*.vue': ['eslint --fix', 'stylelint --fix', 'prettier --write', 'git add .'],
+  '*.{scss,less,styl,css,html}': ['stylelint --fix', 'prettier --write', 'git add .'],
+  '*.md': ['prettier --write'],
+};
+
__VP_STATIC_END__`,57),l=[i];function o(r,p,c,d,h,u){return t(),s("div",null,l)}var m=e(n,[["render",o]]);export{k as __pageData,m as default}; diff --git a/assets/guide_auth.md.d8aee5d7.js b/assets/guide_auth.md.d8aee5d7.js new file mode 100644 index 00000000..83fae5f3 --- /dev/null +++ b/assets/guide_auth.md.d8aee5d7.js @@ -0,0 +1,230 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"\u6743\u9650","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u524D\u7AEF\u89D2\u8272\u6743\u9650","slug":"\u524D\u7AEF\u89D2\u8272\u6743\u9650"},{"level":3,"title":"\u5B9E\u73B0","slug":"\u5B9E\u73B0"},{"level":3,"title":"\u52A8\u6001\u66F4\u6362\u89D2\u8272","slug":"\u52A8\u6001\u66F4\u6362\u89D2\u8272"},{"level":3,"title":"\u7EC6\u7C92\u5EA6\u6743\u9650","slug":"\u7EC6\u7C92\u5EA6\u6743\u9650"},{"level":2,"title":"\u540E\u53F0\u52A8\u6001\u83B7\u53D6","slug":"\u540E\u53F0\u52A8\u6001\u83B7\u53D6"},{"level":3,"title":"\u5B9E\u73B0","slug":"\u5B9E\u73B0-1"},{"level":3,"title":"\u52A8\u6001\u66F4\u6362\u83DC\u5355","slug":"\u52A8\u6001\u66F4\u6362\u83DC\u5355"},{"level":3,"title":"\u7EC6\u7C92\u5EA6\u6743\u9650","slug":"\u7EC6\u7C92\u5EA6\u6743\u9650-1"},{"level":3,"title":"\u5982\u4F55\u521D\u59CB\u5316 code","slug":"\u5982\u4F55\u521D\u59CB\u5316-code"}],"relativePath":"guide/auth.md","lastUpdated":1694442156385}',p={},o=t(`

\u6743\u9650

\u9879\u76EE\u4E2D\u96C6\u6210\u4E86\u4E09\u79CD\u6743\u9650\u5904\u7406\u65B9\u5F0F\uFF1A

  1. \u901A\u8FC7\u7528\u6237\u89D2\u8272\u6765\u8FC7\u6EE4\u83DC\u5355(\u524D\u7AEF\u65B9\u5F0F\u63A7\u5236)\uFF0C\u83DC\u5355\u548C\u8DEF\u7531\u5206\u5F00\u914D\u7F6E
  2. \u901A\u8FC7\u7528\u6237\u89D2\u8272\u6765\u8FC7\u6EE4\u83DC\u5355(\u524D\u7AEF\u65B9\u5F0F\u63A7\u5236)\uFF0C\u83DC\u5355\u7531\u8DEF\u7531\u914D\u7F6E\u81EA\u52A8\u751F\u6210
  3. \u901A\u8FC7\u540E\u53F0\u6765\u52A8\u6001\u751F\u6210\u8DEF\u7531\u8868(\u540E\u53F0\u65B9\u5F0F\u63A7\u5236)

\u524D\u7AEF\u89D2\u8272\u6743\u9650

\u5B9E\u73B0\u539F\u7406: \u5728\u524D\u7AEF\u56FA\u5B9A\u5199\u6B7B\u8DEF\u7531\u7684\u6743\u9650\uFF0C\u6307\u5B9A\u8DEF\u7531\u6709\u54EA\u4E9B\u6743\u9650\u53EF\u4EE5\u67E5\u770B\u3002\u53EA\u521D\u59CB\u5316\u901A\u7528\u7684\u8DEF\u7531\uFF0C\u9700\u8981\u6743\u9650\u624D\u80FD\u8BBF\u95EE\u7684\u8DEF\u7531\u6CA1\u6709\u88AB\u52A0\u5165\u8DEF\u7531\u8868\u5185\u3002\u5728\u767B\u9646\u540E\u6216\u8005\u5176\u4ED6\u65B9\u5F0F\u83B7\u53D6\u7528\u6237\u89D2\u8272\u540E\uFF0C\u901A\u8FC7\u89D2\u8272\u53BB\u904D\u5386\u8DEF\u7531\u8868\uFF0C\u83B7\u53D6\u8BE5\u89D2\u8272\u53EF\u4EE5\u8BBF\u95EE\u7684\u8DEF\u7531\u8868\uFF0C\u751F\u6210\u8DEF\u7531\u8868\uFF0C\u518D\u901A\u8FC7 router.addRoutes \u6DFB\u52A0\u5230\u8DEF\u7531\u5B9E\u4F8B\uFF0C\u5B9E\u73B0\u6743\u9650\u7684\u8FC7\u6EE4\u3002

\u7F3A\u70B9: \u6743\u9650\u76F8\u5BF9\u4E0D\u81EA\u7531\uFF0C\u5982\u679C\u540E\u53F0\u6539\u52A8\u89D2\u8272\uFF0C\u524D\u53F0\u4E5F\u9700\u8981\u8DDF\u7740\u6539\u52A8\u3002\u9002\u5408\u89D2\u8272\u8F83\u56FA\u5B9A\u7684\u7CFB\u7EDF

\u5B9E\u73B0

  1. \u5728\u9879\u76EE\u914D\u7F6E\u5C06\u7CFB\u7EDF\u5185\u6743\u9650\u6A21\u5F0F\u6539\u4E3A ROLE \u6A21\u5F0F
// ! \u6539\u52A8\u540E\u9700\u8981\u6E05\u7A7A\u6D4F\u89C8\u5668\u7F13\u5B58
+const setting: ProjectConfig = {
+  // \u6743\u9650\u6A21\u5F0F
+  permissionMode: PermissionModeEnum.ROLE,
+};
+
  1. \u5728\u8DEF\u7531\u8868\u914D\u7F6E\u8DEF\u7531\u6240\u9700\u7684\u6743\u9650\uFF0C\u5982\u679C\u4E0D\u914D\u7F6E\uFF0C\u9ED8\u8BA4\u53EF\u89C1(\u89C1\u6CE8\u91CA)
import type { AppRouteModule } from '/@/router/types';
+
+import { getParentLayout, LAYOUT } from '/@/router/constant';
+import { RoleEnum } from '/@/enums/roleEnum';
+import { t } from '/@/hooks/web/useI18n';
+
+const permission: AppRouteModule = {
+  path: '/permission',
+  name: 'Permission',
+  component: LAYOUT,
+  redirect: '/permission/front/page',
+  meta: {
+    icon: 'ion:key-outline',
+    title: t('routes.demo.permission.permission'),
+  },
+
+  children: [
+    {
+      path: 'front',
+      name: 'PermissionFrontDemo',
+      component: getParentLayout('PermissionFrontDemo'),
+      meta: {
+        title: t('routes.demo.permission.front'),
+      },
+      children: [
+        {
+          path: 'auth-pageA',
+          name: 'FrontAuthPageA',
+          component: () => import('/@/views/demo/permission/front/AuthPageA.vue'),
+          meta: {
+            title: t('routes.demo.permission.frontTestA'),
+            roles: [RoleEnum.SUPER],
+          },
+        },
+        {
+          path: 'auth-pageB',
+          name: 'FrontAuthPageB',
+          component: () => import('/@/views/demo/permission/front/AuthPageB.vue'),
+          meta: {
+            title: t('routes.demo.permission.frontTestB'),
+            roles: [RoleEnum.TEST],
+          },
+        },
+      ],
+    },
+  ],
+};
+
+export default permission;
+
  1. \u5728\u8DEF\u7531\u94A9\u5B50\u5185\u52A8\u6001\u5224\u65AD

\u8BE6\u7EC6\u4EE3\u7801\u89C1 src/router/guard/permissionGuard.ts

// \u8FD9\u91CC\u53EA\u5217\u4E3E\u4E86\u4E3B\u8981\u4EE3\u7801
+const routes = await permissionStore.buildRoutesAction();
+
+routes.forEach((route) => {
+  router.addRoute(route as unknown as RouteRecordRaw);
+});
+
+const redirectPath = (from.query.redirect || to.path) as string;
+const redirect = decodeURIComponent(redirectPath);
+const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect };
+permissionStore.setDynamicAddedRoute(true);
+next(nextData);
+

permissionStore.buildRoutesAction \u7528\u4E8E\u8FC7\u6EE4\u52A8\u6001\u8DEF\u7531\uFF0C\u8BE6\u7EC6\u4EE3\u7801\u89C1 src/store/modules/permission.ts

// \u4E3B\u8981\u4EE3\u7801
+if (permissionMode === PermissionModeEnum.ROLE) {
+  const routeFilter = (route: AppRouteRecordRaw) => {
+    const { meta } = route;
+    const { roles } = meta || {};
+    if (!roles) return true;
+    return roleList.some((role) => roles.includes(role));
+  };
+  routes = filter(asyncRoutes, routeFilter);
+  routes = routes.filter(routeFilter);
+  // Convert multi-level routing to level 2 routing
+  routes = flatMultiLevelRoutes(routes);
+}
+

\u52A8\u6001\u66F4\u6362\u89D2\u8272

\u7CFB\u7EDF\u63D0\u4F9B usePermission \u65B9\u4FBF\u89D2\u8272\u76F8\u5173\u64CD\u4F5C

import { usePermission } from '/@/hooks/web/usePermission';
+import { RoleEnum } from '/@/enums/roleEnum';
+
+export default defineComponent({
+  setup() {
+    const { changeRole } = usePermission();
+    // \u66F4\u6362\u4E3Atest\u89D2\u8272
+    // \u52A8\u6001\u66F4\u6539\u89D2\u8272\uFF0C\u4F20\u5165\u89D2\u8272\u540D\u79F0\uFF0C\u53EF\u4EE5\u662F\u6570\u7EC4
+    changeRole(RoleEnum.TEST);
+    return {};
+  },
+});
+

\u7EC6\u7C92\u5EA6\u6743\u9650

\u51FD\u6570\u65B9\u5F0F

usePermission \u8FD8\u63D0\u4F9B\u4E86\u6309\u94AE\u7EA7\u522B\u7684\u6743\u9650\u63A7\u5236\u3002

<template>
+  <a-button v-if="hasPermission([RoleEnum.TEST, RoleEnum.SUPER])" color="error" class="mx-4">
+    \u62E5\u6709[test,super]\u89D2\u8272\u6743\u9650\u53EF\u89C1
+  </a-button>
+</template>
+<script lang="ts">
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { RoleEnum } from '/@/enums/roleEnum';
+
+  export default defineComponent({
+    setup() {
+      const { hasPermission } = usePermission();
+
+      return { hasPermission };
+    },
+  });
+</script>
+

\u7EC4\u4EF6\u65B9\u5F0F

\u5177\u4F53\u67E5\u770B\u6743\u9650\u7EC4\u4EF6\u4F7F\u7528

\u6307\u4EE4\u65B9\u5F0F

TIP

\u6307\u4EE4\u65B9\u5F0F\u4E0D\u80FD\u52A8\u6001\u66F4\u6539\u6743\u9650

<a-button v-auth="RoleEnum.SUPER" type="primary" class="mx-4"> \u62E5\u6709super\u89D2\u8272\u6743\u9650\u53EF\u89C1</a-button>
+

\u540E\u53F0\u52A8\u6001\u83B7\u53D6

\u5B9E\u73B0\u539F\u7406: \u662F\u901A\u8FC7\u63A5\u53E3\u52A8\u6001\u751F\u6210\u8DEF\u7531\u8868\uFF0C\u4E14\u9075\u5FAA\u4E00\u5B9A\u7684\u6570\u636E\u7ED3\u6784\u8FD4\u56DE\u3002\u524D\u7AEF\u6839\u636E\u9700\u8981\u5904\u7406\u8BE5\u6570\u636E\u4E3A\u53EF\u8BC6\u522B\u7684\u7ED3\u6784\uFF0C\u518D\u901A\u8FC7 router.addRoutes \u6DFB\u52A0\u5230\u8DEF\u7531\u5B9E\u4F8B\uFF0C\u5B9E\u73B0\u6743\u9650\u7684\u52A8\u6001\u751F\u6210\u3002

\u5B9E\u73B0

  1. \u5728\u9879\u76EE\u914D\u7F6E\u5C06\u7CFB\u7EDF\u5185\u6743\u9650\u6A21\u5F0F\u6539\u4E3A BACK \u6A21\u5F0F
// ! \u6539\u52A8\u540E\u9700\u8981\u6E05\u7A7A\u6D4F\u89C8\u5668\u7F13\u5B58
+const setting: ProjectConfig = {
+  // \u6743\u9650\u6A21\u5F0F
+  permissionMode: PermissionModeEnum.BACK,
+};
+
  1. \u8DEF\u7531\u62E6\u622A\uFF0C\u4E0E\u89D2\u8272\u6743\u9650\u6A21\u5F0F\u4E00\u81F4

permissionStore.buildRoutesAction \u7528\u4E8E\u8FC7\u6EE4\u52A8\u6001\u8DEF\u7531\uFF0C\u8BE6\u7EC6\u4EE3\u7801\u89C1 /@/store/modules/permission.ts

// \u4E3B\u8981\u4EE3\u7801
+if (permissionMode === PermissionModeEnum.BACK) {
+  const { createMessage } = useMessage();
+
+  createMessage.loading({
+    content: t('sys.app.menuLoading'),
+    duration: 1,
+  });
+
+  // !Simulate to obtain permission codes from the background,
+  // this function may only need to be executed once, and the actual project can be put at the right time by itself
+  let routeList: AppRouteRecordRaw[] = [];
+  try {
+    this.changePermissionCode();
+    routeList = (await getMenuList()) as AppRouteRecordRaw[];
+  } catch (error) {
+    console.error(error);
+  }
+
+  // Dynamically introduce components
+  routeList = transformObjToRoute(routeList);
+
+  //  Background routing to menu structure
+  const backMenuList = transformRouteToMenu(routeList);
+  this.setBackMenuList(backMenuList);
+
+  routeList = flatMultiLevelRoutes(routeList);
+  routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
+}
+

getMenuList \u8FD4\u56DE\u503C\u683C\u5F0F

\u8FD4\u56DE\u503C\u7531\u591A\u4E2A\u8DEF\u7531\u6A21\u5757\u7EC4\u6210

\u6CE8\u610F

\u540E\u7AEF\u63A5\u53E3\u8FD4\u56DE\u7684\u6570\u636E\u4E2D\u5FC5\u987B\u5305\u542BPageEnum.BASE_HOME\u6307\u5B9A\u7684\u8DEF\u7531\uFF08path\u5B9A\u4E49\u4E8Esrc/enums/pageEnum.ts\uFF09

[
+  {
+    path: '/dashboard',
+    name: 'Dashboard',
+    component: '/dashboard/welcome/index',
+    meta: {
+      title: 'routes.dashboard.welcome',
+      affix: true,
+      icon: 'ant-design:home-outlined',
+    },
+  },
+  {
+    path: '/permission',
+    name: 'Permission',
+    component: 'LAYOUT',
+    redirect: '/permission/front/page',
+    meta: {
+      icon: 'carbon:user-role',
+      title: 'routes.demo.permission.permission',
+    },
+    children: [
+      {
+        path: 'back',
+        name: 'PermissionBackDemo',
+        meta: {
+          title: 'routes.demo.permission.back',
+        },
+
+        children: [
+          {
+            path: 'page',
+            name: 'BackAuthPage',
+            component: '/demo/permission/back/index',
+            meta: {
+              title: 'routes.demo.permission.backPage',
+            },
+          },
+          {
+            path: 'btn',
+            name: 'BackAuthBtn',
+            component: '/demo/permission/back/Btn',
+            meta: {
+              title: 'routes.demo.permission.backBtn',
+            },
+          },
+        ],
+      },
+    ],
+  },
+];
+

\u52A8\u6001\u66F4\u6362\u83DC\u5355

\u7CFB\u7EDF\u63D0\u4F9B usePermission \u65B9\u4FBF\u89D2\u8272\u76F8\u5173\u64CD\u4F5C

import { usePermission } from '/@/hooks/web/usePermission';
+import { RoleEnum } from '/@/enums/roleEnum';
+
+export default defineComponent({
+  setup() {
+    const { changeMenu } = usePermission();
+
+    // \u66F4\u6539\u83DC\u5355\u7684\u5B9E\u73B0\u9700\u8981\u81EA\u884C\u53BB\u4FEE\u6539
+    changeMenu();
+    return {};
+  },
+});
+

\u7EC6\u7C92\u5EA6\u6743\u9650

\u51FD\u6570\u65B9\u5F0F

usePermission \u8FD8\u63D0\u4F9B\u4E86\u6309\u94AE\u7EA7\u522B\u7684\u6743\u9650\u63A7\u5236\u3002

<template>
+  <a-button v-if="hasPermission(['20000', '2000010'])" color="error" class="mx-4">
+    \u62E5\u6709[20000,2000010]code\u53EF\u89C1
+  </a-button>
+</template>
+<script lang="ts">
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { RoleEnum } from '/@/enums/roleEnum';
+
+  export default defineComponent({
+    setup() {
+      const { hasPermission } = usePermission();
+      return { hasPermission };
+    },
+  });
+</script>
+

\u7EC4\u4EF6\u65B9\u5F0F

\u5177\u4F53\u67E5\u770B\u6743\u9650\u7EC4\u4EF6\u4F7F\u7528

\u6307\u4EE4\u65B9\u5F0F

TIP

\u6307\u4EE4\u65B9\u5F0F\u4E0D\u80FD\u52A8\u6001\u66F4\u6539\u6743\u9650

<a-button v-auth="'1000'" type="primary" class="mx-4"> \u62E5\u6709code ['1000']\u6743\u9650\u53EF\u89C1 </a-button>
+

\u5982\u4F55\u521D\u59CB\u5316 code

\u901A\u5E38\uFF0C\u5982\u9700\u505A\u6309\u94AE\u7EA7\u522B\u6743\u9650\uFF0C\u540E\u53F0\u4F1A\u63D0\u4F9B\u76F8\u5E94\u7684 code\uFF0C\u6216\u8005\u7C7B\u578B\u7684\u5224\u65AD\u6807\u8BC6\u3002\u8FD9\u4E9B\u7F16\u7801\u53EA\u9700\u8981\u5728\u767B\u5F55\u540E\u83B7\u53D6\u4E00\u6B21\u5373\u53EF\u3002

import { getPermCodeByUserId } from '/@/api/sys/user';
+import { permissionStore } from '/@/store/modules/permission';
+async function changePermissionCode(userId: string) {
+  // \u4ECE\u540E\u53F0\u83B7\u53D6\u5F53\u524D\u7528\u6237\u62E5\u6709\u7684\u7F16\u7801
+  const codeList = await getPermCodeByUserId({ userId });
+  permissionStore.commitPermCodeListState(codeList);
+}
+
`,55),e=[o];function c(u,l,i,k,r,d){return a(),s("div",null,e)}var h=n(p,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/guide_auth.md.d8aee5d7.lean.js b/assets/guide_auth.md.d8aee5d7.lean.js new file mode 100644 index 00000000..3aa5155d --- /dev/null +++ b/assets/guide_auth.md.d8aee5d7.lean.js @@ -0,0 +1,230 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"\u6743\u9650","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u524D\u7AEF\u89D2\u8272\u6743\u9650","slug":"\u524D\u7AEF\u89D2\u8272\u6743\u9650"},{"level":3,"title":"\u5B9E\u73B0","slug":"\u5B9E\u73B0"},{"level":3,"title":"\u52A8\u6001\u66F4\u6362\u89D2\u8272","slug":"\u52A8\u6001\u66F4\u6362\u89D2\u8272"},{"level":3,"title":"\u7EC6\u7C92\u5EA6\u6743\u9650","slug":"\u7EC6\u7C92\u5EA6\u6743\u9650"},{"level":2,"title":"\u540E\u53F0\u52A8\u6001\u83B7\u53D6","slug":"\u540E\u53F0\u52A8\u6001\u83B7\u53D6"},{"level":3,"title":"\u5B9E\u73B0","slug":"\u5B9E\u73B0-1"},{"level":3,"title":"\u52A8\u6001\u66F4\u6362\u83DC\u5355","slug":"\u52A8\u6001\u66F4\u6362\u83DC\u5355"},{"level":3,"title":"\u7EC6\u7C92\u5EA6\u6743\u9650","slug":"\u7EC6\u7C92\u5EA6\u6743\u9650-1"},{"level":3,"title":"\u5982\u4F55\u521D\u59CB\u5316 code","slug":"\u5982\u4F55\u521D\u59CB\u5316-code"}],"relativePath":"guide/auth.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

\u6743\u9650

\u9879\u76EE\u4E2D\u96C6\u6210\u4E86\u4E09\u79CD\u6743\u9650\u5904\u7406\u65B9\u5F0F\uFF1A

  1. \u901A\u8FC7\u7528\u6237\u89D2\u8272\u6765\u8FC7\u6EE4\u83DC\u5355(\u524D\u7AEF\u65B9\u5F0F\u63A7\u5236)\uFF0C\u83DC\u5355\u548C\u8DEF\u7531\u5206\u5F00\u914D\u7F6E
  2. \u901A\u8FC7\u7528\u6237\u89D2\u8272\u6765\u8FC7\u6EE4\u83DC\u5355(\u524D\u7AEF\u65B9\u5F0F\u63A7\u5236)\uFF0C\u83DC\u5355\u7531\u8DEF\u7531\u914D\u7F6E\u81EA\u52A8\u751F\u6210
  3. \u901A\u8FC7\u540E\u53F0\u6765\u52A8\u6001\u751F\u6210\u8DEF\u7531\u8868(\u540E\u53F0\u65B9\u5F0F\u63A7\u5236)

\u524D\u7AEF\u89D2\u8272\u6743\u9650

\u5B9E\u73B0\u539F\u7406: \u5728\u524D\u7AEF\u56FA\u5B9A\u5199\u6B7B\u8DEF\u7531\u7684\u6743\u9650\uFF0C\u6307\u5B9A\u8DEF\u7531\u6709\u54EA\u4E9B\u6743\u9650\u53EF\u4EE5\u67E5\u770B\u3002\u53EA\u521D\u59CB\u5316\u901A\u7528\u7684\u8DEF\u7531\uFF0C\u9700\u8981\u6743\u9650\u624D\u80FD\u8BBF\u95EE\u7684\u8DEF\u7531\u6CA1\u6709\u88AB\u52A0\u5165\u8DEF\u7531\u8868\u5185\u3002\u5728\u767B\u9646\u540E\u6216\u8005\u5176\u4ED6\u65B9\u5F0F\u83B7\u53D6\u7528\u6237\u89D2\u8272\u540E\uFF0C\u901A\u8FC7\u89D2\u8272\u53BB\u904D\u5386\u8DEF\u7531\u8868\uFF0C\u83B7\u53D6\u8BE5\u89D2\u8272\u53EF\u4EE5\u8BBF\u95EE\u7684\u8DEF\u7531\u8868\uFF0C\u751F\u6210\u8DEF\u7531\u8868\uFF0C\u518D\u901A\u8FC7 router.addRoutes \u6DFB\u52A0\u5230\u8DEF\u7531\u5B9E\u4F8B\uFF0C\u5B9E\u73B0\u6743\u9650\u7684\u8FC7\u6EE4\u3002

\u7F3A\u70B9: \u6743\u9650\u76F8\u5BF9\u4E0D\u81EA\u7531\uFF0C\u5982\u679C\u540E\u53F0\u6539\u52A8\u89D2\u8272\uFF0C\u524D\u53F0\u4E5F\u9700\u8981\u8DDF\u7740\u6539\u52A8\u3002\u9002\u5408\u89D2\u8272\u8F83\u56FA\u5B9A\u7684\u7CFB\u7EDF

\u5B9E\u73B0

  1. \u5728\u9879\u76EE\u914D\u7F6E\u5C06\u7CFB\u7EDF\u5185\u6743\u9650\u6A21\u5F0F\u6539\u4E3A ROLE \u6A21\u5F0F
// ! \u6539\u52A8\u540E\u9700\u8981\u6E05\u7A7A\u6D4F\u89C8\u5668\u7F13\u5B58
+const setting: ProjectConfig = {
+  // \u6743\u9650\u6A21\u5F0F
+  permissionMode: PermissionModeEnum.ROLE,
+};
+
  1. \u5728\u8DEF\u7531\u8868\u914D\u7F6E\u8DEF\u7531\u6240\u9700\u7684\u6743\u9650\uFF0C\u5982\u679C\u4E0D\u914D\u7F6E\uFF0C\u9ED8\u8BA4\u53EF\u89C1(\u89C1\u6CE8\u91CA)
import type { AppRouteModule } from '/@/router/types';
+
+import { getParentLayout, LAYOUT } from '/@/router/constant';
+import { RoleEnum } from '/@/enums/roleEnum';
+import { t } from '/@/hooks/web/useI18n';
+
+const permission: AppRouteModule = {
+  path: '/permission',
+  name: 'Permission',
+  component: LAYOUT,
+  redirect: '/permission/front/page',
+  meta: {
+    icon: 'ion:key-outline',
+    title: t('routes.demo.permission.permission'),
+  },
+
+  children: [
+    {
+      path: 'front',
+      name: 'PermissionFrontDemo',
+      component: getParentLayout('PermissionFrontDemo'),
+      meta: {
+        title: t('routes.demo.permission.front'),
+      },
+      children: [
+        {
+          path: 'auth-pageA',
+          name: 'FrontAuthPageA',
+          component: () => import('/@/views/demo/permission/front/AuthPageA.vue'),
+          meta: {
+            title: t('routes.demo.permission.frontTestA'),
+            roles: [RoleEnum.SUPER],
+          },
+        },
+        {
+          path: 'auth-pageB',
+          name: 'FrontAuthPageB',
+          component: () => import('/@/views/demo/permission/front/AuthPageB.vue'),
+          meta: {
+            title: t('routes.demo.permission.frontTestB'),
+            roles: [RoleEnum.TEST],
+          },
+        },
+      ],
+    },
+  ],
+};
+
+export default permission;
+
  1. \u5728\u8DEF\u7531\u94A9\u5B50\u5185\u52A8\u6001\u5224\u65AD

\u8BE6\u7EC6\u4EE3\u7801\u89C1 src/router/guard/permissionGuard.ts

// \u8FD9\u91CC\u53EA\u5217\u4E3E\u4E86\u4E3B\u8981\u4EE3\u7801
+const routes = await permissionStore.buildRoutesAction();
+
+routes.forEach((route) => {
+  router.addRoute(route as unknown as RouteRecordRaw);
+});
+
+const redirectPath = (from.query.redirect || to.path) as string;
+const redirect = decodeURIComponent(redirectPath);
+const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect };
+permissionStore.setDynamicAddedRoute(true);
+next(nextData);
+

permissionStore.buildRoutesAction \u7528\u4E8E\u8FC7\u6EE4\u52A8\u6001\u8DEF\u7531\uFF0C\u8BE6\u7EC6\u4EE3\u7801\u89C1 src/store/modules/permission.ts

// \u4E3B\u8981\u4EE3\u7801
+if (permissionMode === PermissionModeEnum.ROLE) {
+  const routeFilter = (route: AppRouteRecordRaw) => {
+    const { meta } = route;
+    const { roles } = meta || {};
+    if (!roles) return true;
+    return roleList.some((role) => roles.includes(role));
+  };
+  routes = filter(asyncRoutes, routeFilter);
+  routes = routes.filter(routeFilter);
+  // Convert multi-level routing to level 2 routing
+  routes = flatMultiLevelRoutes(routes);
+}
+

\u52A8\u6001\u66F4\u6362\u89D2\u8272

\u7CFB\u7EDF\u63D0\u4F9B usePermission \u65B9\u4FBF\u89D2\u8272\u76F8\u5173\u64CD\u4F5C

import { usePermission } from '/@/hooks/web/usePermission';
+import { RoleEnum } from '/@/enums/roleEnum';
+
+export default defineComponent({
+  setup() {
+    const { changeRole } = usePermission();
+    // \u66F4\u6362\u4E3Atest\u89D2\u8272
+    // \u52A8\u6001\u66F4\u6539\u89D2\u8272\uFF0C\u4F20\u5165\u89D2\u8272\u540D\u79F0\uFF0C\u53EF\u4EE5\u662F\u6570\u7EC4
+    changeRole(RoleEnum.TEST);
+    return {};
+  },
+});
+

\u7EC6\u7C92\u5EA6\u6743\u9650

\u51FD\u6570\u65B9\u5F0F

usePermission \u8FD8\u63D0\u4F9B\u4E86\u6309\u94AE\u7EA7\u522B\u7684\u6743\u9650\u63A7\u5236\u3002

<template>
+  <a-button v-if="hasPermission([RoleEnum.TEST, RoleEnum.SUPER])" color="error" class="mx-4">
+    \u62E5\u6709[test,super]\u89D2\u8272\u6743\u9650\u53EF\u89C1
+  </a-button>
+</template>
+<script lang="ts">
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { RoleEnum } from '/@/enums/roleEnum';
+
+  export default defineComponent({
+    setup() {
+      const { hasPermission } = usePermission();
+
+      return { hasPermission };
+    },
+  });
+</script>
+

\u7EC4\u4EF6\u65B9\u5F0F

\u5177\u4F53\u67E5\u770B\u6743\u9650\u7EC4\u4EF6\u4F7F\u7528

\u6307\u4EE4\u65B9\u5F0F

TIP

\u6307\u4EE4\u65B9\u5F0F\u4E0D\u80FD\u52A8\u6001\u66F4\u6539\u6743\u9650

<a-button v-auth="RoleEnum.SUPER" type="primary" class="mx-4"> \u62E5\u6709super\u89D2\u8272\u6743\u9650\u53EF\u89C1</a-button>
+

\u540E\u53F0\u52A8\u6001\u83B7\u53D6

\u5B9E\u73B0\u539F\u7406: \u662F\u901A\u8FC7\u63A5\u53E3\u52A8\u6001\u751F\u6210\u8DEF\u7531\u8868\uFF0C\u4E14\u9075\u5FAA\u4E00\u5B9A\u7684\u6570\u636E\u7ED3\u6784\u8FD4\u56DE\u3002\u524D\u7AEF\u6839\u636E\u9700\u8981\u5904\u7406\u8BE5\u6570\u636E\u4E3A\u53EF\u8BC6\u522B\u7684\u7ED3\u6784\uFF0C\u518D\u901A\u8FC7 router.addRoutes \u6DFB\u52A0\u5230\u8DEF\u7531\u5B9E\u4F8B\uFF0C\u5B9E\u73B0\u6743\u9650\u7684\u52A8\u6001\u751F\u6210\u3002

\u5B9E\u73B0

  1. \u5728\u9879\u76EE\u914D\u7F6E\u5C06\u7CFB\u7EDF\u5185\u6743\u9650\u6A21\u5F0F\u6539\u4E3A BACK \u6A21\u5F0F
// ! \u6539\u52A8\u540E\u9700\u8981\u6E05\u7A7A\u6D4F\u89C8\u5668\u7F13\u5B58
+const setting: ProjectConfig = {
+  // \u6743\u9650\u6A21\u5F0F
+  permissionMode: PermissionModeEnum.BACK,
+};
+
  1. \u8DEF\u7531\u62E6\u622A\uFF0C\u4E0E\u89D2\u8272\u6743\u9650\u6A21\u5F0F\u4E00\u81F4

permissionStore.buildRoutesAction \u7528\u4E8E\u8FC7\u6EE4\u52A8\u6001\u8DEF\u7531\uFF0C\u8BE6\u7EC6\u4EE3\u7801\u89C1 /@/store/modules/permission.ts

// \u4E3B\u8981\u4EE3\u7801
+if (permissionMode === PermissionModeEnum.BACK) {
+  const { createMessage } = useMessage();
+
+  createMessage.loading({
+    content: t('sys.app.menuLoading'),
+    duration: 1,
+  });
+
+  // !Simulate to obtain permission codes from the background,
+  // this function may only need to be executed once, and the actual project can be put at the right time by itself
+  let routeList: AppRouteRecordRaw[] = [];
+  try {
+    this.changePermissionCode();
+    routeList = (await getMenuList()) as AppRouteRecordRaw[];
+  } catch (error) {
+    console.error(error);
+  }
+
+  // Dynamically introduce components
+  routeList = transformObjToRoute(routeList);
+
+  //  Background routing to menu structure
+  const backMenuList = transformRouteToMenu(routeList);
+  this.setBackMenuList(backMenuList);
+
+  routeList = flatMultiLevelRoutes(routeList);
+  routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
+}
+

getMenuList \u8FD4\u56DE\u503C\u683C\u5F0F

\u8FD4\u56DE\u503C\u7531\u591A\u4E2A\u8DEF\u7531\u6A21\u5757\u7EC4\u6210

\u6CE8\u610F

\u540E\u7AEF\u63A5\u53E3\u8FD4\u56DE\u7684\u6570\u636E\u4E2D\u5FC5\u987B\u5305\u542BPageEnum.BASE_HOME\u6307\u5B9A\u7684\u8DEF\u7531\uFF08path\u5B9A\u4E49\u4E8Esrc/enums/pageEnum.ts\uFF09

[
+  {
+    path: '/dashboard',
+    name: 'Dashboard',
+    component: '/dashboard/welcome/index',
+    meta: {
+      title: 'routes.dashboard.welcome',
+      affix: true,
+      icon: 'ant-design:home-outlined',
+    },
+  },
+  {
+    path: '/permission',
+    name: 'Permission',
+    component: 'LAYOUT',
+    redirect: '/permission/front/page',
+    meta: {
+      icon: 'carbon:user-role',
+      title: 'routes.demo.permission.permission',
+    },
+    children: [
+      {
+        path: 'back',
+        name: 'PermissionBackDemo',
+        meta: {
+          title: 'routes.demo.permission.back',
+        },
+
+        children: [
+          {
+            path: 'page',
+            name: 'BackAuthPage',
+            component: '/demo/permission/back/index',
+            meta: {
+              title: 'routes.demo.permission.backPage',
+            },
+          },
+          {
+            path: 'btn',
+            name: 'BackAuthBtn',
+            component: '/demo/permission/back/Btn',
+            meta: {
+              title: 'routes.demo.permission.backBtn',
+            },
+          },
+        ],
+      },
+    ],
+  },
+];
+

\u52A8\u6001\u66F4\u6362\u83DC\u5355

\u7CFB\u7EDF\u63D0\u4F9B usePermission \u65B9\u4FBF\u89D2\u8272\u76F8\u5173\u64CD\u4F5C

import { usePermission } from '/@/hooks/web/usePermission';
+import { RoleEnum } from '/@/enums/roleEnum';
+
+export default defineComponent({
+  setup() {
+    const { changeMenu } = usePermission();
+
+    // \u66F4\u6539\u83DC\u5355\u7684\u5B9E\u73B0\u9700\u8981\u81EA\u884C\u53BB\u4FEE\u6539
+    changeMenu();
+    return {};
+  },
+});
+

\u7EC6\u7C92\u5EA6\u6743\u9650

\u51FD\u6570\u65B9\u5F0F

usePermission \u8FD8\u63D0\u4F9B\u4E86\u6309\u94AE\u7EA7\u522B\u7684\u6743\u9650\u63A7\u5236\u3002

<template>
+  <a-button v-if="hasPermission(['20000', '2000010'])" color="error" class="mx-4">
+    \u62E5\u6709[20000,2000010]code\u53EF\u89C1
+  </a-button>
+</template>
+<script lang="ts">
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { RoleEnum } from '/@/enums/roleEnum';
+
+  export default defineComponent({
+    setup() {
+      const { hasPermission } = usePermission();
+      return { hasPermission };
+    },
+  });
+</script>
+

\u7EC4\u4EF6\u65B9\u5F0F

\u5177\u4F53\u67E5\u770B\u6743\u9650\u7EC4\u4EF6\u4F7F\u7528

\u6307\u4EE4\u65B9\u5F0F

TIP

\u6307\u4EE4\u65B9\u5F0F\u4E0D\u80FD\u52A8\u6001\u66F4\u6539\u6743\u9650

<a-button v-auth="'1000'" type="primary" class="mx-4"> \u62E5\u6709code ['1000']\u6743\u9650\u53EF\u89C1 </a-button>
+

\u5982\u4F55\u521D\u59CB\u5316 code

\u901A\u5E38\uFF0C\u5982\u9700\u505A\u6309\u94AE\u7EA7\u522B\u6743\u9650\uFF0C\u540E\u53F0\u4F1A\u63D0\u4F9B\u76F8\u5E94\u7684 code\uFF0C\u6216\u8005\u7C7B\u578B\u7684\u5224\u65AD\u6807\u8BC6\u3002\u8FD9\u4E9B\u7F16\u7801\u53EA\u9700\u8981\u5728\u767B\u5F55\u540E\u83B7\u53D6\u4E00\u6B21\u5373\u53EF\u3002

import { getPermCodeByUserId } from '/@/api/sys/user';
+import { permissionStore } from '/@/store/modules/permission';
+async function changePermissionCode(userId: string) {
+  // \u4ECE\u540E\u53F0\u83B7\u53D6\u5F53\u524D\u7528\u6237\u62E5\u6709\u7684\u7F16\u7801
+  const codeList = await getPermCodeByUserId({ userId });
+  permissionStore.commitPermCodeListState(codeList);
+}
+
__VP_STATIC_END__`,55),e=[o];function c(u,l,i,k,r,d){return a(),s("div",null,e)}var h=n(p,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/guide_component.md.1c40f9d7.js b/assets/guide_component.md.1c40f9d7.js new file mode 100644 index 00000000..de715efd --- /dev/null +++ b/assets/guide_component.md.1c40f9d7.js @@ -0,0 +1,115 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const f='{"title":"\u7EC4\u4EF6\u6CE8\u518C","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u6309\u9700\u5F15\u5165","slug":"\u6309\u9700\u5F15\u5165"},{"level":3,"title":"tsx \u6587\u4EF6\u6CE8\u518C","slug":"tsx-\u6587\u4EF6\u6CE8\u518C"},{"level":2,"title":"\u5168\u5C40\u6CE8\u518C","slug":"\u5168\u5C40\u6CE8\u518C"},{"level":3,"title":"\u5168\u5C40\u6309\u9700\u6CE8\u518C","slug":"\u5168\u5C40\u6309\u9700\u6CE8\u518C"},{"level":3,"title":"\u5168\u91CF\u6CE8\u518C","slug":"\u5168\u91CF\u6CE8\u518C"}],"relativePath":"guide/component.md","lastUpdated":1694442156385}',p={},o=t(`

\u7EC4\u4EF6\u6CE8\u518C

\u6309\u9700\u5F15\u5165

\u9879\u76EE\u76EE\u524D\u7684\u7EC4\u4EF6\u6CE8\u518C\u673A\u5236\u662F\u6309\u9700\u6CE8\u518C\uFF0C\u662F\u5728\u9700\u8981\u7528\u5230\u7684\u9875\u9762\u624D\u5F15\u5165\u3002

<template>
+  <Menu>
+    <SubMenu></SubMenu>
+  <Menu>
+
+  <menu>
+    <sub-menu></sub-menu>
+  <menu>
+</template>
+<script>
+import { Menu } from 'ant-design-vue';
+export default defineComponent({
+  components: {
+    Menu: Menu,
+    SubMenu: Menu.SubMenu
+  },
+})
+</script>
+

tsx \u6587\u4EF6\u6CE8\u518C

tsx \u6587\u4EF6\u5185\u4E0D\u80FD\u4F7F\u7528\u5168\u5C40\u6CE8\u518C\u7EC4\u4EF6

import { Menu } from 'ant-design-vue';
+
+export default defineComponent({
+  setup() {
+    return () => (
+      <Menu>
+        <Menu.SubMenu></Menu.SubMenu>
+      </Menu>
+    );
+  },
+});
+

\u5168\u5C40\u6CE8\u518C

\u5982\u679C\u4E0D\u4E60\u60EF\u6309\u9700\u5F15\u5165\u65B9\u5F0F\uFF0C\u53EF\u4EE5\u8FDB\u884C\u5168\u5C40\u6CE8\u518C\u3002\u5168\u5C40\u6CE8\u518C\u4E5F\u5206\u4E24\u79CD\u65B9\u5F0F

\u5168\u5C40\u6309\u9700\u6CE8\u518C

\u53EA\u6CE8\u518C\u9700\u8981\u7684\u7EC4\u4EF6

\u4EE3\u7801\u5730\u5740\uFF1Asrc/components/registerGlobComp.ts

import {
+  // Need
+  Button as AntButton,
+  Optional
+  Select,
+  Alert,
+  Checkbox,
+  DatePicker,
+  Radio,
+  Switch,
+  Card,
+  List,
+  Tabs,
+  Descriptions,
+  Tree,
+  Table,
+  Divider,
+  Modal,
+  Drawer,
+  Dropdown,
+  Tag,
+  Tooltip,
+  Badge,
+  Popover,
+  Upload,
+  Transfer,
+  Steps,
+  PageHeader,
+  Result,
+  Empty,
+  Avatar,
+  Menu,
+  Breadcrumb,
+  Form,
+  Input,
+  Row,
+  Col,
+  Spin,
+} from 'ant-design-vue';
+
+export function registerGlobComp(app: App) {
+  app
+    .use(Select)
+    .use(Alert)
+    .use(Breadcrumb)
+    .use(Checkbox)
+    .use(DatePicker)
+    .use(Radio)
+    .use(Switch)
+    .use(Card)
+    .use(List)
+    .use(Descriptions)
+    .use(Tree)
+    .use(Table)
+    .use(Divider)
+    .use(Modal)
+    .use(Drawer)
+    .use(Dropdown)
+    .use(Tag)
+    .use(Tooltip)
+    .use(Badge)
+    .use(Popover)
+    .use(Upload)
+    .use(Transfer)
+    .use(Steps)
+    .use(PageHeader)
+    .use(Result)
+    .use(Empty)
+    .use(Avatar)
+    .use(Menu)
+    .use(Tabs)
+    .use(Form)
+    .use(Input)
+    .use(Row)
+    .use(Col)
+    .use(Spin);
+}
+

\u5168\u91CF\u6CE8\u518C

  • \u5728main.ts\u5185
import { createApp } from 'vue';
+import Antd from 'ant-design-vue';
+import 'ant-design-vue/dist/antd.less';
+const app = createApp(App);
+app.use(Antd);
+
  • \u5220\u9664\u4EE5\u4E0B\u4EE3\u7801
if (import.meta.env.DEV) {
+  import('ant-design-vue/dist/antd.less');
+}
+
`,18),c=[o];function e(u,l,i,k,r,d){return a(),s("div",null,c)}var m=n(p,[["render",e]]);export{f as __pageData,m as default}; diff --git a/assets/guide_component.md.1c40f9d7.lean.js b/assets/guide_component.md.1c40f9d7.lean.js new file mode 100644 index 00000000..bbff9f83 --- /dev/null +++ b/assets/guide_component.md.1c40f9d7.lean.js @@ -0,0 +1,115 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const f='{"title":"\u7EC4\u4EF6\u6CE8\u518C","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u6309\u9700\u5F15\u5165","slug":"\u6309\u9700\u5F15\u5165"},{"level":3,"title":"tsx \u6587\u4EF6\u6CE8\u518C","slug":"tsx-\u6587\u4EF6\u6CE8\u518C"},{"level":2,"title":"\u5168\u5C40\u6CE8\u518C","slug":"\u5168\u5C40\u6CE8\u518C"},{"level":3,"title":"\u5168\u5C40\u6309\u9700\u6CE8\u518C","slug":"\u5168\u5C40\u6309\u9700\u6CE8\u518C"},{"level":3,"title":"\u5168\u91CF\u6CE8\u518C","slug":"\u5168\u91CF\u6CE8\u518C"}],"relativePath":"guide/component.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

\u7EC4\u4EF6\u6CE8\u518C

\u6309\u9700\u5F15\u5165

\u9879\u76EE\u76EE\u524D\u7684\u7EC4\u4EF6\u6CE8\u518C\u673A\u5236\u662F\u6309\u9700\u6CE8\u518C\uFF0C\u662F\u5728\u9700\u8981\u7528\u5230\u7684\u9875\u9762\u624D\u5F15\u5165\u3002

<template>
+  <Menu>
+    <SubMenu></SubMenu>
+  <Menu>
+
+  <menu>
+    <sub-menu></sub-menu>
+  <menu>
+</template>
+<script>
+import { Menu } from 'ant-design-vue';
+export default defineComponent({
+  components: {
+    Menu: Menu,
+    SubMenu: Menu.SubMenu
+  },
+})
+</script>
+

tsx \u6587\u4EF6\u6CE8\u518C

tsx \u6587\u4EF6\u5185\u4E0D\u80FD\u4F7F\u7528\u5168\u5C40\u6CE8\u518C\u7EC4\u4EF6

import { Menu } from 'ant-design-vue';
+
+export default defineComponent({
+  setup() {
+    return () => (
+      <Menu>
+        <Menu.SubMenu></Menu.SubMenu>
+      </Menu>
+    );
+  },
+});
+

\u5168\u5C40\u6CE8\u518C

\u5982\u679C\u4E0D\u4E60\u60EF\u6309\u9700\u5F15\u5165\u65B9\u5F0F\uFF0C\u53EF\u4EE5\u8FDB\u884C\u5168\u5C40\u6CE8\u518C\u3002\u5168\u5C40\u6CE8\u518C\u4E5F\u5206\u4E24\u79CD\u65B9\u5F0F

\u5168\u5C40\u6309\u9700\u6CE8\u518C

\u53EA\u6CE8\u518C\u9700\u8981\u7684\u7EC4\u4EF6

\u4EE3\u7801\u5730\u5740\uFF1Asrc/components/registerGlobComp.ts

import {
+  // Need
+  Button as AntButton,
+  Optional
+  Select,
+  Alert,
+  Checkbox,
+  DatePicker,
+  Radio,
+  Switch,
+  Card,
+  List,
+  Tabs,
+  Descriptions,
+  Tree,
+  Table,
+  Divider,
+  Modal,
+  Drawer,
+  Dropdown,
+  Tag,
+  Tooltip,
+  Badge,
+  Popover,
+  Upload,
+  Transfer,
+  Steps,
+  PageHeader,
+  Result,
+  Empty,
+  Avatar,
+  Menu,
+  Breadcrumb,
+  Form,
+  Input,
+  Row,
+  Col,
+  Spin,
+} from 'ant-design-vue';
+
+export function registerGlobComp(app: App) {
+  app
+    .use(Select)
+    .use(Alert)
+    .use(Breadcrumb)
+    .use(Checkbox)
+    .use(DatePicker)
+    .use(Radio)
+    .use(Switch)
+    .use(Card)
+    .use(List)
+    .use(Descriptions)
+    .use(Tree)
+    .use(Table)
+    .use(Divider)
+    .use(Modal)
+    .use(Drawer)
+    .use(Dropdown)
+    .use(Tag)
+    .use(Tooltip)
+    .use(Badge)
+    .use(Popover)
+    .use(Upload)
+    .use(Transfer)
+    .use(Steps)
+    .use(PageHeader)
+    .use(Result)
+    .use(Empty)
+    .use(Avatar)
+    .use(Menu)
+    .use(Tabs)
+    .use(Form)
+    .use(Input)
+    .use(Row)
+    .use(Col)
+    .use(Spin);
+}
+

\u5168\u91CF\u6CE8\u518C

  • \u5728main.ts\u5185
import { createApp } from 'vue';
+import Antd from 'ant-design-vue';
+import 'ant-design-vue/dist/antd.less';
+const app = createApp(App);
+app.use(Antd);
+
  • \u5220\u9664\u4EE5\u4E0B\u4EE3\u7801
if (import.meta.env.DEV) {
+  import('ant-design-vue/dist/antd.less');
+}
+
__VP_STATIC_END__`,18),c=[o];function e(u,l,i,k,r,d){return a(),s("div",null,c)}var m=n(p,[["render",e]]);export{f as __pageData,m as default}; diff --git a/assets/guide_deploy.md.e4fab0c1.js b/assets/guide_deploy.md.e4fab0c1.js new file mode 100644 index 00000000..92e880d7 --- /dev/null +++ b/assets/guide_deploy.md.e4fab0c1.js @@ -0,0 +1,109 @@ +import{_ as n,f as a,e as s,N as e}from"./plugin-vue_export-helper.147b70e9.js";var t="/images/report.png";const m='{"title":"\u6784\u5EFA&\u90E8\u7F72","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u6784\u5EFA","slug":"\u6784\u5EFA"},{"level":3,"title":"\u65E7\u7248\u6D4F\u89C8\u5668\u517C\u5BB9","slug":"\u65E7\u7248\u6D4F\u89C8\u5668\u517C\u5BB9"},{"level":3,"title":"\u9884\u89C8","slug":"\u9884\u89C8"},{"level":3,"title":"\u5206\u6790\u6784\u5EFA\u6587\u4EF6\u4F53\u79EF","slug":"\u5206\u6790\u6784\u5EFA\u6587\u4EF6\u4F53\u79EF"},{"level":2,"title":"\u538B\u7F29","slug":"\u538B\u7F29"},{"level":3,"title":"\u5F00\u542F gzip \u538B\u7F29","slug":"\u5F00\u542F-gzip-\u538B\u7F29"},{"level":3,"title":"\u5F00\u542F brotli \u538B\u7F29","slug":"\u5F00\u542F-brotli-\u538B\u7F29"},{"level":3,"title":"\u540C\u65F6\u5F00\u542F gzip \u4E0E brotli","slug":"\u540C\u65F6\u5F00\u542F-gzip-\u4E0E-brotli"},{"level":3,"title":"gzip \u4E0E brotli \u5728 nginx \u5185\u7684\u914D\u7F6E","slug":"gzip-\u4E0E-brotli-\u5728-nginx-\u5185\u7684\u914D\u7F6E"},{"level":2,"title":"\u90E8\u7F72","slug":"\u90E8\u7F72"},{"level":3,"title":"\u53D1\u5E03","slug":"\u53D1\u5E03"},{"level":3,"title":"\u524D\u7AEF\u8DEF\u7531\u4E0E\u670D\u52A1\u7AEF\u7684\u7ED3\u5408","slug":"\u524D\u7AEF\u8DEF\u7531\u4E0E\u670D\u52A1\u7AEF\u7684\u7ED3\u5408"},{"level":3,"title":"history \u8DEF\u7531\u6A21\u5F0F\u4E0B\u670D\u52A1\u7AEF\u914D\u7F6E","slug":"history-\u8DEF\u7531\u6A21\u5F0F\u4E0B\u670D\u52A1\u7AEF\u914D\u7F6E"},{"level":3,"title":"\u4F7F\u7528 nginx \u5904\u7406\u8DE8\u57DF","slug":"\u4F7F\u7528-nginx-\u5904\u7406\u8DE8\u57DF"}],"relativePath":"guide/deploy.md","lastUpdated":1694442156385}',p={},o=e(`

\u6784\u5EFA&\u90E8\u7F72

\u524D\u8A00

\u7531\u4E8E\u662F\u5C55\u793A\u9879\u76EE\uFF0C\u6240\u4EE5\u6253\u5305\u540E\u76F8\u5BF9\u8F83\u5927\uFF0C\u5982\u679C\u9879\u76EE\u4E2D\u6CA1\u6709\u7528\u5230\u7684\u63D2\u4EF6\uFF0C\u53EF\u4EE5\u5220\u9664\u5BF9\u5E94\u7684\u6587\u4EF6\u6216\u8005\u8DEF\u7531\uFF0C\u4E0D\u5F15\u7528\u5373\u53EF\uFF0C\u6CA1\u6709\u5F15\u7528\u5C31\u4E0D\u4F1A\u6253\u5305\u3002

\u5F53\u7136\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u4F7F\u7528\u7CBE\u7B80\u7248 vue-vben-admin-thin \u8FDB\u884C\u5F00\u53D1\u3002

\u6784\u5EFA

\u9879\u76EE\u5F00\u53D1\u5B8C\u6210\u4E4B\u540E\uFF0C\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\u8FDB\u884C\u6784\u5EFA

yarn build
+

\u6784\u5EFA\u6253\u5305\u6210\u529F\u4E4B\u540E\uFF0C\u4F1A\u5728\u6839\u76EE\u5F55\u751F\u6210 dist \u6587\u4EF6\u5939\uFF0C\u91CC\u9762\u5C31\u662F\u6784\u5EFA\u6253\u5305\u597D\u7684\u6587\u4EF6

\u65E7\u7248\u6D4F\u89C8\u5668\u517C\u5BB9

\u5728 .env.production \u5185

\u8BBE\u7F6E VITE_LEGACY=true \u5373\u53EF\u6253\u5305\u51FA\u517C\u5BB9\u65E7\u7248\u6D4F\u89C8\u5668\u7684\u4EE3\u7801

VITE_LEGACY = true
+

\u9884\u89C8

\u53D1\u5E03\u4E4B\u524D\u53EF\u4EE5\u5728\u672C\u5730\u8FDB\u884C\u9884\u89C8\uFF0C\u6709\u591A\u79CD\u65B9\u5F0F\uFF0C\u8FD9\u91CC\u4ECB\u7ECD\u4E24\u79CD

\u4E0D\u80FD\u76F4\u63A5\u6253\u5F00\u6784\u5EFA\u540E\u7684 html \u6587\u4EF6

  • \u4F7F\u7528\u9879\u76EE\u81EA\u5B9A\u7684\u547D\u4EE4\u8FDB\u884C\u9884\u89C8(\u63A8\u8350)
# \u5148\u6253\u5305\u518D\u8FDB\u884C\u9884\u89C8
+yarn preview
+# \u76F4\u63A5\u9884\u89C8\u672C\u5730 dist \u6587\u4EF6\u76EE\u5F55
+yarn preview:dist
+
  • \u672C\u5730\u670D\u52A1\u5668\u9884\u89C8(\u901A\u8FC7 live-server)
# 1.\u5168\u5C40\u5B89\u88C5live-server
+yarn global add live-server
+# 2. \u8FDB\u5165\u6253\u5305\u7684\u540E\u76EE\u5F55
+cd ./dist
+# \u672C\u5730\u9884\u89C8\uFF0C\u9ED8\u8BA4\u7AEF\u53E38080
+live-server
+# \u6307\u5B9A\u7AEF\u53E3
+live-server --port 9000
+

\u5206\u6790\u6784\u5EFA\u6587\u4EF6\u4F53\u79EF

\u5982\u679C\u4F60\u7684\u6784\u5EFA\u6587\u4EF6\u5F88\u5927\uFF0C\u53EF\u4EE5\u901A\u8FC7\u9879\u76EE\u5185\u7F6E rollup-plugin-analyzer \u63D2\u4EF6\u8FDB\u884C\u4EE3\u7801\u4F53\u79EF\u5206\u6790\uFF0C\u4ECE\u800C\u4F18\u5316\u4F60\u7684\u4EE3\u7801\u3002

yarn report
+
+

\u8FD0\u884C\u4E4B\u540E\uFF0C\u5728\u81EA\u52A8\u6253\u5F00\u7684\u9875\u9762\u53EF\u4EE5\u770B\u5230\u5177\u4F53\u7684\u4F53\u79EF\u5206\u5E03\uFF0C\u4EE5\u5206\u6790\u54EA\u4E9B\u4F9D\u8D56\u6709\u95EE\u9898\u3002

TIP

\u5DE6\u4E0A\u89D2\u53EF\u4EE5\u5207\u6362 \u663E\u793A gzip \u6216\u8005 brotli

\u538B\u7F29

\u5F00\u542F gzip \u538B\u7F29

\u5F00\u542F gzip\uFF0C\u5E76\u914D\u5408 nginx \u7684 gzip_static \u529F\u80FD\u53EF\u4EE5\u5927\u5927\u52A0\u5FEB\u9875\u9762\u8BBF\u95EE\u901F\u5EA6

TIP

\u53EA\u9700\u5F00\u542F VITE_BUILD_COMPRESS='gzip' \u5373\u53EF\u5728\u6253\u5305\u7684\u540C\u65F6\u751F\u6210 .gz \u6587\u4EF6

# \u6839\u636E\u81EA\u5DF1\u8DEF\u5F84\u6765\u914D\u7F6E\u66F4\u6539
+# \u4F8B\u5982\u90E8\u7F72\u5728nginx /next/\u8DEF\u5F84\u4E0B  \u5219VITE_PUBLIC_PATH=/next/
+VITE_PUBLIC_PATH=/
+

\u5F00\u542F brotli \u538B\u7F29

brotli \u662F\u6BD4 gzip \u538B\u7F29\u7387\u66F4\u9AD8\u7684\u7B97\u6CD5\uFF0C\u53EF\u4EE5\u4E0E gzip \u5171\u5B58\u4E0D\u4F1A\u51B2\u7A81\uFF0C\u9700\u8981 nginx \u5B89\u88C5\u6307\u5B9A\u6A21\u5757\u5E76\u5F00\u542F\u5373\u53EF\u3002

TIP

\u53EA\u9700\u5F00\u542F VITE_BUILD_COMPRESS='brotli' \u5373\u53EF\u5728\u6253\u5305\u7684\u540C\u65F6\u751F\u6210 .br \u6587\u4EF6

# \u6839\u636E\u81EA\u5DF1\u8DEF\u5F84\u6765\u914D\u7F6E\u66F4\u6539
+# \u4F8B\u5982\u90E8\u7F72\u5728nginx /next/\u8DEF\u5F84\u4E0B  \u5219VITE_PUBLIC_PATH=/next/
+VITE_PUBLIC_PATH=/
+

\u540C\u65F6\u5F00\u542F gzip \u4E0E brotli

\u53EA\u9700\u5F00\u542F VITE_BUILD_COMPRESS='brotli,gzip' \u5373\u53EF\u5728\u6253\u5305\u7684\u540C\u65F6\u751F\u6210 .gz \u548C .br \u6587\u4EF6\u3002

gzip \u4E0E brotli \u5728 nginx \u5185\u7684\u914D\u7F6E

http {
+  # \u5F00\u542Fgzip
+  gzip on;
+  # \u5F00\u542Fgzip_static
+  # gzip_static \u5F00\u542F\u540E\u53EF\u80FD\u4F1A\u62A5\u9519\uFF0C\u9700\u8981\u5B89\u88C5\u76F8\u5E94\u7684\u6A21\u5757, \u5177\u4F53\u5B89\u88C5\u65B9\u5F0F\u53EF\u4EE5\u81EA\u884C\u67E5\u8BE2
+  # \u53EA\u6709\u8FD9\u4E2A\u5F00\u542F\uFF0Cvue\u6587\u4EF6\u6253\u5305\u7684.gz\u6587\u4EF6\u624D\u4F1A\u6709\u6548\u679C\uFF0C\u5426\u5219\u4E0D\u9700\u8981\u5F00\u542Fgzip\u8FDB\u884C\u6253\u5305
+  gzip_static on;
+  gzip_proxied any;
+  gzip_min_length 1k;
+  gzip_buffers 4 16k;
+  #\u5982\u679Cnginx\u4E2D\u4F7F\u7528\u4E86\u591A\u5C42\u4EE3\u7406 \u5FC5\u987B\u8BBE\u7F6E\u8FD9\u4E2A\u624D\u53EF\u4EE5\u5F00\u542Fgzip\u3002
+  gzip_http_version 1.0;
+  gzip_comp_level 2;
+  gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
+  gzip_vary off;
+  gzip_disable "MSIE [1-6]\\.";
+
+  # \u5F00\u542F brotli\u538B\u7F29
+  # \u9700\u8981\u5B89\u88C5\u5BF9\u5E94\u7684nginx\u6A21\u5757,\u5177\u4F53\u5B89\u88C5\u65B9\u5F0F\u53EF\u4EE5\u81EA\u884C\u67E5\u8BE2
+  # \u53EF\u4EE5\u4E0Egzip\u5171\u5B58\u4E0D\u4F1A\u51B2\u7A81
+  brotli on;
+  brotli_comp_level 6;
+  brotli_buffers 16 8k;
+  brotli_min_length 20;
+  brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
+}
+

\u90E8\u7F72

\u6CE8\u610F

\u9879\u76EE\u9ED8\u8BA4\u662F\u5728\u751F\u4EA7\u73AF\u5883\u5F00\u542F Mock\uFF0C\u8FD9\u6837\u505A\u975E\u5E38\u4E0D\u597D\uFF0C\u53EA\u662F\u4E3A\u4E86\u6F14\u793A\u73AF\u5883\u6709\u6570\u636E\uFF0C\u4E0D\u5EFA\u8BAE\u5728\u751F\u4EA7\u73AF\u5883\u4F7F\u7528 Mock\uFF0C\u800C\u5E94\u8BE5\u4F7F\u7528\u771F\u5B9E\u7684\u540E\u53F0\u63A5\u53E3\uFF0C\u5E76\u5C06 Mock \u5173\u95ED\u3002

\u53D1\u5E03

\u7B80\u5355\u7684\u90E8\u7F72\u53EA\u9700\u8981\u5C06\u6700\u7EC8\u751F\u6210\u7684\u9759\u6001\u6587\u4EF6\uFF0Cdist \u6587\u4EF6\u5939\u7684\u9759\u6001\u6587\u4EF6\u53D1\u5E03\u5230\u4F60\u7684 cdn \u6216\u8005\u9759\u6001\u670D\u52A1\u5668\u5373\u53EF\uFF0C\u9700\u8981\u6CE8\u610F\u7684\u662F\u5176\u4E2D\u7684 index.html \u901A\u5E38\u4F1A\u662F\u4F60\u540E\u53F0\u670D\u52A1\u7684\u5165\u53E3\u9875\u9762\uFF0C\u5728\u786E\u5B9A\u4E86 js \u548C css \u7684\u9759\u6001\u4E4B\u540E\u53EF\u80FD\u9700\u8981\u6539\u53D8\u9875\u9762\u7684\u5F15\u5165\u8DEF\u5F84\u3002

\u4F8B\u5982\u4E0A\u4F20\u5230 nginx

/srv/www/project/index.html

# nginx\u914D\u7F6E
+location / {
+  # \u4E0D\u7F13\u5B58html\uFF0C\u9632\u6B62\u7A0B\u5E8F\u66F4\u65B0\u540E\u7F13\u5B58\u7EE7\u7EED\u751F\u6548
+  if ($request_filename ~* .*\\.(?:htm|html)$) {
+    add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
+    access_log on;
+  }
+  # \u8FD9\u91CC\u662Fvue\u6253\u5305\u6587\u4EF6dist\u5185\u7684\u6587\u4EF6\u7684\u5B58\u653E\u8DEF\u5F84
+  root   /srv/www/project/;
+  index  index.html index.htm;
+}
+
+

\u90E8\u7F72\u65F6\u53EF\u80FD\u4F1A\u53D1\u73B0\u8D44\u6E90\u8DEF\u5F84\u4E0D\u5BF9\uFF0C\u53EA\u9700\u8981\u4FEE\u6539.env.production\u6587\u4EF6\u5373\u53EF\u3002

# \u6839\u636E\u81EA\u5DF1\u8DEF\u5F84\u6765\u914D\u7F6E\u66F4\u6539
+# \u6CE8\u610F\u9700\u8981\u4EE5 / \u5F00\u5934\u548C\u7ED3\u5C3E
+VITE_PUBLIC_PATH=/
+VITE_PUBLIC_PATH=/xxx/
+

\u524D\u7AEF\u8DEF\u7531\u4E0E\u670D\u52A1\u7AEF\u7684\u7ED3\u5408

\u9879\u76EE\u524D\u7AEF\u8DEF\u7531\u4F7F\u7528\u7684\u662F vue-router\uFF0C\u6240\u4EE5\u4F60\u53EF\u4EE5\u9009\u62E9\u4E24\u79CD\u65B9\u5F0F\uFF1Ahistory \u548C hash\u3002

  • hash \u9ED8\u8BA4\u4F1A\u5728 url \u540E\u9762\u62FC\u63A5#
  • history \u5219\u4E0D\u4F1A\uFF0C\u4E0D\u8FC7 history \u9700\u8981\u670D\u52A1\u5668\u914D\u5408

\u53EF\u5728 src/router/index.ts \u5185\u8FDB\u884C mode \u4FEE\u6539

import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
+
+createRouter({
+  history: createWebHashHistory(),
+  // or
+  history: createWebHistory(),
+});
+

history \u8DEF\u7531\u6A21\u5F0F\u4E0B\u670D\u52A1\u7AEF\u914D\u7F6E

\u5F00\u542F history \u6A21\u5F0F\u9700\u8981\u670D\u52A1\u5668\u914D\u7F6E\uFF0C\u66F4\u591A\u7684\u670D\u52A1\u5668\u914D\u7F6E\u8BE6\u60C5\u53EF\u4EE5\u770B history-mode

\u8FD9\u91CC\u4EE5 nginx \u914D\u7F6E\u4E3A\u4F8B

\u90E8\u7F72\u5230\u6839\u76EE\u5F55

server {
+  listen 80;
+  location / {
+    # \u7528\u4E8E\u914D\u5408 History \u4F7F\u7528
+    try_files $uri $uri/ /index.html;
+  }
+}
+

\u90E8\u7F72\u5230\u975E\u6839\u76EE\u5F55

  1. \u9996\u5148\u9700\u8981\u5728\u6253\u5305\u7684\u65F6\u5019\u66F4\u6539\u914D\u7F6E
# \u5728.env.production\u5185\uFF0C\u914D\u7F6E\u5B50\u76EE\u5F55\u8DEF\u5F84
+VITE_PUBLIC_PATH = /sub/
+
server {
+    listen       80;
+    server_name  localhost;
+    location /sub/ {
+      # \u8FD9\u91CC\u662Fvue\u6253\u5305\u6587\u4EF6dist\u5185\u7684\u6587\u4EF6\u7684\u5B58\u653E\u8DEF\u5F84
+      alias   /srv/www/project/;
+      index index.html index.htm;
+      try_files $uri $uri/ /sub/index.html;
+    }
+}
+

\u4F7F\u7528 nginx \u5904\u7406\u8DE8\u57DF

\u4F7F\u7528 nginx \u5904\u7406\u9879\u76EE\u90E8\u7F72\u540E\u7684\u8DE8\u57DF\u95EE\u9898

  1. \u914D\u7F6E\u524D\u7AEF\u9879\u76EE\u63A5\u53E3\u5730\u5740
# \u5728.env.production\u5185\uFF0C\u914D\u7F6E\u63A5\u53E3\u5730\u5740
+VITE_GLOB_API_URL=/api
+
  1. \u5728 nginx \u914D\u7F6E\u8BF7\u6C42\u8F6C\u53D1\u5230\u540E\u53F0
server {
+  listen       8080;
+  server_name  localhost;
+  # \u63A5\u53E3\u4EE3\u7406\uFF0C\u7528\u4E8E\u89E3\u51B3\u8DE8\u57DF\u95EE\u9898
+  location /api {
+    proxy_set_header Host $host;
+    proxy_set_header X-Real-IP $remote_addr;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    # \u540E\u53F0\u63A5\u53E3\u5730\u5740
+    proxy_pass http://110.110.1.1:8080/api;
+    proxy_redirect default;
+    add_header Access-Control-Allow-Origin *;
+    add_header Access-Control-Allow-Headers X-Requested-With;
+    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
+  }
+}
+
`,65),c=[o];function i(l,r,u,d,k,h){return s(),a("div",null,c)}var v=n(p,[["render",i]]);export{m as __pageData,v as default}; diff --git a/assets/guide_deploy.md.e4fab0c1.lean.js b/assets/guide_deploy.md.e4fab0c1.lean.js new file mode 100644 index 00000000..8f885987 --- /dev/null +++ b/assets/guide_deploy.md.e4fab0c1.lean.js @@ -0,0 +1,109 @@ +import{_ as n,f as a,e as s,N as e}from"./plugin-vue_export-helper.147b70e9.js";var t="/images/report.png";const m='{"title":"\u6784\u5EFA&\u90E8\u7F72","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u6784\u5EFA","slug":"\u6784\u5EFA"},{"level":3,"title":"\u65E7\u7248\u6D4F\u89C8\u5668\u517C\u5BB9","slug":"\u65E7\u7248\u6D4F\u89C8\u5668\u517C\u5BB9"},{"level":3,"title":"\u9884\u89C8","slug":"\u9884\u89C8"},{"level":3,"title":"\u5206\u6790\u6784\u5EFA\u6587\u4EF6\u4F53\u79EF","slug":"\u5206\u6790\u6784\u5EFA\u6587\u4EF6\u4F53\u79EF"},{"level":2,"title":"\u538B\u7F29","slug":"\u538B\u7F29"},{"level":3,"title":"\u5F00\u542F gzip \u538B\u7F29","slug":"\u5F00\u542F-gzip-\u538B\u7F29"},{"level":3,"title":"\u5F00\u542F brotli \u538B\u7F29","slug":"\u5F00\u542F-brotli-\u538B\u7F29"},{"level":3,"title":"\u540C\u65F6\u5F00\u542F gzip \u4E0E brotli","slug":"\u540C\u65F6\u5F00\u542F-gzip-\u4E0E-brotli"},{"level":3,"title":"gzip \u4E0E brotli \u5728 nginx \u5185\u7684\u914D\u7F6E","slug":"gzip-\u4E0E-brotli-\u5728-nginx-\u5185\u7684\u914D\u7F6E"},{"level":2,"title":"\u90E8\u7F72","slug":"\u90E8\u7F72"},{"level":3,"title":"\u53D1\u5E03","slug":"\u53D1\u5E03"},{"level":3,"title":"\u524D\u7AEF\u8DEF\u7531\u4E0E\u670D\u52A1\u7AEF\u7684\u7ED3\u5408","slug":"\u524D\u7AEF\u8DEF\u7531\u4E0E\u670D\u52A1\u7AEF\u7684\u7ED3\u5408"},{"level":3,"title":"history \u8DEF\u7531\u6A21\u5F0F\u4E0B\u670D\u52A1\u7AEF\u914D\u7F6E","slug":"history-\u8DEF\u7531\u6A21\u5F0F\u4E0B\u670D\u52A1\u7AEF\u914D\u7F6E"},{"level":3,"title":"\u4F7F\u7528 nginx \u5904\u7406\u8DE8\u57DF","slug":"\u4F7F\u7528-nginx-\u5904\u7406\u8DE8\u57DF"}],"relativePath":"guide/deploy.md","lastUpdated":1694442156385}',p={},o=e(`__VP_STATIC_START__

\u6784\u5EFA&\u90E8\u7F72

\u524D\u8A00

\u7531\u4E8E\u662F\u5C55\u793A\u9879\u76EE\uFF0C\u6240\u4EE5\u6253\u5305\u540E\u76F8\u5BF9\u8F83\u5927\uFF0C\u5982\u679C\u9879\u76EE\u4E2D\u6CA1\u6709\u7528\u5230\u7684\u63D2\u4EF6\uFF0C\u53EF\u4EE5\u5220\u9664\u5BF9\u5E94\u7684\u6587\u4EF6\u6216\u8005\u8DEF\u7531\uFF0C\u4E0D\u5F15\u7528\u5373\u53EF\uFF0C\u6CA1\u6709\u5F15\u7528\u5C31\u4E0D\u4F1A\u6253\u5305\u3002

\u5F53\u7136\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u4F7F\u7528\u7CBE\u7B80\u7248 vue-vben-admin-thin \u8FDB\u884C\u5F00\u53D1\u3002

\u6784\u5EFA

\u9879\u76EE\u5F00\u53D1\u5B8C\u6210\u4E4B\u540E\uFF0C\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\u8FDB\u884C\u6784\u5EFA

yarn build
+

\u6784\u5EFA\u6253\u5305\u6210\u529F\u4E4B\u540E\uFF0C\u4F1A\u5728\u6839\u76EE\u5F55\u751F\u6210 dist \u6587\u4EF6\u5939\uFF0C\u91CC\u9762\u5C31\u662F\u6784\u5EFA\u6253\u5305\u597D\u7684\u6587\u4EF6

\u65E7\u7248\u6D4F\u89C8\u5668\u517C\u5BB9

\u5728 .env.production \u5185

\u8BBE\u7F6E VITE_LEGACY=true \u5373\u53EF\u6253\u5305\u51FA\u517C\u5BB9\u65E7\u7248\u6D4F\u89C8\u5668\u7684\u4EE3\u7801

VITE_LEGACY = true
+

\u9884\u89C8

\u53D1\u5E03\u4E4B\u524D\u53EF\u4EE5\u5728\u672C\u5730\u8FDB\u884C\u9884\u89C8\uFF0C\u6709\u591A\u79CD\u65B9\u5F0F\uFF0C\u8FD9\u91CC\u4ECB\u7ECD\u4E24\u79CD

\u4E0D\u80FD\u76F4\u63A5\u6253\u5F00\u6784\u5EFA\u540E\u7684 html \u6587\u4EF6

  • \u4F7F\u7528\u9879\u76EE\u81EA\u5B9A\u7684\u547D\u4EE4\u8FDB\u884C\u9884\u89C8(\u63A8\u8350)
# \u5148\u6253\u5305\u518D\u8FDB\u884C\u9884\u89C8
+yarn preview
+# \u76F4\u63A5\u9884\u89C8\u672C\u5730 dist \u6587\u4EF6\u76EE\u5F55
+yarn preview:dist
+
  • \u672C\u5730\u670D\u52A1\u5668\u9884\u89C8(\u901A\u8FC7 live-server)
# 1.\u5168\u5C40\u5B89\u88C5live-server
+yarn global add live-server
+# 2. \u8FDB\u5165\u6253\u5305\u7684\u540E\u76EE\u5F55
+cd ./dist
+# \u672C\u5730\u9884\u89C8\uFF0C\u9ED8\u8BA4\u7AEF\u53E38080
+live-server
+# \u6307\u5B9A\u7AEF\u53E3
+live-server --port 9000
+

\u5206\u6790\u6784\u5EFA\u6587\u4EF6\u4F53\u79EF

\u5982\u679C\u4F60\u7684\u6784\u5EFA\u6587\u4EF6\u5F88\u5927\uFF0C\u53EF\u4EE5\u901A\u8FC7\u9879\u76EE\u5185\u7F6E rollup-plugin-analyzer \u63D2\u4EF6\u8FDB\u884C\u4EE3\u7801\u4F53\u79EF\u5206\u6790\uFF0C\u4ECE\u800C\u4F18\u5316\u4F60\u7684\u4EE3\u7801\u3002

yarn report
+
+

\u8FD0\u884C\u4E4B\u540E\uFF0C\u5728\u81EA\u52A8\u6253\u5F00\u7684\u9875\u9762\u53EF\u4EE5\u770B\u5230\u5177\u4F53\u7684\u4F53\u79EF\u5206\u5E03\uFF0C\u4EE5\u5206\u6790\u54EA\u4E9B\u4F9D\u8D56\u6709\u95EE\u9898\u3002

TIP

\u5DE6\u4E0A\u89D2\u53EF\u4EE5\u5207\u6362 \u663E\u793A gzip \u6216\u8005 brotli

\u538B\u7F29

\u5F00\u542F gzip \u538B\u7F29

\u5F00\u542F gzip\uFF0C\u5E76\u914D\u5408 nginx \u7684 gzip_static \u529F\u80FD\u53EF\u4EE5\u5927\u5927\u52A0\u5FEB\u9875\u9762\u8BBF\u95EE\u901F\u5EA6

TIP

\u53EA\u9700\u5F00\u542F VITE_BUILD_COMPRESS='gzip' \u5373\u53EF\u5728\u6253\u5305\u7684\u540C\u65F6\u751F\u6210 .gz \u6587\u4EF6

# \u6839\u636E\u81EA\u5DF1\u8DEF\u5F84\u6765\u914D\u7F6E\u66F4\u6539
+# \u4F8B\u5982\u90E8\u7F72\u5728nginx /next/\u8DEF\u5F84\u4E0B  \u5219VITE_PUBLIC_PATH=/next/
+VITE_PUBLIC_PATH=/
+

\u5F00\u542F brotli \u538B\u7F29

brotli \u662F\u6BD4 gzip \u538B\u7F29\u7387\u66F4\u9AD8\u7684\u7B97\u6CD5\uFF0C\u53EF\u4EE5\u4E0E gzip \u5171\u5B58\u4E0D\u4F1A\u51B2\u7A81\uFF0C\u9700\u8981 nginx \u5B89\u88C5\u6307\u5B9A\u6A21\u5757\u5E76\u5F00\u542F\u5373\u53EF\u3002

TIP

\u53EA\u9700\u5F00\u542F VITE_BUILD_COMPRESS='brotli' \u5373\u53EF\u5728\u6253\u5305\u7684\u540C\u65F6\u751F\u6210 .br \u6587\u4EF6

# \u6839\u636E\u81EA\u5DF1\u8DEF\u5F84\u6765\u914D\u7F6E\u66F4\u6539
+# \u4F8B\u5982\u90E8\u7F72\u5728nginx /next/\u8DEF\u5F84\u4E0B  \u5219VITE_PUBLIC_PATH=/next/
+VITE_PUBLIC_PATH=/
+

\u540C\u65F6\u5F00\u542F gzip \u4E0E brotli

\u53EA\u9700\u5F00\u542F VITE_BUILD_COMPRESS='brotli,gzip' \u5373\u53EF\u5728\u6253\u5305\u7684\u540C\u65F6\u751F\u6210 .gz \u548C .br \u6587\u4EF6\u3002

gzip \u4E0E brotli \u5728 nginx \u5185\u7684\u914D\u7F6E

http {
+  # \u5F00\u542Fgzip
+  gzip on;
+  # \u5F00\u542Fgzip_static
+  # gzip_static \u5F00\u542F\u540E\u53EF\u80FD\u4F1A\u62A5\u9519\uFF0C\u9700\u8981\u5B89\u88C5\u76F8\u5E94\u7684\u6A21\u5757, \u5177\u4F53\u5B89\u88C5\u65B9\u5F0F\u53EF\u4EE5\u81EA\u884C\u67E5\u8BE2
+  # \u53EA\u6709\u8FD9\u4E2A\u5F00\u542F\uFF0Cvue\u6587\u4EF6\u6253\u5305\u7684.gz\u6587\u4EF6\u624D\u4F1A\u6709\u6548\u679C\uFF0C\u5426\u5219\u4E0D\u9700\u8981\u5F00\u542Fgzip\u8FDB\u884C\u6253\u5305
+  gzip_static on;
+  gzip_proxied any;
+  gzip_min_length 1k;
+  gzip_buffers 4 16k;
+  #\u5982\u679Cnginx\u4E2D\u4F7F\u7528\u4E86\u591A\u5C42\u4EE3\u7406 \u5FC5\u987B\u8BBE\u7F6E\u8FD9\u4E2A\u624D\u53EF\u4EE5\u5F00\u542Fgzip\u3002
+  gzip_http_version 1.0;
+  gzip_comp_level 2;
+  gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
+  gzip_vary off;
+  gzip_disable "MSIE [1-6]\\.";
+
+  # \u5F00\u542F brotli\u538B\u7F29
+  # \u9700\u8981\u5B89\u88C5\u5BF9\u5E94\u7684nginx\u6A21\u5757,\u5177\u4F53\u5B89\u88C5\u65B9\u5F0F\u53EF\u4EE5\u81EA\u884C\u67E5\u8BE2
+  # \u53EF\u4EE5\u4E0Egzip\u5171\u5B58\u4E0D\u4F1A\u51B2\u7A81
+  brotli on;
+  brotli_comp_level 6;
+  brotli_buffers 16 8k;
+  brotli_min_length 20;
+  brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
+}
+

\u90E8\u7F72

\u6CE8\u610F

\u9879\u76EE\u9ED8\u8BA4\u662F\u5728\u751F\u4EA7\u73AF\u5883\u5F00\u542F Mock\uFF0C\u8FD9\u6837\u505A\u975E\u5E38\u4E0D\u597D\uFF0C\u53EA\u662F\u4E3A\u4E86\u6F14\u793A\u73AF\u5883\u6709\u6570\u636E\uFF0C\u4E0D\u5EFA\u8BAE\u5728\u751F\u4EA7\u73AF\u5883\u4F7F\u7528 Mock\uFF0C\u800C\u5E94\u8BE5\u4F7F\u7528\u771F\u5B9E\u7684\u540E\u53F0\u63A5\u53E3\uFF0C\u5E76\u5C06 Mock \u5173\u95ED\u3002

\u53D1\u5E03

\u7B80\u5355\u7684\u90E8\u7F72\u53EA\u9700\u8981\u5C06\u6700\u7EC8\u751F\u6210\u7684\u9759\u6001\u6587\u4EF6\uFF0Cdist \u6587\u4EF6\u5939\u7684\u9759\u6001\u6587\u4EF6\u53D1\u5E03\u5230\u4F60\u7684 cdn \u6216\u8005\u9759\u6001\u670D\u52A1\u5668\u5373\u53EF\uFF0C\u9700\u8981\u6CE8\u610F\u7684\u662F\u5176\u4E2D\u7684 index.html \u901A\u5E38\u4F1A\u662F\u4F60\u540E\u53F0\u670D\u52A1\u7684\u5165\u53E3\u9875\u9762\uFF0C\u5728\u786E\u5B9A\u4E86 js \u548C css \u7684\u9759\u6001\u4E4B\u540E\u53EF\u80FD\u9700\u8981\u6539\u53D8\u9875\u9762\u7684\u5F15\u5165\u8DEF\u5F84\u3002

\u4F8B\u5982\u4E0A\u4F20\u5230 nginx

/srv/www/project/index.html

# nginx\u914D\u7F6E
+location / {
+  # \u4E0D\u7F13\u5B58html\uFF0C\u9632\u6B62\u7A0B\u5E8F\u66F4\u65B0\u540E\u7F13\u5B58\u7EE7\u7EED\u751F\u6548
+  if ($request_filename ~* .*\\.(?:htm|html)$) {
+    add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
+    access_log on;
+  }
+  # \u8FD9\u91CC\u662Fvue\u6253\u5305\u6587\u4EF6dist\u5185\u7684\u6587\u4EF6\u7684\u5B58\u653E\u8DEF\u5F84
+  root   /srv/www/project/;
+  index  index.html index.htm;
+}
+
+

\u90E8\u7F72\u65F6\u53EF\u80FD\u4F1A\u53D1\u73B0\u8D44\u6E90\u8DEF\u5F84\u4E0D\u5BF9\uFF0C\u53EA\u9700\u8981\u4FEE\u6539.env.production\u6587\u4EF6\u5373\u53EF\u3002

# \u6839\u636E\u81EA\u5DF1\u8DEF\u5F84\u6765\u914D\u7F6E\u66F4\u6539
+# \u6CE8\u610F\u9700\u8981\u4EE5 / \u5F00\u5934\u548C\u7ED3\u5C3E
+VITE_PUBLIC_PATH=/
+VITE_PUBLIC_PATH=/xxx/
+

\u524D\u7AEF\u8DEF\u7531\u4E0E\u670D\u52A1\u7AEF\u7684\u7ED3\u5408

\u9879\u76EE\u524D\u7AEF\u8DEF\u7531\u4F7F\u7528\u7684\u662F vue-router\uFF0C\u6240\u4EE5\u4F60\u53EF\u4EE5\u9009\u62E9\u4E24\u79CD\u65B9\u5F0F\uFF1Ahistory \u548C hash\u3002

  • hash \u9ED8\u8BA4\u4F1A\u5728 url \u540E\u9762\u62FC\u63A5#
  • history \u5219\u4E0D\u4F1A\uFF0C\u4E0D\u8FC7 history \u9700\u8981\u670D\u52A1\u5668\u914D\u5408

\u53EF\u5728 src/router/index.ts \u5185\u8FDB\u884C mode \u4FEE\u6539

import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
+
+createRouter({
+  history: createWebHashHistory(),
+  // or
+  history: createWebHistory(),
+});
+

history \u8DEF\u7531\u6A21\u5F0F\u4E0B\u670D\u52A1\u7AEF\u914D\u7F6E

\u5F00\u542F history \u6A21\u5F0F\u9700\u8981\u670D\u52A1\u5668\u914D\u7F6E\uFF0C\u66F4\u591A\u7684\u670D\u52A1\u5668\u914D\u7F6E\u8BE6\u60C5\u53EF\u4EE5\u770B history-mode

\u8FD9\u91CC\u4EE5 nginx \u914D\u7F6E\u4E3A\u4F8B

\u90E8\u7F72\u5230\u6839\u76EE\u5F55

server {
+  listen 80;
+  location / {
+    # \u7528\u4E8E\u914D\u5408 History \u4F7F\u7528
+    try_files $uri $uri/ /index.html;
+  }
+}
+

\u90E8\u7F72\u5230\u975E\u6839\u76EE\u5F55

  1. \u9996\u5148\u9700\u8981\u5728\u6253\u5305\u7684\u65F6\u5019\u66F4\u6539\u914D\u7F6E
# \u5728.env.production\u5185\uFF0C\u914D\u7F6E\u5B50\u76EE\u5F55\u8DEF\u5F84
+VITE_PUBLIC_PATH = /sub/
+
server {
+    listen       80;
+    server_name  localhost;
+    location /sub/ {
+      # \u8FD9\u91CC\u662Fvue\u6253\u5305\u6587\u4EF6dist\u5185\u7684\u6587\u4EF6\u7684\u5B58\u653E\u8DEF\u5F84
+      alias   /srv/www/project/;
+      index index.html index.htm;
+      try_files $uri $uri/ /sub/index.html;
+    }
+}
+

\u4F7F\u7528 nginx \u5904\u7406\u8DE8\u57DF

\u4F7F\u7528 nginx \u5904\u7406\u9879\u76EE\u90E8\u7F72\u540E\u7684\u8DE8\u57DF\u95EE\u9898

  1. \u914D\u7F6E\u524D\u7AEF\u9879\u76EE\u63A5\u53E3\u5730\u5740
# \u5728.env.production\u5185\uFF0C\u914D\u7F6E\u63A5\u53E3\u5730\u5740
+VITE_GLOB_API_URL=/api
+
  1. \u5728 nginx \u914D\u7F6E\u8BF7\u6C42\u8F6C\u53D1\u5230\u540E\u53F0
server {
+  listen       8080;
+  server_name  localhost;
+  # \u63A5\u53E3\u4EE3\u7406\uFF0C\u7528\u4E8E\u89E3\u51B3\u8DE8\u57DF\u95EE\u9898
+  location /api {
+    proxy_set_header Host $host;
+    proxy_set_header X-Real-IP $remote_addr;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    # \u540E\u53F0\u63A5\u53E3\u5730\u5740
+    proxy_pass http://110.110.1.1:8080/api;
+    proxy_redirect default;
+    add_header Access-Control-Allow-Origin *;
+    add_header Access-Control-Allow-Headers X-Requested-With;
+    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
+  }
+}
+
__VP_STATIC_END__`,65),c=[o];function i(l,r,u,d,k,h){return s(),a("div",null,c)}var v=n(p,[["render",i]]);export{m as __pageData,v as default}; diff --git a/assets/guide_design.md.3cf5232f.js b/assets/guide_design.md.3cf5232f.js new file mode 100644 index 00000000..0479fd8b --- /dev/null +++ b/assets/guide_design.md.3cf5232f.js @@ -0,0 +1,77 @@ +import{_ as s,f as n,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u6837\u5F0F","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4ECB\u7ECD","slug":"\u4ECB\u7ECD"},{"level":2,"title":"tailwindcss(2.5.0+)","slug":"tailwindcss-2-5-0"},{"level":2,"title":"windicss(2.5.0 \u5DF2\u5F03\u7528)","slug":"windicss-2-5-0-\u5DF2\u5F03\u7528"},{"level":2,"title":"\u4E3A\u4EC0\u4E48\u4F7F\u7528 Less","slug":"\u4E3A\u4EC0\u4E48\u4F7F\u7528-less"},{"level":2,"title":"\u5F00\u542F scoped","slug":"\u5F00\u542F-scoped"},{"level":2,"title":"\u6DF1\u5EA6\u9009\u62E9\u5668","slug":"\u6DF1\u5EA6\u9009\u62E9\u5668"},{"level":2,"title":"CSS Modules","slug":"css-modules"},{"level":2,"title":"\u91CD\u590D\u5F15\u7528\u95EE\u9898","slug":"\u91CD\u590D\u5F15\u7528\u95EE\u9898"}],"relativePath":"guide/design.md","lastUpdated":1694442156385}',p={},e=t(`

\u6837\u5F0F

\u4ECB\u7ECD

\u4E3B\u8981\u4ECB\u7ECD\u5982\u4F55\u5728\u9879\u76EE\u4E2D\u4F7F\u7528\u548C\u89C4\u5212\u6837\u5F0F\u6587\u4EF6\u3002

\u9ED8\u8BA4\u4F7F\u7528 less \u4F5C\u4E3A\u9884\u5904\u7406\u8BED\u8A00\uFF0C\u5EFA\u8BAE\u5728\u4F7F\u7528\u524D\u6216\u8005\u9047\u5230\u7591\u95EE\u65F6\u5B66\u4E60\u4E00\u4E0B Less \u7684\u76F8\u5173\u7279\u6027\uFF08\u5982\u679C\u60F3\u83B7\u53D6\u57FA\u7840\u7684 CSS \u77E5\u8BC6\u6216\u67E5\u9605\u5C5E\u6027\uFF0C\u8BF7\u53C2\u8003 MDN \u6587\u6863\uFF09\u3002

\u9879\u76EE\u4E2D\u4F7F\u7528\u7684\u901A\u7528\u6837\u5F0F\uFF0C\u90FD\u5B58\u653E\u4E8E src/design/ \u4E0B\u9762\u3002

.
+\u251C\u2500\u2500 ant # ant design \u4E00\u4E9B\u6837\u5F0F\u8986\u76D6
+\u251C\u2500\u2500 color.less # \u989C\u8272
+\u251C\u2500\u2500 index.less # \u5165\u53E3
+\u251C\u2500\u2500 public.less # \u516C\u5171\u7C7B
+\u251C\u2500\u2500 theme.less # \u4E3B\u9898\u76F8\u5173
+\u251C\u2500\u2500 config.less  # \u6BCF\u4E2A\u7EC4\u4EF6\u90FD\u4F1A\u81EA\u52A8\u5F15\u5165\u6837\u5F0F
+\u251C\u2500\u2500 transition # \u52A8\u753B\u76F8\u5173
+\u2514\u2500\u2500 var # \u53D8\u91CF
+
+

\u5168\u5C40\u6CE8\u5165

config.less \u8FD9\u4E2A\u6587\u4EF6\u4F1A\u88AB\u5168\u5C40\u6CE8\u5165\u5230\u6240\u6709\u6587\u4EF6\uFF0C\u6240\u4EE5\u5728\u9875\u9762\u5185\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u53D8\u91CF\u800C\u4E0D\u9700\u8981\u624B\u52A8\u5F15\u5165

<style lang="less" scoped>
+  // \u8FD9\u91CC\u5DF2\u7ECF\u9690\u5F0F\u6CE8\u5165\u4E86 config.less
+</style>
+

tailwindcss(2.5.0+)

\u9879\u76EE\u4E2D\u5F15\u7528\u5230\u4E86 tailwindcss,\u5177\u4F53\u53EF\u4EE5\u89C1\u6587\u4EF6\u4F7F\u7528\u8BF4\u660E\u3002

\u8BED\u6CD5\u5982\u4E0B:

<div class="relative w-full h-full px-4"></div>
+

windicss(2.5.0 \u5DF2\u5F03\u7528)

\u9879\u76EE\u4E2D\u4F7F\u7528\u4E86 windicss\uFF0C\u5177\u4F53\u53C2\u89C1\u6587\u4EF6\u4F7F\u7528\u8BF4\u660E\u3002

\u8BED\u6CD5\u5982\u4E0B:

<div class="relative w-full h-full px-4"></div>
+

\u6CE8\u610F\u4E8B\u9879

windcss \u76EE\u524D\u4F1A\u9020\u6210\u672C\u5730\u5F00\u53D1\u5185\u5B58\u6EA2\u51FA\uFF0C\u6240\u4EE5\u540E\u7EED\u53EF\u80FD\u4F1A\u8003\u8651\u5207\u6362\u5230 TailwindCss\uFF0C\u4E24\u8005\u57FA\u672C\u76F8\u540C\u3002

\u6240\u4EE5\u5C3D\u91CF\u5C11\u7528 Windicss \u65B0\u589E\u7684\u7279\u6027\uFF0C\u9632\u6B62\u540E\u7EED\u5207\u6362\u6210\u672C\u9AD8\u3002

\u4E3A\u4EC0\u4E48\u4F7F\u7528 Less

\u4E3B\u8981\u662F\u56E0\u4E3A Ant Design \u9ED8\u8BA4\u4F7F\u7528 less \u4F5C\u4E3A\u6837\u5F0F\u8BED\u8A00\uFF0C\u4F7F\u7528 Less \u53EF\u4EE5\u8DDF\u5176\u4FDD\u6301\u4E00\u81F4\u3002

\u5F00\u542F scoped

\u6CA1\u6709\u52A0 scoped \u5C5E\u6027\uFF0C\u9ED8\u8BA4\u4F1A\u7F16\u8BD1\u6210\u5168\u5C40\u6837\u5F0F\uFF0C\u53EF\u80FD\u4F1A\u9020\u6210\u5168\u5C40\u6C61\u67D3

<style></style>
+
+<style scoped></style>
+

\u6E29\u99A8\u63D0\u9192

\u4F7F\u7528 scoped \u540E\uFF0C\u7236\u7EC4\u4EF6\u7684\u6837\u5F0F\u5C06\u4E0D\u4F1A\u6E17\u900F\u5230\u5B50\u7EC4\u4EF6\u4E2D\u3002\u4E0D\u8FC7\u4E00\u4E2A\u5B50\u7EC4\u4EF6\u7684\u6839\u8282\u70B9\u4F1A\u540C\u65F6\u53D7\u5176\u7236\u7EC4\u4EF6\u7684 scoped CSS \u548C\u5B50\u7EC4\u4EF6\u7684 scoped CSS \u7684\u5F71\u54CD\u3002\u8FD9\u6837\u8BBE\u8BA1\u662F\u4E3A\u4E86\u8BA9\u7236\u7EC4\u4EF6\u53EF\u4EE5\u4ECE\u5E03\u5C40\u7684\u89D2\u5EA6\u51FA\u53D1\uFF0C\u8C03\u6574\u5176\u5B50\u7EC4\u4EF6\u6839\u5143\u7D20\u7684\u6837\u5F0F\u3002

\u6DF1\u5EA6\u9009\u62E9\u5668

\u6709\u65F6\u6211\u4EEC\u53EF\u80FD\u60F3\u660E\u786E\u5730\u5236\u5B9A\u4E00\u4E2A\u9488\u5BF9\u5B50\u7EC4\u4EF6\u7684\u89C4\u5219\u3002

\u5982\u679C\u4F60\u5E0C\u671B scoped \u6837\u5F0F\u4E2D\u7684\u4E00\u4E2A\u9009\u62E9\u5668\u80FD\u591F\u4F5C\u7528\u5F97\u201C\u66F4\u6DF1\u201D\uFF0C\u4F8B\u5982\u5F71\u54CD\u5B50\u7EC4\u4EF6\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 >>> \u64CD\u4F5C\u7B26\u3002\u6709\u4E9B\u50CF Sass \u4E4B\u7C7B\u7684\u9884\u5904\u7406\u5668\u65E0\u6CD5\u6B63\u786E\u89E3\u6790 >>>\u3002\u8FD9\u79CD\u60C5\u51B5\u4E0B\u4F60\u53EF\u4EE5\u4F7F\u7528 /deep/ \u6216 ::v-deep \u64CD\u4F5C\u7B26\u53D6\u800C\u4EE3\u4E4B\u2014\u2014\u4E24\u8005\u90FD\u662F >>> \u7684\u522B\u540D\uFF0C\u540C\u6837\u53EF\u4EE5\u6B63\u5E38\u5DE5\u4F5C\u3002

\u8BE6\u60C5\u53EF\u4EE5\u67E5\u770B RFC0023-scoped-styles-changes\u3002

\u4F7F\u7528 scoped \u540E\uFF0C\u7236\u7EC4\u4EF6\u7684\u6837\u5F0F\u5C06\u4E0D\u4F1A\u6E17\u900F\u5230\u5B50\u7EC4\u4EF6\u4E2D\uFF0C\u6240\u4EE5\u53EF\u4EE5\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u89E3\u51B3\uFF1A

<style scoped>
+  /* deep selectors */
+  ::v-deep(.foo) {
+  }
+  /* shorthand */
+  :deep(.foo) {
+  }
+
+  /* targeting slot content */
+  ::v-slotted(.foo) {
+  }
+  /* shorthand */
+  :slotted(.foo) {
+  }
+
+  /* one-off global rule */
+  ::v-global(.foo) {
+  }
+  /* shorthand */
+  :global(.foo) {
+  }
+</style>
+

CSS Modules

\u9488\u5BF9\u6837\u5F0F\u8986\u76D6\u95EE\u9898\uFF0C\u8FD8\u6709\u4E00\u79CD\u65B9\u6848\u662F\u4F7F\u7528 CSS Modules \u6A21\u5757\u5316\u65B9\u6848\u3002\u4F7F\u7528\u65B9\u5F0F\u5982\u4E0B\u3002

<template>
+  <span :class="$style.span1">hello</span>
+</template>
+
+<script>
+  import { useCSSModule } from 'vue';
+
+  export default {
+    setup(props, context) {
+      const $style = useCSSModule();
+      const moduleAStyle = useCSSModule('moduleA');
+      return {
+        $style,
+        moduleAStyle,
+      };
+    },
+  };
+</script>
+
+<style lang="less" module>
+  .span1 {
+    color: green;
+    font-size: 30px;
+  }
+</style>
+
+<style lang="less" module="moduleA">
+  .span1 {
+    color: green;
+    font-size: 30px;
+  }
+</style>
+

\u91CD\u590D\u5F15\u7528\u95EE\u9898

\u52A0\u4E0A reference \u53EF\u4EE5\u89E3\u51B3\u9875\u9762\u5185\u91CD\u590D\u5F15\u7528\u5BFC\u81F4\u5B9E\u9645\u751F\u6210\u7684 style \u6837\u5F0F\u8868\u91CD\u590D\u7684\u95EE\u9898\u3002

\u8FD9\u6B65\u5DF2\u7ECF\u5168\u5C40\u5F15\u5165\u4E86\u3002\u6240\u4EE5\u53EF\u4EE5\u4E0D\u5199\uFF0C\u76F4\u63A5\u4F7F\u7528\u53D8\u91CF

<style lang="less" scoped>
+  /* \u8BE5\u884C\u4EE3\u7801\u5DF2\u5168\u5C40\u5F15\u7528\u3002\u53EF\u4EE5\u4E0D\u7528\u5355\u72EC\u5F15\u5165 */
+  @import (reference) '../../design/config.less';
+<style>
+
`,36),o=[e];function c(l,u,i,k,r,d){return a(),n("div",null,o)}var m=s(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/guide_design.md.3cf5232f.lean.js b/assets/guide_design.md.3cf5232f.lean.js new file mode 100644 index 00000000..d0b22e89 --- /dev/null +++ b/assets/guide_design.md.3cf5232f.lean.js @@ -0,0 +1,77 @@ +import{_ as s,f as n,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u6837\u5F0F","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4ECB\u7ECD","slug":"\u4ECB\u7ECD"},{"level":2,"title":"tailwindcss(2.5.0+)","slug":"tailwindcss-2-5-0"},{"level":2,"title":"windicss(2.5.0 \u5DF2\u5F03\u7528)","slug":"windicss-2-5-0-\u5DF2\u5F03\u7528"},{"level":2,"title":"\u4E3A\u4EC0\u4E48\u4F7F\u7528 Less","slug":"\u4E3A\u4EC0\u4E48\u4F7F\u7528-less"},{"level":2,"title":"\u5F00\u542F scoped","slug":"\u5F00\u542F-scoped"},{"level":2,"title":"\u6DF1\u5EA6\u9009\u62E9\u5668","slug":"\u6DF1\u5EA6\u9009\u62E9\u5668"},{"level":2,"title":"CSS Modules","slug":"css-modules"},{"level":2,"title":"\u91CD\u590D\u5F15\u7528\u95EE\u9898","slug":"\u91CD\u590D\u5F15\u7528\u95EE\u9898"}],"relativePath":"guide/design.md","lastUpdated":1694442156385}',p={},e=t(`__VP_STATIC_START__

\u6837\u5F0F

\u4ECB\u7ECD

\u4E3B\u8981\u4ECB\u7ECD\u5982\u4F55\u5728\u9879\u76EE\u4E2D\u4F7F\u7528\u548C\u89C4\u5212\u6837\u5F0F\u6587\u4EF6\u3002

\u9ED8\u8BA4\u4F7F\u7528 less \u4F5C\u4E3A\u9884\u5904\u7406\u8BED\u8A00\uFF0C\u5EFA\u8BAE\u5728\u4F7F\u7528\u524D\u6216\u8005\u9047\u5230\u7591\u95EE\u65F6\u5B66\u4E60\u4E00\u4E0B Less \u7684\u76F8\u5173\u7279\u6027\uFF08\u5982\u679C\u60F3\u83B7\u53D6\u57FA\u7840\u7684 CSS \u77E5\u8BC6\u6216\u67E5\u9605\u5C5E\u6027\uFF0C\u8BF7\u53C2\u8003 MDN \u6587\u6863\uFF09\u3002

\u9879\u76EE\u4E2D\u4F7F\u7528\u7684\u901A\u7528\u6837\u5F0F\uFF0C\u90FD\u5B58\u653E\u4E8E src/design/ \u4E0B\u9762\u3002

.
+\u251C\u2500\u2500 ant # ant design \u4E00\u4E9B\u6837\u5F0F\u8986\u76D6
+\u251C\u2500\u2500 color.less # \u989C\u8272
+\u251C\u2500\u2500 index.less # \u5165\u53E3
+\u251C\u2500\u2500 public.less # \u516C\u5171\u7C7B
+\u251C\u2500\u2500 theme.less # \u4E3B\u9898\u76F8\u5173
+\u251C\u2500\u2500 config.less  # \u6BCF\u4E2A\u7EC4\u4EF6\u90FD\u4F1A\u81EA\u52A8\u5F15\u5165\u6837\u5F0F
+\u251C\u2500\u2500 transition # \u52A8\u753B\u76F8\u5173
+\u2514\u2500\u2500 var # \u53D8\u91CF
+
+

\u5168\u5C40\u6CE8\u5165

config.less \u8FD9\u4E2A\u6587\u4EF6\u4F1A\u88AB\u5168\u5C40\u6CE8\u5165\u5230\u6240\u6709\u6587\u4EF6\uFF0C\u6240\u4EE5\u5728\u9875\u9762\u5185\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u53D8\u91CF\u800C\u4E0D\u9700\u8981\u624B\u52A8\u5F15\u5165

<style lang="less" scoped>
+  // \u8FD9\u91CC\u5DF2\u7ECF\u9690\u5F0F\u6CE8\u5165\u4E86 config.less
+</style>
+

tailwindcss(2.5.0+)

\u9879\u76EE\u4E2D\u5F15\u7528\u5230\u4E86 tailwindcss,\u5177\u4F53\u53EF\u4EE5\u89C1\u6587\u4EF6\u4F7F\u7528\u8BF4\u660E\u3002

\u8BED\u6CD5\u5982\u4E0B:

<div class="relative w-full h-full px-4"></div>
+

windicss(2.5.0 \u5DF2\u5F03\u7528)

\u9879\u76EE\u4E2D\u4F7F\u7528\u4E86 windicss\uFF0C\u5177\u4F53\u53C2\u89C1\u6587\u4EF6\u4F7F\u7528\u8BF4\u660E\u3002

\u8BED\u6CD5\u5982\u4E0B:

<div class="relative w-full h-full px-4"></div>
+

\u6CE8\u610F\u4E8B\u9879

windcss \u76EE\u524D\u4F1A\u9020\u6210\u672C\u5730\u5F00\u53D1\u5185\u5B58\u6EA2\u51FA\uFF0C\u6240\u4EE5\u540E\u7EED\u53EF\u80FD\u4F1A\u8003\u8651\u5207\u6362\u5230 TailwindCss\uFF0C\u4E24\u8005\u57FA\u672C\u76F8\u540C\u3002

\u6240\u4EE5\u5C3D\u91CF\u5C11\u7528 Windicss \u65B0\u589E\u7684\u7279\u6027\uFF0C\u9632\u6B62\u540E\u7EED\u5207\u6362\u6210\u672C\u9AD8\u3002

\u4E3A\u4EC0\u4E48\u4F7F\u7528 Less

\u4E3B\u8981\u662F\u56E0\u4E3A Ant Design \u9ED8\u8BA4\u4F7F\u7528 less \u4F5C\u4E3A\u6837\u5F0F\u8BED\u8A00\uFF0C\u4F7F\u7528 Less \u53EF\u4EE5\u8DDF\u5176\u4FDD\u6301\u4E00\u81F4\u3002

\u5F00\u542F scoped

\u6CA1\u6709\u52A0 scoped \u5C5E\u6027\uFF0C\u9ED8\u8BA4\u4F1A\u7F16\u8BD1\u6210\u5168\u5C40\u6837\u5F0F\uFF0C\u53EF\u80FD\u4F1A\u9020\u6210\u5168\u5C40\u6C61\u67D3

<style></style>
+
+<style scoped></style>
+

\u6E29\u99A8\u63D0\u9192

\u4F7F\u7528 scoped \u540E\uFF0C\u7236\u7EC4\u4EF6\u7684\u6837\u5F0F\u5C06\u4E0D\u4F1A\u6E17\u900F\u5230\u5B50\u7EC4\u4EF6\u4E2D\u3002\u4E0D\u8FC7\u4E00\u4E2A\u5B50\u7EC4\u4EF6\u7684\u6839\u8282\u70B9\u4F1A\u540C\u65F6\u53D7\u5176\u7236\u7EC4\u4EF6\u7684 scoped CSS \u548C\u5B50\u7EC4\u4EF6\u7684 scoped CSS \u7684\u5F71\u54CD\u3002\u8FD9\u6837\u8BBE\u8BA1\u662F\u4E3A\u4E86\u8BA9\u7236\u7EC4\u4EF6\u53EF\u4EE5\u4ECE\u5E03\u5C40\u7684\u89D2\u5EA6\u51FA\u53D1\uFF0C\u8C03\u6574\u5176\u5B50\u7EC4\u4EF6\u6839\u5143\u7D20\u7684\u6837\u5F0F\u3002

\u6DF1\u5EA6\u9009\u62E9\u5668

\u6709\u65F6\u6211\u4EEC\u53EF\u80FD\u60F3\u660E\u786E\u5730\u5236\u5B9A\u4E00\u4E2A\u9488\u5BF9\u5B50\u7EC4\u4EF6\u7684\u89C4\u5219\u3002

\u5982\u679C\u4F60\u5E0C\u671B scoped \u6837\u5F0F\u4E2D\u7684\u4E00\u4E2A\u9009\u62E9\u5668\u80FD\u591F\u4F5C\u7528\u5F97\u201C\u66F4\u6DF1\u201D\uFF0C\u4F8B\u5982\u5F71\u54CD\u5B50\u7EC4\u4EF6\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 >>> \u64CD\u4F5C\u7B26\u3002\u6709\u4E9B\u50CF Sass \u4E4B\u7C7B\u7684\u9884\u5904\u7406\u5668\u65E0\u6CD5\u6B63\u786E\u89E3\u6790 >>>\u3002\u8FD9\u79CD\u60C5\u51B5\u4E0B\u4F60\u53EF\u4EE5\u4F7F\u7528 /deep/ \u6216 ::v-deep \u64CD\u4F5C\u7B26\u53D6\u800C\u4EE3\u4E4B\u2014\u2014\u4E24\u8005\u90FD\u662F >>> \u7684\u522B\u540D\uFF0C\u540C\u6837\u53EF\u4EE5\u6B63\u5E38\u5DE5\u4F5C\u3002

\u8BE6\u60C5\u53EF\u4EE5\u67E5\u770B RFC0023-scoped-styles-changes\u3002

\u4F7F\u7528 scoped \u540E\uFF0C\u7236\u7EC4\u4EF6\u7684\u6837\u5F0F\u5C06\u4E0D\u4F1A\u6E17\u900F\u5230\u5B50\u7EC4\u4EF6\u4E2D\uFF0C\u6240\u4EE5\u53EF\u4EE5\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u89E3\u51B3\uFF1A

<style scoped>
+  /* deep selectors */
+  ::v-deep(.foo) {
+  }
+  /* shorthand */
+  :deep(.foo) {
+  }
+
+  /* targeting slot content */
+  ::v-slotted(.foo) {
+  }
+  /* shorthand */
+  :slotted(.foo) {
+  }
+
+  /* one-off global rule */
+  ::v-global(.foo) {
+  }
+  /* shorthand */
+  :global(.foo) {
+  }
+</style>
+

CSS Modules

\u9488\u5BF9\u6837\u5F0F\u8986\u76D6\u95EE\u9898\uFF0C\u8FD8\u6709\u4E00\u79CD\u65B9\u6848\u662F\u4F7F\u7528 CSS Modules \u6A21\u5757\u5316\u65B9\u6848\u3002\u4F7F\u7528\u65B9\u5F0F\u5982\u4E0B\u3002

<template>
+  <span :class="$style.span1">hello</span>
+</template>
+
+<script>
+  import { useCSSModule } from 'vue';
+
+  export default {
+    setup(props, context) {
+      const $style = useCSSModule();
+      const moduleAStyle = useCSSModule('moduleA');
+      return {
+        $style,
+        moduleAStyle,
+      };
+    },
+  };
+</script>
+
+<style lang="less" module>
+  .span1 {
+    color: green;
+    font-size: 30px;
+  }
+</style>
+
+<style lang="less" module="moduleA">
+  .span1 {
+    color: green;
+    font-size: 30px;
+  }
+</style>
+

\u91CD\u590D\u5F15\u7528\u95EE\u9898

\u52A0\u4E0A reference \u53EF\u4EE5\u89E3\u51B3\u9875\u9762\u5185\u91CD\u590D\u5F15\u7528\u5BFC\u81F4\u5B9E\u9645\u751F\u6210\u7684 style \u6837\u5F0F\u8868\u91CD\u590D\u7684\u95EE\u9898\u3002

\u8FD9\u6B65\u5DF2\u7ECF\u5168\u5C40\u5F15\u5165\u4E86\u3002\u6240\u4EE5\u53EF\u4EE5\u4E0D\u5199\uFF0C\u76F4\u63A5\u4F7F\u7528\u53D8\u91CF

<style lang="less" scoped>
+  /* \u8BE5\u884C\u4EE3\u7801\u5DF2\u5168\u5C40\u5F15\u7528\u3002\u53EF\u4EE5\u4E0D\u7528\u5355\u72EC\u5F15\u5165 */
+  @import (reference) '../../design/config.less';
+<style>
+
__VP_STATIC_END__`,36),o=[e];function c(l,u,i,k,r,d){return a(),n("div",null,o)}var m=s(p,[["render",c]]);export{h as __pageData,m as default}; diff --git a/assets/guide_electron.md.ef66133a.js b/assets/guide_electron.md.ef66133a.js new file mode 100644 index 00000000..fe21cb21 --- /dev/null +++ b/assets/guide_electron.md.ef66133a.js @@ -0,0 +1,7 @@ +import{_ as e,f as a,e as n,N as t}from"./plugin-vue_export-helper.147b70e9.js";const v='{"title":"Electron","description":"","frontmatter":{},"headers":[{"level":2,"title":"URL \u6A21\u5F0F","slug":"url-\u6A21\u5F0F"},{"level":3,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":3,"title":"\u4ECE GitHub \u83B7\u53D6\u4EE3\u7801","slug":"\u4ECE-github-\u83B7\u53D6\u4EE3\u7801"},{"level":3,"title":"\u5B89\u88C5\u4F9D\u8D56","slug":"\u5B89\u88C5\u4F9D\u8D56"},{"level":3,"title":"\u8FD0\u884C","slug":"\u8FD0\u884C"},{"level":3,"title":"\u6253\u5305","slug":"\u6253\u5305"},{"level":2,"title":"\u6807\u51C6\u6A21\u5F0F","slug":"\u6807\u51C6\u6A21\u5F0F"}],"relativePath":"guide/electron.md","lastUpdated":1694442156385}',r={},s=t(`

Electron

URL \u6A21\u5F0F

\u8FD9\u79CD\u6A21\u5F0F\u4F1A\u5148\u542F\u52A8 vite \u670D\u52A1\uFF0CElectron \u4F7F\u7528 Url \u5730\u5740\u6765\u8FDB\u884C\u6E32\u67D3

\u4F7F\u7528

\u4ECE GitHub \u83B7\u53D6\u4EE3\u7801

Electron \u4EE3\u7801\u5728 electron-main \u5206\u652F

# clone electron-main\u5206\u652F\u4EE3\u7801
+git clone -b electron-main https://github.com/vbenjs/vue-vben-admin vben-admin-electron
+

\u5B89\u88C5\u4F9D\u8D56

yarn
+

\u63D0\u793A

\u9996\u6B21\u4E0B\u8F7D Electron \u4F9D\u8D56\u4F1A\u6BD4\u8F83\u6162\uFF0C\u53EF\u4EE5\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u65B0\u5EFA.npmrc\u6587\u4EF6\uFF0C\u586B\u5165\u4E0B\u65B9\u5185\u5BB9\u5373\u53EF

ELETRON_MIRROR=https://npm.taobao.org/mirrors/electron/
+

\u8FD0\u884C

yarn dev:app
+

\u6253\u5305

yarn build:app
+

\u6807\u51C6\u6A21\u5F0F

TODO: \u5F85\u9002\u914D

`,16),l=[s];function c(o,i,d,h,p,u){return n(),a("div",null,l)}var _=e(r,[["render",c]]);export{v as __pageData,_ as default}; diff --git a/assets/guide_electron.md.ef66133a.lean.js b/assets/guide_electron.md.ef66133a.lean.js new file mode 100644 index 00000000..980b0cee --- /dev/null +++ b/assets/guide_electron.md.ef66133a.lean.js @@ -0,0 +1,7 @@ +import{_ as e,f as a,e as n,N as t}from"./plugin-vue_export-helper.147b70e9.js";const v='{"title":"Electron","description":"","frontmatter":{},"headers":[{"level":2,"title":"URL \u6A21\u5F0F","slug":"url-\u6A21\u5F0F"},{"level":3,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":3,"title":"\u4ECE GitHub \u83B7\u53D6\u4EE3\u7801","slug":"\u4ECE-github-\u83B7\u53D6\u4EE3\u7801"},{"level":3,"title":"\u5B89\u88C5\u4F9D\u8D56","slug":"\u5B89\u88C5\u4F9D\u8D56"},{"level":3,"title":"\u8FD0\u884C","slug":"\u8FD0\u884C"},{"level":3,"title":"\u6253\u5305","slug":"\u6253\u5305"},{"level":2,"title":"\u6807\u51C6\u6A21\u5F0F","slug":"\u6807\u51C6\u6A21\u5F0F"}],"relativePath":"guide/electron.md","lastUpdated":1694442156385}',r={},s=t(`__VP_STATIC_START__

Electron

URL \u6A21\u5F0F

\u8FD9\u79CD\u6A21\u5F0F\u4F1A\u5148\u542F\u52A8 vite \u670D\u52A1\uFF0CElectron \u4F7F\u7528 Url \u5730\u5740\u6765\u8FDB\u884C\u6E32\u67D3

\u4F7F\u7528

\u4ECE GitHub \u83B7\u53D6\u4EE3\u7801

Electron \u4EE3\u7801\u5728 electron-main \u5206\u652F

# clone electron-main\u5206\u652F\u4EE3\u7801
+git clone -b electron-main https://github.com/vbenjs/vue-vben-admin vben-admin-electron
+

\u5B89\u88C5\u4F9D\u8D56

yarn
+

\u63D0\u793A

\u9996\u6B21\u4E0B\u8F7D Electron \u4F9D\u8D56\u4F1A\u6BD4\u8F83\u6162\uFF0C\u53EF\u4EE5\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u65B0\u5EFA.npmrc\u6587\u4EF6\uFF0C\u586B\u5165\u4E0B\u65B9\u5185\u5BB9\u5373\u53EF

ELETRON_MIRROR=https://npm.taobao.org/mirrors/electron/
+

\u8FD0\u884C

yarn dev:app
+

\u6253\u5305

yarn build:app
+

\u6807\u51C6\u6A21\u5F0F

TODO: \u5F85\u9002\u914D

__VP_STATIC_END__`,16),l=[s];function c(o,i,d,h,p,u){return n(),a("div",null,l)}var _=e(r,[["render",c]]);export{v as __pageData,_ as default}; diff --git a/assets/guide_index.md.25bdf89c.js b/assets/guide_index.md.25bdf89c.js new file mode 100644 index 00000000..c11a33fe --- /dev/null +++ b/assets/guide_index.md.25bdf89c.js @@ -0,0 +1,116 @@ +import{_ as n,f as s,e as a,N as e}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u5F00\u59CB","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u524D\u8A00","slug":"\u524D\u8A00"},{"level":2,"title":"\u73AF\u5883\u51C6\u5907","slug":"\u73AF\u5883\u51C6\u5907"},{"level":2,"title":"\u5DE5\u5177\u914D\u7F6E","slug":"\u5DE5\u5177\u914D\u7F6E"},{"level":2,"title":"\u4EE3\u7801\u83B7\u53D6","slug":"\u4EE3\u7801\u83B7\u53D6"},{"level":3,"title":"\u4ECE GitHub \u83B7\u53D6\u4EE3\u7801","slug":"\u4ECE-github-\u83B7\u53D6\u4EE3\u7801"},{"level":3,"title":"\u4ECE Gitee \u83B7\u53D6\u4EE3\u7801","slug":"\u4ECE-gitee-\u83B7\u53D6\u4EE3\u7801"},{"level":2,"title":"\u5B89\u88C5","slug":"\u5B89\u88C5"},{"level":3,"title":"\u5B89\u88C5 Node.js","slug":"\u5B89\u88C5-node-js"},{"level":3,"title":"\u5B89\u88C5\u4F9D\u8D56","slug":"\u5B89\u88C5\u4F9D\u8D56"},{"level":3,"title":"imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\u89E3\u51B3\u65B9\u6CD5","slug":"imagemin-\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\u89E3\u51B3\u65B9\u6CD5"},{"level":2,"title":"npm script","slug":"npm-script"},{"level":3,"title":"\u751F\u6210\u56FE\u6807\u96C6","slug":"\u751F\u6210\u56FE\u6807\u96C6"},{"level":3,"title":"\u91CD\u65B0\u5B89\u88C5\u4F9D\u8D56","slug":"\u91CD\u65B0\u5B89\u88C5\u4F9D\u8D56"},{"level":2,"title":"\u76EE\u5F55\u8BF4\u660E","slug":"\u76EE\u5F55\u8BF4\u660E"}],"relativePath":"guide/index.md","lastUpdated":1694442156385}',t={},o=e(`

\u5F00\u59CB

\u672C\u6587\u4F1A\u5E2E\u52A9\u4F60\u4ECE\u5934\u542F\u52A8\u9879\u76EE

\u524D\u8A00

\u5173\u4E8E\u7EC4\u4EF6

\u9879\u76EE\u867D\u7136\u4E8C\u6B21\u5C01\u88C5\u4E86\u4E00\u4E9B\u7EC4\u4EF6\uFF0C\u4F46\u662F\u53EF\u80FD\u4E0D\u80FD\u6EE1\u8DB3\u5927\u90E8\u5206\u7684\u8981\u6C42\u3002\u6240\u4EE5\uFF0C\u5982\u679C\u7EC4\u4EF6\u4E0D\u6EE1\u8DB3\u4F60\u7684\u8981\u6C42\uFF0C\u5B8C\u5168\u53EF\u4EE5\u4E0D\u7528\u751A\u81F3\u5220\u9664\u4EE3\u7801\u81EA\u5DF1\u5199\uFF0C\u4E0D\u5FC5\u575A\u6301\u4F7F\u7528\u9879\u76EE\u81EA\u5E26\u7684\u7EC4\u4EF6\u3002

\u73AF\u5883\u51C6\u5907

\u672C\u5730\u73AF\u5883\u9700\u8981\u5B89\u88C5 pnpm\u3001Node.js \u548C Git

\u6CE8\u610F

  • \u63A8\u8350\u4F7F\u7528pnpm\uFF0C\u5426\u5219\u4F9D\u8D56\u53EF\u80FD\u5B89\u88C5\u4E0D\u4E0A\u3002
  • Node.js \u7248\u672C\u8981\u6C4212.x\u4EE5\u4E0A\uFF0C\u4E14\u4E0D\u80FD\u4E3A13.x\u7248\u672C\uFF0C\u8FD9\u91CC\u63A8\u8350 14.x \u53CA\u4EE5\u4E0A\u3002

\u5DE5\u5177\u914D\u7F6E

\u5982\u679C\u60A8\u4F7F\u7528\u7684 IDE \u662Fvscode(\u63A8\u8350)\u7684\u8BDD\uFF0C\u53EF\u4EE5\u5B89\u88C5\u4EE5\u4E0B\u5DE5\u5177\u6765\u63D0\u9AD8\u5F00\u53D1\u6548\u7387\u53CA\u4EE3\u7801\u683C\u5F0F\u5316

\u4EE3\u7801\u83B7\u53D6

\u6CE8\u610F

\u6CE8\u610F\u5B58\u653E\u4EE3\u7801\u7684\u76EE\u5F55\u53CA\u6240\u6709\u7236\u7EA7\u76EE\u5F55\u4E0D\u80FD\u5B58\u5728\u4E2D\u6587\u3001\u97E9\u6587\u3001\u65E5\u6587\u4EE5\u53CA\u7A7A\u683C\uFF0C\u5426\u5219\u5B89\u88C5\u4F9D\u8D56\u540E\u542F\u52A8\u4F1A\u51FA\u9519\u3002

\u4ECE GitHub \u83B7\u53D6\u4EE3\u7801

# clone \u4EE3\u7801
+git clone https://github.com/vbenjs/vue-vben-admin.git
+
+

\u4ECE Gitee \u83B7\u53D6\u4EE3\u7801

\u5982\u679C\u4ECE github clone \u4EE3\u7801\u8F83\u6162\u7684\u8BDD\uFF0C\u53EF\u4EE5\u5C1D\u8BD5\u7528 Gitee \u540C\u6B65\u4EE3\u7801\u5230\u81EA\u5DF1\u7684\u4ED3\u5E93\uFF0C\u518D clone \u4E0B\u6765\u5373\u53EF\u3002

\u4E5F\u53EF\u4EE5\u901A\u8FC7\u4E0B\u65B9\u5730\u5740\u8FDB\u884C clone

git clone https://gitee.com/annsion/vue-vben-admin.git
+

\u6CE8\u610F

Gitee\u7684\u4EE3\u7801\u53EF\u80FD\u4E0D\u662F\u6700\u65B0\u7684

\u5B89\u88C5

\u5B89\u88C5 Node.js

\u5982\u679C\u60A8\u7535\u8111\u672A\u5B89\u88C5Node.js\uFF0C\u8BF7\u5B89\u88C5\u5B83\u3002

\u9A8C\u8BC1

# \u51FA\u73B0\u76F8\u5E94npm\u7248\u672C\u5373\u53EF
+npm -v
+# \u51FA\u73B0\u76F8\u5E94node\u7248\u672C\u5373\u53EF
+node -v
+
+

\u5982\u679C\u4F60\u9700\u8981\u540C\u65F6\u5B58\u5728\u591A\u4E2A node \u7248\u672C\uFF0C\u53EF\u4EE5\u4F7F\u7528 Nvm \u6216\u8005\u5176\u4ED6\u5DE5\u5177\u8FDB\u884C Node.js \u8FDB\u884C\u7248\u672C\u7BA1\u7406\u3002

\u5B89\u88C5\u4F9D\u8D56

pnpm \u5B89\u88C5

\u5FC5\u987B\u4F7F\u7528 pnpm\u8FDB\u884C\u4F9D\u8D56\u5B89\u88C5\uFF08\u82E5\u5176\u4ED6\u5305\u7BA1\u7406\u5668\u5B89\u88C5\u4E0D\u4E86\u9700\u8981\u81EA\u884C\u5904\u7406\uFF09\u3002

\u5982\u679C\u672A\u5B89\u88C5pnpm\uFF0C\u53EF\u4EE5\u7528\u4E0B\u9762\u547D\u4EE4\u6765\u8FDB\u884C\u5168\u5C40\u5B89\u88C5

# \u5168\u5C40\u5B89\u88C5pnpm
+npm install -g pnpm
+# \u9A8C\u8BC1
+pnpm -v # \u51FA\u73B0\u5BF9\u5E94\u7248\u672C\u53F7\u5373\u4EE3\u8868\u5B89\u88C5\u6210\u529F
+

\u4F9D\u8D56\u5B89\u88C5\u547D\u4EE4

\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\uFF0C\u6253\u5F00\u547D\u4EE4\u7A97\u53E3\u6267\u884C\uFF0C\u8010\u5FC3\u7B49\u5F85\u5B89\u88C5\u5B8C\u6210\u5373\u53EF

# \u5B89\u88C5\u4F9D\u8D56
+pnpm i
+

imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\u89E3\u51B3\u65B9\u6CD5

\u7531\u4E8E imagemin \u5728\u56FD\u5185\u5B89\u88C5\u56F0\u96BE\uFF0C\u63D0\u4F9B\u4EE5\u4E0B\u51E0\u4E2A\u89E3\u51B3\u65B9\u6848\uFF1A

  1. \u4F7F\u7528 yarn \u5728 package.json \u5185\u914D\u7F6E(\u63A8\u8350\uFF0C\u9879\u76EE\u5185\u5DF2\u96C6\u6210\uFF0C\u524D\u63D0\u662F\u5FC5\u987B\u4F7F\u7528 yarn)
"resolutions": {
+  "bin-wrapper": "npm:bin-wrapper-china"
+}
+
  1. \u4F7F\u7528 npm\uFF0C\u5728\u7535\u8111 host \u6587\u4EF6\u52A0\u4E0A\u5982\u4E0B\u914D\u7F6E\u5373\u53EF
199.232.4.133 raw.githubusercontent.com
+

\u5B89\u88C5\u4F9D\u8D56\u65F6 husky \u5B89\u88C5\u5931\u8D25

\u8BF7\u67E5\u770B\u4F60\u7684\u6E90\u7801\u662F\u5426\u4ECE github \u76F4\u63A5\u4E0B\u8F7D\u7684\uFF0C\u76F4\u63A5\u4E0B\u8F7D\u662F\u6CA1\u6709 .git \u6587\u4EF6\u5939\u7684\uFF0C\u800C husky \u9700\u8981\u4F9D\u8D56 git \u624D\u80FD\u5B89\u88C5\u3002\u6B64\u65F6\u9700\u4F7F\u7528 git init \u521D\u59CB\u5316\u9879\u76EE\uFF0C\u518D\u5C1D\u8BD5\u91CD\u65B0\u5B89\u88C5\u5373\u53EF\u3002

npm script

"scripts": {
+  # \u5B89\u88C5\u4F9D\u8D56
+  "bootstrap": "yarn install",
+  # \u8FD0\u884C\u9879\u76EE
+  "serve": "npm run dev",
+  # \u8FD0\u884C\u9879\u76EE
+  "dev": "vite",
+  # \u6784\u5EFA\u9879\u76EE
+  "build": "vite build && esno ./build/script/postBuild.ts",
+  # \u6E05\u7A7A\u7F13\u5B58\u540E\u6784\u5EFA\u9879\u76EE
+  "build:no-cache": "yarn clean:cache && npm run build",
+  # \u751F\u6210\u6253\u5305\u5206\u6790\uFF0C\u5728 \`Mac OS\` \u7535\u8111\u4E0A\u6267\u884C\u5B8C\u6210\u540E\u4F1A\u81EA\u52A8\u6253\u5F00\u754C\u9762\uFF0C\u5728 \`Window\` \u7535\u8111\u4E0A\u6267\u884C\u5B8C\u6210\u540E\u9700\u8981\u6253\u5F00 \`./build/.cache/stats.html\` \u67E5\u770B
+  "report": "cross-env REPORT=true npm run build",
+  # \u7C7B\u578B\u68C0\u67E5
+  "type:check": "vue-tsc --noEmit --skipLibCheck",
+  # \u9884\u89C8\u6253\u5305\u540E\u7684\u5185\u5BB9\uFF08\u5148\u6253\u5305\u5728\u8FDB\u884C\u9884\u89C8\uFF09
+  "preview": "npm run build && vite preview",
+  # \u76F4\u63A5\u9884\u89C8\u672C\u5730 dist \u6587\u4EF6\u76EE\u5F55
+  "preview:dist": "vite preview",
+  # \u751F\u6210 ChangeLog
+  "log": "conventional-changelog -p angular -i CHANGELOG.md -s",
+  # \u5220\u9664\u7F13\u5B58
+  "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
+  # \u5220\u9664 node_modules (\`window\` \u7CFB\u7EDF\u624B\u52A8\u5220\u9664\u8BE5\u76EE\u5F55\u8F83\u6162\uFF0C\u53EF\u4EE5\u4F7F\u7528\u8BE5\u547D\u4EE4\u6765\u8FDB\u884C\u5220\u9664)
+  "clean:lib": "rimraf node_modules",
+  # \u6267\u884C eslint \u6821\u9A8C\uFF0C\u5E76\u4FEE\u590D\u90E8\u5206\u95EE\u9898
+  "lint:eslint": "eslint \\"{src,mock}/**/*.{vue,ts,tsx}\\" --fix",
+  # \u6267\u884C prettier \u683C\u5F0F\u5316\uFF08\u8BE5\u547D\u4EE4\u4F1A\u5BF9\u9879\u76EE\u6240\u6709\u4EE3\u7801\u8FDB\u884C prettier \u683C\u5F0F\u5316\uFF0C\u8BF7\u8C28\u614E\u6267\u884C\uFF09
+  "lint:prettier": "prettier --write --loglevel warn \\"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\\"",
+  # \u6267\u884C stylelint \u683C\u5F0F\u5316
+  "lint:stylelint": "stylelint --fix \\"**/*.{vue,less,postcss,css,scss}\\" --cache --cache-location node_modules/.cache/stylelint/",
+  "lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
+  "lint:pretty": "pretty-quick --staged",
+  # \u5BF9\u6253\u5305\u7ED3\u679C\u8FDB\u884C gzip \u6D4B\u8BD5
+  "test:gzip": "http-server dist --cors --gzip -c-1",
+  # \u5BF9\u6253\u5305\u76EE\u5F55\u8FDB\u884C brotli \u6D4B\u8BD5
+  "test:br": "http-server dist --cors --brotli -c-1",
+  # \u91CD\u65B0\u5B89\u88C5\u4F9D\u8D56\uFF0C\u89C1\u4E0B\u65B9\u8BF4\u660E
+  "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
+  "install:husky": "is-ci || husky install",
+  # \u751F\u6210\u56FE\u6807\u96C6\uFF0C\u89C1\u4E0B\u65B9\u8BF4\u660E
+  "gen:icon": "esno ./build/generate/icon/index.ts",
+  "postinstall": "npm run install:husky"
+},
+

\u751F\u6210\u56FE\u6807\u96C6

\u8BE5\u547D\u4EE4\u4F1A\u751F\u6210\u6240\u9009\u62E9\u7684\u56FE\u6807\u96C6\uFF0C\u63D0\u4F9B\u7ED9\u56FE\u6807\u9009\u62E9\u5668\u4F7F\u7528\u3002\u5177\u4F53\u4F7F\u7528\u65B9\u5F0F\u8BF7\u67E5\u770B \u56FE\u6807\u96C6\u751F\u6210

\u91CD\u65B0\u5B89\u88C5\u4F9D\u8D56

\u8BE5\u547D\u4EE4\u4F1A\u5148\u5220\u9664 node_modules\u3001yarn.lock\u3001package.lock.json \u540E\u518D\u8FDB\u884C\u4F9D\u8D56\u91CD\u65B0\u5B89\u88C5\uFF08\u5B89\u88C5\u901F\u5EA6\u4F1A\u660E\u663E\u53D8\u6162\uFF09\u3002

\u63A5\u4E0B\u6765\u4F60\u53EF\u4EE5\u4FEE\u6539\u4EE3\u7801\u8FDB\u884C\u4E1A\u52A1\u5F00\u53D1\u4E86\u3002\u6211\u4EEC\u5185\u5EFA\u4E86\u6A21\u62DF\u6570\u636E\u3001HMR \u5B9E\u65F6\u9884\u89C8\u3001\u72B6\u6001\u7BA1\u7406\u3001\u56FD\u9645\u5316\u3001\u5168\u5C40\u8DEF\u7531\u7B49\u5404\u79CD\u5B9E\u7528\u7684\u529F\u80FD\u8F85\u52A9\u5F00\u53D1\uFF0C\u8BF7\u9605\u8BFB\u5176\u4ED6\u7AE0\u8282\u4E86\u89E3\u66F4\u591A\u3002

\u76EE\u5F55\u8BF4\u660E


+.
+\u251C\u2500\u2500 build # \u6253\u5305\u811A\u672C\u76F8\u5173
+\u2502   \u251C\u2500\u2500 config # \u914D\u7F6E\u6587\u4EF6
+\u2502   \u251C\u2500\u2500 generate # \u751F\u6210\u5668
+\u2502   \u251C\u2500\u2500 script # \u811A\u672C
+\u2502   \u2514\u2500\u2500 vite # vite\u914D\u7F6E
+\u251C\u2500\u2500 mock # mock\u6587\u4EF6\u5939
+\u251C\u2500\u2500 public # \u516C\u5171\u9759\u6001\u8D44\u6E90\u76EE\u5F55
+\u251C\u2500\u2500 src # \u4E3B\u76EE\u5F55
+\u2502   \u251C\u2500\u2500 api # \u63A5\u53E3\u6587\u4EF6
+\u2502   \u251C\u2500\u2500 assets # \u8D44\u6E90\u6587\u4EF6
+\u2502   \u2502   \u251C\u2500\u2500 icons # icon sprite \u56FE\u6807\u6587\u4EF6\u5939
+\u2502   \u2502   \u251C\u2500\u2500 images # \u9879\u76EE\u5B58\u653E\u56FE\u7247\u7684\u6587\u4EF6\u5939
+\u2502   \u2502   \u2514\u2500\u2500 svg # \u9879\u76EE\u5B58\u653Esvg\u56FE\u7247\u7684\u6587\u4EF6\u5939
+\u2502   \u251C\u2500\u2500 components # \u516C\u5171\u7EC4\u4EF6
+\u2502   \u251C\u2500\u2500 design # \u6837\u5F0F\u6587\u4EF6
+\u2502   \u251C\u2500\u2500 directives # \u6307\u4EE4
+\u2502   \u251C\u2500\u2500 enums # \u679A\u4E3E/\u5E38\u91CF
+\u2502   \u251C\u2500\u2500 hooks # hook
+\u2502   \u2502   \u251C\u2500\u2500 component # \u7EC4\u4EF6\u76F8\u5173hook
+\u2502   \u2502   \u251C\u2500\u2500 core # \u57FA\u7840hook
+\u2502   \u2502   \u251C\u2500\u2500 event # \u4E8B\u4EF6\u76F8\u5173hook
+\u2502   \u2502   \u251C\u2500\u2500 setting # \u914D\u7F6E\u76F8\u5173hook
+\u2502   \u2502   \u2514\u2500\u2500 web # web\u76F8\u5173hook
+\u2502   \u251C\u2500\u2500 layouts # \u5E03\u5C40\u6587\u4EF6
+\u2502   \u2502   \u251C\u2500\u2500 default # \u9ED8\u8BA4\u5E03\u5C40
+\u2502   \u2502   \u251C\u2500\u2500 iframe # iframe\u5E03\u5C40
+\u2502   \u2502   \u2514\u2500\u2500 page # \u9875\u9762\u5E03\u5C40
+\u2502   \u251C\u2500\u2500 locales # \u591A\u8BED\u8A00
+\u2502   \u251C\u2500\u2500 logics # \u903B\u8F91
+\u2502   \u251C\u2500\u2500 main.ts # \u4E3B\u5165\u53E3
+\u2502   \u251C\u2500\u2500 router # \u8DEF\u7531\u914D\u7F6E
+\u2502   \u251C\u2500\u2500 settings # \u9879\u76EE\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 componentSetting.ts # \u7EC4\u4EF6\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 designSetting.ts # \u6837\u5F0F\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 encryptionSetting.ts # \u52A0\u5BC6\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 localeSetting.ts # \u591A\u8BED\u8A00\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 projectSetting.ts # \u9879\u76EE\u914D\u7F6E
+\u2502   \u2502   \u2514\u2500\u2500 siteSetting.ts # \u7AD9\u70B9\u914D\u7F6E
+\u2502   \u251C\u2500\u2500 store # \u6570\u636E\u4ED3\u5E93
+\u2502   \u251C\u2500\u2500 utils # \u5DE5\u5177\u7C7B
+\u2502   \u2514\u2500\u2500 views # \u9875\u9762
+\u251C\u2500\u2500 test # \u6D4B\u8BD5
+\u2502   \u2514\u2500\u2500 server # \u6D4B\u8BD5\u7528\u5230\u7684\u670D\u52A1
+\u2502       \u251C\u2500\u2500 api # \u6D4B\u8BD5\u670D\u52A1\u5668
+\u2502       \u251C\u2500\u2500 upload # \u6D4B\u8BD5\u4E0A\u4F20\u670D\u52A1\u5668
+\u2502       \u2514\u2500\u2500 websocket # \u6D4B\u8BD5ws\u670D\u52A1\u5668
+\u251C\u2500\u2500 types # \u7C7B\u578B\u6587\u4EF6
+\u251C\u2500\u2500 vite.config.ts # vite\u914D\u7F6E\u6587\u4EF6
+\u2514\u2500\u2500 windi.config.ts # windcss\u914D\u7F6E\u6587\u4EF6
+
+
`,49),p=[o];function l(c,i,r,m,u,k){return a(),s("div",null,p)}var g=n(t,[["render",l]]);export{h as __pageData,g as default}; diff --git a/assets/guide_index.md.25bdf89c.lean.js b/assets/guide_index.md.25bdf89c.lean.js new file mode 100644 index 00000000..6f34bfb3 --- /dev/null +++ b/assets/guide_index.md.25bdf89c.lean.js @@ -0,0 +1,116 @@ +import{_ as n,f as s,e as a,N as e}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u5F00\u59CB","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u524D\u8A00","slug":"\u524D\u8A00"},{"level":2,"title":"\u73AF\u5883\u51C6\u5907","slug":"\u73AF\u5883\u51C6\u5907"},{"level":2,"title":"\u5DE5\u5177\u914D\u7F6E","slug":"\u5DE5\u5177\u914D\u7F6E"},{"level":2,"title":"\u4EE3\u7801\u83B7\u53D6","slug":"\u4EE3\u7801\u83B7\u53D6"},{"level":3,"title":"\u4ECE GitHub \u83B7\u53D6\u4EE3\u7801","slug":"\u4ECE-github-\u83B7\u53D6\u4EE3\u7801"},{"level":3,"title":"\u4ECE Gitee \u83B7\u53D6\u4EE3\u7801","slug":"\u4ECE-gitee-\u83B7\u53D6\u4EE3\u7801"},{"level":2,"title":"\u5B89\u88C5","slug":"\u5B89\u88C5"},{"level":3,"title":"\u5B89\u88C5 Node.js","slug":"\u5B89\u88C5-node-js"},{"level":3,"title":"\u5B89\u88C5\u4F9D\u8D56","slug":"\u5B89\u88C5\u4F9D\u8D56"},{"level":3,"title":"imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\u89E3\u51B3\u65B9\u6CD5","slug":"imagemin-\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\u89E3\u51B3\u65B9\u6CD5"},{"level":2,"title":"npm script","slug":"npm-script"},{"level":3,"title":"\u751F\u6210\u56FE\u6807\u96C6","slug":"\u751F\u6210\u56FE\u6807\u96C6"},{"level":3,"title":"\u91CD\u65B0\u5B89\u88C5\u4F9D\u8D56","slug":"\u91CD\u65B0\u5B89\u88C5\u4F9D\u8D56"},{"level":2,"title":"\u76EE\u5F55\u8BF4\u660E","slug":"\u76EE\u5F55\u8BF4\u660E"}],"relativePath":"guide/index.md","lastUpdated":1694442156385}',t={},o=e(`__VP_STATIC_START__

\u5F00\u59CB

\u672C\u6587\u4F1A\u5E2E\u52A9\u4F60\u4ECE\u5934\u542F\u52A8\u9879\u76EE

\u524D\u8A00

\u5173\u4E8E\u7EC4\u4EF6

\u9879\u76EE\u867D\u7136\u4E8C\u6B21\u5C01\u88C5\u4E86\u4E00\u4E9B\u7EC4\u4EF6\uFF0C\u4F46\u662F\u53EF\u80FD\u4E0D\u80FD\u6EE1\u8DB3\u5927\u90E8\u5206\u7684\u8981\u6C42\u3002\u6240\u4EE5\uFF0C\u5982\u679C\u7EC4\u4EF6\u4E0D\u6EE1\u8DB3\u4F60\u7684\u8981\u6C42\uFF0C\u5B8C\u5168\u53EF\u4EE5\u4E0D\u7528\u751A\u81F3\u5220\u9664\u4EE3\u7801\u81EA\u5DF1\u5199\uFF0C\u4E0D\u5FC5\u575A\u6301\u4F7F\u7528\u9879\u76EE\u81EA\u5E26\u7684\u7EC4\u4EF6\u3002

\u73AF\u5883\u51C6\u5907

\u672C\u5730\u73AF\u5883\u9700\u8981\u5B89\u88C5 pnpm\u3001Node.js \u548C Git

\u6CE8\u610F

  • \u63A8\u8350\u4F7F\u7528pnpm\uFF0C\u5426\u5219\u4F9D\u8D56\u53EF\u80FD\u5B89\u88C5\u4E0D\u4E0A\u3002
  • Node.js \u7248\u672C\u8981\u6C4212.x\u4EE5\u4E0A\uFF0C\u4E14\u4E0D\u80FD\u4E3A13.x\u7248\u672C\uFF0C\u8FD9\u91CC\u63A8\u8350 14.x \u53CA\u4EE5\u4E0A\u3002

\u5DE5\u5177\u914D\u7F6E

\u5982\u679C\u60A8\u4F7F\u7528\u7684 IDE \u662Fvscode(\u63A8\u8350)\u7684\u8BDD\uFF0C\u53EF\u4EE5\u5B89\u88C5\u4EE5\u4E0B\u5DE5\u5177\u6765\u63D0\u9AD8\u5F00\u53D1\u6548\u7387\u53CA\u4EE3\u7801\u683C\u5F0F\u5316

\u4EE3\u7801\u83B7\u53D6

\u6CE8\u610F

\u6CE8\u610F\u5B58\u653E\u4EE3\u7801\u7684\u76EE\u5F55\u53CA\u6240\u6709\u7236\u7EA7\u76EE\u5F55\u4E0D\u80FD\u5B58\u5728\u4E2D\u6587\u3001\u97E9\u6587\u3001\u65E5\u6587\u4EE5\u53CA\u7A7A\u683C\uFF0C\u5426\u5219\u5B89\u88C5\u4F9D\u8D56\u540E\u542F\u52A8\u4F1A\u51FA\u9519\u3002

\u4ECE GitHub \u83B7\u53D6\u4EE3\u7801

# clone \u4EE3\u7801
+git clone https://github.com/vbenjs/vue-vben-admin.git
+
+

\u4ECE Gitee \u83B7\u53D6\u4EE3\u7801

\u5982\u679C\u4ECE github clone \u4EE3\u7801\u8F83\u6162\u7684\u8BDD\uFF0C\u53EF\u4EE5\u5C1D\u8BD5\u7528 Gitee \u540C\u6B65\u4EE3\u7801\u5230\u81EA\u5DF1\u7684\u4ED3\u5E93\uFF0C\u518D clone \u4E0B\u6765\u5373\u53EF\u3002

\u4E5F\u53EF\u4EE5\u901A\u8FC7\u4E0B\u65B9\u5730\u5740\u8FDB\u884C clone

git clone https://gitee.com/annsion/vue-vben-admin.git
+

\u6CE8\u610F

Gitee\u7684\u4EE3\u7801\u53EF\u80FD\u4E0D\u662F\u6700\u65B0\u7684

\u5B89\u88C5

\u5B89\u88C5 Node.js

\u5982\u679C\u60A8\u7535\u8111\u672A\u5B89\u88C5Node.js\uFF0C\u8BF7\u5B89\u88C5\u5B83\u3002

\u9A8C\u8BC1

# \u51FA\u73B0\u76F8\u5E94npm\u7248\u672C\u5373\u53EF
+npm -v
+# \u51FA\u73B0\u76F8\u5E94node\u7248\u672C\u5373\u53EF
+node -v
+
+

\u5982\u679C\u4F60\u9700\u8981\u540C\u65F6\u5B58\u5728\u591A\u4E2A node \u7248\u672C\uFF0C\u53EF\u4EE5\u4F7F\u7528 Nvm \u6216\u8005\u5176\u4ED6\u5DE5\u5177\u8FDB\u884C Node.js \u8FDB\u884C\u7248\u672C\u7BA1\u7406\u3002

\u5B89\u88C5\u4F9D\u8D56

pnpm \u5B89\u88C5

\u5FC5\u987B\u4F7F\u7528 pnpm\u8FDB\u884C\u4F9D\u8D56\u5B89\u88C5\uFF08\u82E5\u5176\u4ED6\u5305\u7BA1\u7406\u5668\u5B89\u88C5\u4E0D\u4E86\u9700\u8981\u81EA\u884C\u5904\u7406\uFF09\u3002

\u5982\u679C\u672A\u5B89\u88C5pnpm\uFF0C\u53EF\u4EE5\u7528\u4E0B\u9762\u547D\u4EE4\u6765\u8FDB\u884C\u5168\u5C40\u5B89\u88C5

# \u5168\u5C40\u5B89\u88C5pnpm
+npm install -g pnpm
+# \u9A8C\u8BC1
+pnpm -v # \u51FA\u73B0\u5BF9\u5E94\u7248\u672C\u53F7\u5373\u4EE3\u8868\u5B89\u88C5\u6210\u529F
+

\u4F9D\u8D56\u5B89\u88C5\u547D\u4EE4

\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\uFF0C\u6253\u5F00\u547D\u4EE4\u7A97\u53E3\u6267\u884C\uFF0C\u8010\u5FC3\u7B49\u5F85\u5B89\u88C5\u5B8C\u6210\u5373\u53EF

# \u5B89\u88C5\u4F9D\u8D56
+pnpm i
+

imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\u89E3\u51B3\u65B9\u6CD5

\u7531\u4E8E imagemin \u5728\u56FD\u5185\u5B89\u88C5\u56F0\u96BE\uFF0C\u63D0\u4F9B\u4EE5\u4E0B\u51E0\u4E2A\u89E3\u51B3\u65B9\u6848\uFF1A

  1. \u4F7F\u7528 yarn \u5728 package.json \u5185\u914D\u7F6E(\u63A8\u8350\uFF0C\u9879\u76EE\u5185\u5DF2\u96C6\u6210\uFF0C\u524D\u63D0\u662F\u5FC5\u987B\u4F7F\u7528 yarn)
"resolutions": {
+  "bin-wrapper": "npm:bin-wrapper-china"
+}
+
  1. \u4F7F\u7528 npm\uFF0C\u5728\u7535\u8111 host \u6587\u4EF6\u52A0\u4E0A\u5982\u4E0B\u914D\u7F6E\u5373\u53EF
199.232.4.133 raw.githubusercontent.com
+

\u5B89\u88C5\u4F9D\u8D56\u65F6 husky \u5B89\u88C5\u5931\u8D25

\u8BF7\u67E5\u770B\u4F60\u7684\u6E90\u7801\u662F\u5426\u4ECE github \u76F4\u63A5\u4E0B\u8F7D\u7684\uFF0C\u76F4\u63A5\u4E0B\u8F7D\u662F\u6CA1\u6709 .git \u6587\u4EF6\u5939\u7684\uFF0C\u800C husky \u9700\u8981\u4F9D\u8D56 git \u624D\u80FD\u5B89\u88C5\u3002\u6B64\u65F6\u9700\u4F7F\u7528 git init \u521D\u59CB\u5316\u9879\u76EE\uFF0C\u518D\u5C1D\u8BD5\u91CD\u65B0\u5B89\u88C5\u5373\u53EF\u3002

npm script

"scripts": {
+  # \u5B89\u88C5\u4F9D\u8D56
+  "bootstrap": "yarn install",
+  # \u8FD0\u884C\u9879\u76EE
+  "serve": "npm run dev",
+  # \u8FD0\u884C\u9879\u76EE
+  "dev": "vite",
+  # \u6784\u5EFA\u9879\u76EE
+  "build": "vite build && esno ./build/script/postBuild.ts",
+  # \u6E05\u7A7A\u7F13\u5B58\u540E\u6784\u5EFA\u9879\u76EE
+  "build:no-cache": "yarn clean:cache && npm run build",
+  # \u751F\u6210\u6253\u5305\u5206\u6790\uFF0C\u5728 \`Mac OS\` \u7535\u8111\u4E0A\u6267\u884C\u5B8C\u6210\u540E\u4F1A\u81EA\u52A8\u6253\u5F00\u754C\u9762\uFF0C\u5728 \`Window\` \u7535\u8111\u4E0A\u6267\u884C\u5B8C\u6210\u540E\u9700\u8981\u6253\u5F00 \`./build/.cache/stats.html\` \u67E5\u770B
+  "report": "cross-env REPORT=true npm run build",
+  # \u7C7B\u578B\u68C0\u67E5
+  "type:check": "vue-tsc --noEmit --skipLibCheck",
+  # \u9884\u89C8\u6253\u5305\u540E\u7684\u5185\u5BB9\uFF08\u5148\u6253\u5305\u5728\u8FDB\u884C\u9884\u89C8\uFF09
+  "preview": "npm run build && vite preview",
+  # \u76F4\u63A5\u9884\u89C8\u672C\u5730 dist \u6587\u4EF6\u76EE\u5F55
+  "preview:dist": "vite preview",
+  # \u751F\u6210 ChangeLog
+  "log": "conventional-changelog -p angular -i CHANGELOG.md -s",
+  # \u5220\u9664\u7F13\u5B58
+  "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
+  # \u5220\u9664 node_modules (\`window\` \u7CFB\u7EDF\u624B\u52A8\u5220\u9664\u8BE5\u76EE\u5F55\u8F83\u6162\uFF0C\u53EF\u4EE5\u4F7F\u7528\u8BE5\u547D\u4EE4\u6765\u8FDB\u884C\u5220\u9664)
+  "clean:lib": "rimraf node_modules",
+  # \u6267\u884C eslint \u6821\u9A8C\uFF0C\u5E76\u4FEE\u590D\u90E8\u5206\u95EE\u9898
+  "lint:eslint": "eslint \\"{src,mock}/**/*.{vue,ts,tsx}\\" --fix",
+  # \u6267\u884C prettier \u683C\u5F0F\u5316\uFF08\u8BE5\u547D\u4EE4\u4F1A\u5BF9\u9879\u76EE\u6240\u6709\u4EE3\u7801\u8FDB\u884C prettier \u683C\u5F0F\u5316\uFF0C\u8BF7\u8C28\u614E\u6267\u884C\uFF09
+  "lint:prettier": "prettier --write --loglevel warn \\"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\\"",
+  # \u6267\u884C stylelint \u683C\u5F0F\u5316
+  "lint:stylelint": "stylelint --fix \\"**/*.{vue,less,postcss,css,scss}\\" --cache --cache-location node_modules/.cache/stylelint/",
+  "lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
+  "lint:pretty": "pretty-quick --staged",
+  # \u5BF9\u6253\u5305\u7ED3\u679C\u8FDB\u884C gzip \u6D4B\u8BD5
+  "test:gzip": "http-server dist --cors --gzip -c-1",
+  # \u5BF9\u6253\u5305\u76EE\u5F55\u8FDB\u884C brotli \u6D4B\u8BD5
+  "test:br": "http-server dist --cors --brotli -c-1",
+  # \u91CD\u65B0\u5B89\u88C5\u4F9D\u8D56\uFF0C\u89C1\u4E0B\u65B9\u8BF4\u660E
+  "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
+  "install:husky": "is-ci || husky install",
+  # \u751F\u6210\u56FE\u6807\u96C6\uFF0C\u89C1\u4E0B\u65B9\u8BF4\u660E
+  "gen:icon": "esno ./build/generate/icon/index.ts",
+  "postinstall": "npm run install:husky"
+},
+

\u751F\u6210\u56FE\u6807\u96C6

\u8BE5\u547D\u4EE4\u4F1A\u751F\u6210\u6240\u9009\u62E9\u7684\u56FE\u6807\u96C6\uFF0C\u63D0\u4F9B\u7ED9\u56FE\u6807\u9009\u62E9\u5668\u4F7F\u7528\u3002\u5177\u4F53\u4F7F\u7528\u65B9\u5F0F\u8BF7\u67E5\u770B \u56FE\u6807\u96C6\u751F\u6210

\u91CD\u65B0\u5B89\u88C5\u4F9D\u8D56

\u8BE5\u547D\u4EE4\u4F1A\u5148\u5220\u9664 node_modules\u3001yarn.lock\u3001package.lock.json \u540E\u518D\u8FDB\u884C\u4F9D\u8D56\u91CD\u65B0\u5B89\u88C5\uFF08\u5B89\u88C5\u901F\u5EA6\u4F1A\u660E\u663E\u53D8\u6162\uFF09\u3002

\u63A5\u4E0B\u6765\u4F60\u53EF\u4EE5\u4FEE\u6539\u4EE3\u7801\u8FDB\u884C\u4E1A\u52A1\u5F00\u53D1\u4E86\u3002\u6211\u4EEC\u5185\u5EFA\u4E86\u6A21\u62DF\u6570\u636E\u3001HMR \u5B9E\u65F6\u9884\u89C8\u3001\u72B6\u6001\u7BA1\u7406\u3001\u56FD\u9645\u5316\u3001\u5168\u5C40\u8DEF\u7531\u7B49\u5404\u79CD\u5B9E\u7528\u7684\u529F\u80FD\u8F85\u52A9\u5F00\u53D1\uFF0C\u8BF7\u9605\u8BFB\u5176\u4ED6\u7AE0\u8282\u4E86\u89E3\u66F4\u591A\u3002

\u76EE\u5F55\u8BF4\u660E


+.
+\u251C\u2500\u2500 build # \u6253\u5305\u811A\u672C\u76F8\u5173
+\u2502   \u251C\u2500\u2500 config # \u914D\u7F6E\u6587\u4EF6
+\u2502   \u251C\u2500\u2500 generate # \u751F\u6210\u5668
+\u2502   \u251C\u2500\u2500 script # \u811A\u672C
+\u2502   \u2514\u2500\u2500 vite # vite\u914D\u7F6E
+\u251C\u2500\u2500 mock # mock\u6587\u4EF6\u5939
+\u251C\u2500\u2500 public # \u516C\u5171\u9759\u6001\u8D44\u6E90\u76EE\u5F55
+\u251C\u2500\u2500 src # \u4E3B\u76EE\u5F55
+\u2502   \u251C\u2500\u2500 api # \u63A5\u53E3\u6587\u4EF6
+\u2502   \u251C\u2500\u2500 assets # \u8D44\u6E90\u6587\u4EF6
+\u2502   \u2502   \u251C\u2500\u2500 icons # icon sprite \u56FE\u6807\u6587\u4EF6\u5939
+\u2502   \u2502   \u251C\u2500\u2500 images # \u9879\u76EE\u5B58\u653E\u56FE\u7247\u7684\u6587\u4EF6\u5939
+\u2502   \u2502   \u2514\u2500\u2500 svg # \u9879\u76EE\u5B58\u653Esvg\u56FE\u7247\u7684\u6587\u4EF6\u5939
+\u2502   \u251C\u2500\u2500 components # \u516C\u5171\u7EC4\u4EF6
+\u2502   \u251C\u2500\u2500 design # \u6837\u5F0F\u6587\u4EF6
+\u2502   \u251C\u2500\u2500 directives # \u6307\u4EE4
+\u2502   \u251C\u2500\u2500 enums # \u679A\u4E3E/\u5E38\u91CF
+\u2502   \u251C\u2500\u2500 hooks # hook
+\u2502   \u2502   \u251C\u2500\u2500 component # \u7EC4\u4EF6\u76F8\u5173hook
+\u2502   \u2502   \u251C\u2500\u2500 core # \u57FA\u7840hook
+\u2502   \u2502   \u251C\u2500\u2500 event # \u4E8B\u4EF6\u76F8\u5173hook
+\u2502   \u2502   \u251C\u2500\u2500 setting # \u914D\u7F6E\u76F8\u5173hook
+\u2502   \u2502   \u2514\u2500\u2500 web # web\u76F8\u5173hook
+\u2502   \u251C\u2500\u2500 layouts # \u5E03\u5C40\u6587\u4EF6
+\u2502   \u2502   \u251C\u2500\u2500 default # \u9ED8\u8BA4\u5E03\u5C40
+\u2502   \u2502   \u251C\u2500\u2500 iframe # iframe\u5E03\u5C40
+\u2502   \u2502   \u2514\u2500\u2500 page # \u9875\u9762\u5E03\u5C40
+\u2502   \u251C\u2500\u2500 locales # \u591A\u8BED\u8A00
+\u2502   \u251C\u2500\u2500 logics # \u903B\u8F91
+\u2502   \u251C\u2500\u2500 main.ts # \u4E3B\u5165\u53E3
+\u2502   \u251C\u2500\u2500 router # \u8DEF\u7531\u914D\u7F6E
+\u2502   \u251C\u2500\u2500 settings # \u9879\u76EE\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 componentSetting.ts # \u7EC4\u4EF6\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 designSetting.ts # \u6837\u5F0F\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 encryptionSetting.ts # \u52A0\u5BC6\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 localeSetting.ts # \u591A\u8BED\u8A00\u914D\u7F6E
+\u2502   \u2502   \u251C\u2500\u2500 projectSetting.ts # \u9879\u76EE\u914D\u7F6E
+\u2502   \u2502   \u2514\u2500\u2500 siteSetting.ts # \u7AD9\u70B9\u914D\u7F6E
+\u2502   \u251C\u2500\u2500 store # \u6570\u636E\u4ED3\u5E93
+\u2502   \u251C\u2500\u2500 utils # \u5DE5\u5177\u7C7B
+\u2502   \u2514\u2500\u2500 views # \u9875\u9762
+\u251C\u2500\u2500 test # \u6D4B\u8BD5
+\u2502   \u2514\u2500\u2500 server # \u6D4B\u8BD5\u7528\u5230\u7684\u670D\u52A1
+\u2502       \u251C\u2500\u2500 api # \u6D4B\u8BD5\u670D\u52A1\u5668
+\u2502       \u251C\u2500\u2500 upload # \u6D4B\u8BD5\u4E0A\u4F20\u670D\u52A1\u5668
+\u2502       \u2514\u2500\u2500 websocket # \u6D4B\u8BD5ws\u670D\u52A1\u5668
+\u251C\u2500\u2500 types # \u7C7B\u578B\u6587\u4EF6
+\u251C\u2500\u2500 vite.config.ts # vite\u914D\u7F6E\u6587\u4EF6
+\u2514\u2500\u2500 windi.config.ts # windcss\u914D\u7F6E\u6587\u4EF6
+
+
__VP_STATIC_END__`,49),p=[o];function l(c,i,r,m,u,k){return a(),s("div",null,p)}var g=n(t,[["render",l]]);export{h as __pageData,g as default}; diff --git a/assets/guide_introduction.md.c5c06773.js b/assets/guide_introduction.md.c5c06773.js new file mode 100644 index 00000000..30b8e333 --- /dev/null +++ b/assets/guide_introduction.md.c5c06773.js @@ -0,0 +1,9 @@ +import{_ as e,f as r,e as t,N as n}from"./plugin-vue_export-helper.147b70e9.js";const b='{"title":"\u4ECB\u7ECD","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u7B80\u4ECB","slug":"\u7B80\u4ECB"},{"level":2,"title":"\u6587\u6863","slug":"\u6587\u6863"},{"level":3,"title":"\u672C\u5730\u8FD0\u884C\u6587\u6863","slug":"\u672C\u5730\u8FD0\u884C\u6587\u6863"},{"level":2,"title":"\u9700\u8981\u638C\u63E1\u7684\u57FA\u7840\u77E5\u8BC6","slug":"\u9700\u8981\u638C\u63E1\u7684\u57FA\u7840\u77E5\u8BC6"},{"level":2,"title":"\u6A21\u7248","slug":"\u6A21\u7248"},{"level":2,"title":"vite \u63D2\u4EF6\u63A8\u8350","slug":"vite-\u63D2\u4EF6\u63A8\u8350"},{"level":2,"title":"\u6D4F\u89C8\u5668\u652F\u6301","slug":"\u6D4F\u89C8\u5668\u652F\u6301"},{"level":2,"title":"\u5982\u4F55\u52A0\u5165\u6211\u4EEC","slug":"\u5982\u4F55\u52A0\u5165\u6211\u4EEC"}],"relativePath":"guide/introduction.md","lastUpdated":1694442156385}',a={},o=n(`

\u4ECB\u7ECD

\u7B80\u4ECB

Vue-Vben-Admin \u662F\u4E00\u4E2A\u57FA\u4E8E Vue3.0\u3001Vite\u3001 Ant-Design-Vue\u3001TypeScript \u7684\u540E\u53F0\u89E3\u51B3\u65B9\u6848\uFF0C\u76EE\u6807\u662F\u4E3A\u5F00\u53D1\u4E2D\u5927\u578B\u9879\u76EE\u63D0\u4F9B\u5F00\u7BB1\u5373\u7528\u7684\u89E3\u51B3\u65B9\u6848\u3002\u5305\u62EC\u4E8C\u6B21\u5C01\u88C5\u7EC4\u4EF6\u3001utils\u3001hooks\u3001\u52A8\u6001\u83DC\u5355\u3001\u6743\u9650\u6821\u9A8C\u3001\u6309\u94AE\u7EA7\u522B\u6743\u9650\u63A7\u5236\u7B49\u529F\u80FD\u3002\u9879\u76EE\u4F1A\u4F7F\u7528\u524D\u7AEF\u8F83\u65B0\u7684\u6280\u672F\u6808\uFF0C\u53EF\u4EE5\u4F5C\u4E3A\u9879\u76EE\u7684\u542F\u52A8\u6A21\u7248\uFF0C\u4EE5\u5E2E\u52A9\u4F60\u5FEB\u901F\u642D\u5EFA\u4F01\u4E1A\u7EA7\u4E2D\u540E\u53F0\u4EA7\u54C1\u539F\u578B\u3002\u4E5F\u53EF\u4EE5\u4F5C\u4E3A\u4E00\u4E2A\u793A\u4F8B\uFF0C\u7528\u4E8E\u5B66\u4E60 vue3\u3001vite\u3001ts \u7B49\u4E3B\u6D41\u6280\u672F\u3002\u8BE5\u9879\u76EE\u4F1A\u6301\u7EED\u8DDF\u8FDB\u6700\u65B0\u6280\u672F\uFF0C\u5E76\u5C06\u5176\u5E94\u7528\u5728\u9879\u76EE\u4E2D\u3002

\u6587\u6863

  • \u4E2D\u6587\u6587\u6863\u5730\u5740\u4E3A vben-admin-doc\uFF0C\u91C7\u7528 Vitepress \u5F00\u53D1\u3002\u5982\u53D1\u73B0\u6587\u6863\u6709\u8BEF\uFF0C\u6B22\u8FCE\u63D0 pr \u5E2E\u52A9\u6211\u4EEC\u6539\u8FDB\u3002
  • \u82F1\u6587\u6587\u6863\u6682\u65F6\u6CA1\u6709\u65F6\u95F4\u6765\u5199\uFF0C\u6B22\u8FCE\u6709\u65F6\u95F4\u7684\u540C\u5B66\u6765\u5E2E\u5FD9\u5199\u82F1\u6587\u6587\u6863\u3002

\u672C\u5730\u8FD0\u884C\u6587\u6863

\u5982\u9700\u672C\u5730\u8FD0\u884C\u6587\u6863\uFF0C\u8BF7\u62C9\u53D6\u4EE3\u7801\u5230\u672C\u5730\u3002

# \u62C9\u53D6\u4EE3\u7801
+git clone https://github.com/vbenjs/vue-vben-admin-doc
+
+# \u5B89\u88C5\u4F9D\u8D56
+yarn
+
+# \u8FD0\u884C\u9879\u76EE
+yarn dev
+

\u9700\u8981\u638C\u63E1\u7684\u57FA\u7840\u77E5\u8BC6

\u672C\u9879\u76EE\u9700\u8981\u4E00\u5B9A\u524D\u7AEF\u57FA\u7840\u77E5\u8BC6\uFF0C\u8BF7\u786E\u4FDD\u638C\u63E1 Vue \u7684\u57FA\u7840\u77E5\u8BC6\uFF0C\u4EE5\u4FBF\u80FD\u5904\u7406\u4E00\u4E9B\u5E38\u89C1\u7684\u95EE\u9898\u3002 \u5EFA\u8BAE\u5728\u5F00\u53D1\u524D\u5148\u5B66\u4E00\u4E0B\u4EE5\u4E0B\u5185\u5BB9\uFF0C\u63D0\u524D\u4E86\u89E3\u548C\u5B66\u4E60\u8FD9\u4E9B\u77E5\u8BC6\uFF0C\u4F1A\u5BF9\u9879\u76EE\u7406\u89E3\u975E\u5E38\u6709\u5E2E\u52A9:

\u6A21\u7248

\u8BE5\u7248\u672C\u4E3B\u8981\u662F\u63D0\u4F9B\u4E00\u4E9B Demo \u793A\u4F8B\u53CA\u63D2\u4EF6\u7684\u4F7F\u7528\u96C6\u6210\u65B9\u5F0F\uFF0C\u4E3B\u8981\u7528\u4E8E\u53C2\u8003\u3002\u5982\u679C\u5BF9\u9879\u76EE\u4E0D\u662F\u5F88\u719F\u6089\uFF0C\u4E0D\u5EFA\u8BAE\u5728\u6B64\u57FA\u7840\u4E0A\u8FDB\u884C\u5F00\u53D1\uFF0C\u8BF7\u4F7F\u7528\u4E0B\u65B9\u63D0\u4F9B\u7684\u7CBE\u7B80\u7248\u672C\u3002

vue-vben-admin \u7CBE\u7B80\u7248\u672C\u3002\u5220\u9664\u4E86\u76F8\u5173\u793A\u4F8B\u3001\u65E0\u7528\u6587\u4EF6\u53CA\u529F\u80FD\u3001\u4F9D\u8D56\u3002\u53EF\u4EE5\u6839\u636E\u81EA\u8EAB\u9700\u6C42\u5B89\u88C5\u5BF9\u5E94\u7684\u4F9D\u8D56\u3002\u56E0\u4E3A\u4F7F\u7528\u7684\u662F vite\uFF0C\u4F9D\u8D56\u5220\u9664\u4E0D\u4F1A\u5BFC\u81F4\u76F8\u5173\u7EC4\u4EF6\u6216\u8005 hook \u53D1\u51FA\u8B66\u544A\u3002\u53EA\u5728\u9700\u8981\u7684\u65F6\u5019\u5B89\u88C5\u5BF9\u5E94\u7684\u5E93\u5373\u53EF\u3002

vite \u63D2\u4EF6\u63A8\u8350

\u5982\u679C\u8FD9\u4E9B\u63D2\u4EF6\u5BF9\u4F60\u6709\u5E2E\u52A9\uFF0C\u53EF\u4EE5\u7ED9\u4E00\u4E2A star \u652F\u6301\u4E0B

  • vite-plugin-mock - \u7528\u4E8E\u672C\u5730\u53CA\u5F00\u53D1\u73AF\u5883\u6570\u636E mock
  • vite-plugin-html - \u7528\u4E8E html \u6A21\u7248\u8F6C\u6362\uFF0C\u53EF\u4EE5\u5728html\u6587\u4EF6\u5185\u8FDB\u884C\u4E66\u5199\u6A21\u7248\u8BED\u6CD5
  • vite-plugin-style-import - \u7528\u4E8E\u7EC4\u4EF6\u5E93\u6837\u5F0F\u6309\u9700\u5F15\u5165
  • vite-plugin-imagemin - \u7528\u4E8E\u6253\u5305\u538B\u7F29\u56FE\u7247\u8D44\u6E90
  • vite-plugin-theme - \u7528\u4E8E\u5728\u7EBF\u5207\u6362\u4E3B\u9898\u8272/\u9ED1\u6697\u4E3B\u9898\u9002\u914D\u7B49\u4E3B\u9898\u76F8\u5173\u914D\u7F6E
  • vite-plugin-compression - \u7528\u4E8E\u6253\u5305\u8F93\u51FA.gz|.br\u6587\u4EF6
  • vite-plugin-svg-icons - \u5FEB\u901F\u751F\u6210 svg sprite

\u6D4F\u89C8\u5668\u652F\u6301

\u672C\u5730\u5F00\u53D1\u63A8\u8350\u4F7F\u7528Chrome \u6700\u65B0\u7248\u6D4F\u89C8\u5668\uFF0C\u4E0D\u652F\u6301Chrome 80\u4EE5\u4E0B\u7248\u672C\u3002

\u751F\u4EA7\u73AF\u5883\u652F\u6301\u73B0\u4EE3\u6D4F\u89C8\u5668\uFF0C\u4E0D\u652F\u6301 IE\u3002

IEIE EdgeEdgeFirefoxFirefoxChromeChromeSafariSafari
not supportlast 2 versionslast 2 versionslast 2 versionslast 2 versions

\u5982\u4F55\u52A0\u5165\u6211\u4EEC

  • Vue-Vben-Admin \u8FD8\u5728\u6301\u7EED\u66F4\u65B0\u4E2D\uFF0C\u672C\u9879\u76EE\u6B22\u8FCE\u60A8\u7684\u53C2\u4E0E\uFF0C\u5171\u540C\u7EF4\u62A4\uFF0C\u9010\u6B65\u5B8C\u5584\uFF0C\u5C06\u9879\u76EE\u505A\u5F97\u66F4\u5F3A\u3002\u540C\u65F6\u6574\u4E2A\u9879\u76EE\u672C\u7740\u4E00\u5207\u514D\u8D39\u7684\u539F\u5219\uFF0C\u539F\u5219\u4E0A\u4E0D\u4F1A\u6536\u53D6\u4EFB\u4F55\u8D39\u7528\u53CA\u7248\u6743\uFF0C\u53EF\u4EE5\u653E\u5FC3\u4F7F\u7528\u3002
  • \u5982\u679C\u4F60\u60F3\u52A0\u5165\u6211\u4EEC\uFF0C\u53EF\u4EE5\u591A\u63D0\u4F9B\u4E00\u4E9B\u597D\u7684\u5EFA\u8BAE\u6216\u8005\u63D0\u4EA4 pr\uFF0C\u6211\u4EEC\u4F1A\u6839\u636E\u4F60\u7684\u6D3B\u8DC3\u5EA6\u9080\u8BF7\u4F60\u52A0\u5165\u3002
`,25),i=[o];function l(s,h,p,c,g,d){return t(),r("div",null,i)}var f=e(a,[["render",l]]);export{b as __pageData,f as default}; diff --git a/assets/guide_introduction.md.c5c06773.lean.js b/assets/guide_introduction.md.c5c06773.lean.js new file mode 100644 index 00000000..d3bd51a7 --- /dev/null +++ b/assets/guide_introduction.md.c5c06773.lean.js @@ -0,0 +1,9 @@ +import{_ as e,f as r,e as t,N as n}from"./plugin-vue_export-helper.147b70e9.js";const b='{"title":"\u4ECB\u7ECD","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u7B80\u4ECB","slug":"\u7B80\u4ECB"},{"level":2,"title":"\u6587\u6863","slug":"\u6587\u6863"},{"level":3,"title":"\u672C\u5730\u8FD0\u884C\u6587\u6863","slug":"\u672C\u5730\u8FD0\u884C\u6587\u6863"},{"level":2,"title":"\u9700\u8981\u638C\u63E1\u7684\u57FA\u7840\u77E5\u8BC6","slug":"\u9700\u8981\u638C\u63E1\u7684\u57FA\u7840\u77E5\u8BC6"},{"level":2,"title":"\u6A21\u7248","slug":"\u6A21\u7248"},{"level":2,"title":"vite \u63D2\u4EF6\u63A8\u8350","slug":"vite-\u63D2\u4EF6\u63A8\u8350"},{"level":2,"title":"\u6D4F\u89C8\u5668\u652F\u6301","slug":"\u6D4F\u89C8\u5668\u652F\u6301"},{"level":2,"title":"\u5982\u4F55\u52A0\u5165\u6211\u4EEC","slug":"\u5982\u4F55\u52A0\u5165\u6211\u4EEC"}],"relativePath":"guide/introduction.md","lastUpdated":1694442156385}',a={},o=n(`__VP_STATIC_START__

\u4ECB\u7ECD

\u7B80\u4ECB

Vue-Vben-Admin \u662F\u4E00\u4E2A\u57FA\u4E8E Vue3.0\u3001Vite\u3001 Ant-Design-Vue\u3001TypeScript \u7684\u540E\u53F0\u89E3\u51B3\u65B9\u6848\uFF0C\u76EE\u6807\u662F\u4E3A\u5F00\u53D1\u4E2D\u5927\u578B\u9879\u76EE\u63D0\u4F9B\u5F00\u7BB1\u5373\u7528\u7684\u89E3\u51B3\u65B9\u6848\u3002\u5305\u62EC\u4E8C\u6B21\u5C01\u88C5\u7EC4\u4EF6\u3001utils\u3001hooks\u3001\u52A8\u6001\u83DC\u5355\u3001\u6743\u9650\u6821\u9A8C\u3001\u6309\u94AE\u7EA7\u522B\u6743\u9650\u63A7\u5236\u7B49\u529F\u80FD\u3002\u9879\u76EE\u4F1A\u4F7F\u7528\u524D\u7AEF\u8F83\u65B0\u7684\u6280\u672F\u6808\uFF0C\u53EF\u4EE5\u4F5C\u4E3A\u9879\u76EE\u7684\u542F\u52A8\u6A21\u7248\uFF0C\u4EE5\u5E2E\u52A9\u4F60\u5FEB\u901F\u642D\u5EFA\u4F01\u4E1A\u7EA7\u4E2D\u540E\u53F0\u4EA7\u54C1\u539F\u578B\u3002\u4E5F\u53EF\u4EE5\u4F5C\u4E3A\u4E00\u4E2A\u793A\u4F8B\uFF0C\u7528\u4E8E\u5B66\u4E60 vue3\u3001vite\u3001ts \u7B49\u4E3B\u6D41\u6280\u672F\u3002\u8BE5\u9879\u76EE\u4F1A\u6301\u7EED\u8DDF\u8FDB\u6700\u65B0\u6280\u672F\uFF0C\u5E76\u5C06\u5176\u5E94\u7528\u5728\u9879\u76EE\u4E2D\u3002

\u6587\u6863

  • \u4E2D\u6587\u6587\u6863\u5730\u5740\u4E3A vben-admin-doc\uFF0C\u91C7\u7528 Vitepress \u5F00\u53D1\u3002\u5982\u53D1\u73B0\u6587\u6863\u6709\u8BEF\uFF0C\u6B22\u8FCE\u63D0 pr \u5E2E\u52A9\u6211\u4EEC\u6539\u8FDB\u3002
  • \u82F1\u6587\u6587\u6863\u6682\u65F6\u6CA1\u6709\u65F6\u95F4\u6765\u5199\uFF0C\u6B22\u8FCE\u6709\u65F6\u95F4\u7684\u540C\u5B66\u6765\u5E2E\u5FD9\u5199\u82F1\u6587\u6587\u6863\u3002

\u672C\u5730\u8FD0\u884C\u6587\u6863

\u5982\u9700\u672C\u5730\u8FD0\u884C\u6587\u6863\uFF0C\u8BF7\u62C9\u53D6\u4EE3\u7801\u5230\u672C\u5730\u3002

# \u62C9\u53D6\u4EE3\u7801
+git clone https://github.com/vbenjs/vue-vben-admin-doc
+
+# \u5B89\u88C5\u4F9D\u8D56
+yarn
+
+# \u8FD0\u884C\u9879\u76EE
+yarn dev
+

\u9700\u8981\u638C\u63E1\u7684\u57FA\u7840\u77E5\u8BC6

\u672C\u9879\u76EE\u9700\u8981\u4E00\u5B9A\u524D\u7AEF\u57FA\u7840\u77E5\u8BC6\uFF0C\u8BF7\u786E\u4FDD\u638C\u63E1 Vue \u7684\u57FA\u7840\u77E5\u8BC6\uFF0C\u4EE5\u4FBF\u80FD\u5904\u7406\u4E00\u4E9B\u5E38\u89C1\u7684\u95EE\u9898\u3002 \u5EFA\u8BAE\u5728\u5F00\u53D1\u524D\u5148\u5B66\u4E00\u4E0B\u4EE5\u4E0B\u5185\u5BB9\uFF0C\u63D0\u524D\u4E86\u89E3\u548C\u5B66\u4E60\u8FD9\u4E9B\u77E5\u8BC6\uFF0C\u4F1A\u5BF9\u9879\u76EE\u7406\u89E3\u975E\u5E38\u6709\u5E2E\u52A9:

\u6A21\u7248

\u8BE5\u7248\u672C\u4E3B\u8981\u662F\u63D0\u4F9B\u4E00\u4E9B Demo \u793A\u4F8B\u53CA\u63D2\u4EF6\u7684\u4F7F\u7528\u96C6\u6210\u65B9\u5F0F\uFF0C\u4E3B\u8981\u7528\u4E8E\u53C2\u8003\u3002\u5982\u679C\u5BF9\u9879\u76EE\u4E0D\u662F\u5F88\u719F\u6089\uFF0C\u4E0D\u5EFA\u8BAE\u5728\u6B64\u57FA\u7840\u4E0A\u8FDB\u884C\u5F00\u53D1\uFF0C\u8BF7\u4F7F\u7528\u4E0B\u65B9\u63D0\u4F9B\u7684\u7CBE\u7B80\u7248\u672C\u3002

vue-vben-admin \u7CBE\u7B80\u7248\u672C\u3002\u5220\u9664\u4E86\u76F8\u5173\u793A\u4F8B\u3001\u65E0\u7528\u6587\u4EF6\u53CA\u529F\u80FD\u3001\u4F9D\u8D56\u3002\u53EF\u4EE5\u6839\u636E\u81EA\u8EAB\u9700\u6C42\u5B89\u88C5\u5BF9\u5E94\u7684\u4F9D\u8D56\u3002\u56E0\u4E3A\u4F7F\u7528\u7684\u662F vite\uFF0C\u4F9D\u8D56\u5220\u9664\u4E0D\u4F1A\u5BFC\u81F4\u76F8\u5173\u7EC4\u4EF6\u6216\u8005 hook \u53D1\u51FA\u8B66\u544A\u3002\u53EA\u5728\u9700\u8981\u7684\u65F6\u5019\u5B89\u88C5\u5BF9\u5E94\u7684\u5E93\u5373\u53EF\u3002

vite \u63D2\u4EF6\u63A8\u8350

\u5982\u679C\u8FD9\u4E9B\u63D2\u4EF6\u5BF9\u4F60\u6709\u5E2E\u52A9\uFF0C\u53EF\u4EE5\u7ED9\u4E00\u4E2A star \u652F\u6301\u4E0B

  • vite-plugin-mock - \u7528\u4E8E\u672C\u5730\u53CA\u5F00\u53D1\u73AF\u5883\u6570\u636E mock
  • vite-plugin-html - \u7528\u4E8E html \u6A21\u7248\u8F6C\u6362\uFF0C\u53EF\u4EE5\u5728html\u6587\u4EF6\u5185\u8FDB\u884C\u4E66\u5199\u6A21\u7248\u8BED\u6CD5
  • vite-plugin-style-import - \u7528\u4E8E\u7EC4\u4EF6\u5E93\u6837\u5F0F\u6309\u9700\u5F15\u5165
  • vite-plugin-imagemin - \u7528\u4E8E\u6253\u5305\u538B\u7F29\u56FE\u7247\u8D44\u6E90
  • vite-plugin-theme - \u7528\u4E8E\u5728\u7EBF\u5207\u6362\u4E3B\u9898\u8272/\u9ED1\u6697\u4E3B\u9898\u9002\u914D\u7B49\u4E3B\u9898\u76F8\u5173\u914D\u7F6E
  • vite-plugin-compression - \u7528\u4E8E\u6253\u5305\u8F93\u51FA.gz|.br\u6587\u4EF6
  • vite-plugin-svg-icons - \u5FEB\u901F\u751F\u6210 svg sprite

\u6D4F\u89C8\u5668\u652F\u6301

\u672C\u5730\u5F00\u53D1\u63A8\u8350\u4F7F\u7528Chrome \u6700\u65B0\u7248\u6D4F\u89C8\u5668\uFF0C\u4E0D\u652F\u6301Chrome 80\u4EE5\u4E0B\u7248\u672C\u3002

\u751F\u4EA7\u73AF\u5883\u652F\u6301\u73B0\u4EE3\u6D4F\u89C8\u5668\uFF0C\u4E0D\u652F\u6301 IE\u3002

IEIE EdgeEdgeFirefoxFirefoxChromeChromeSafariSafari
not supportlast 2 versionslast 2 versionslast 2 versionslast 2 versions

\u5982\u4F55\u52A0\u5165\u6211\u4EEC

  • Vue-Vben-Admin \u8FD8\u5728\u6301\u7EED\u66F4\u65B0\u4E2D\uFF0C\u672C\u9879\u76EE\u6B22\u8FCE\u60A8\u7684\u53C2\u4E0E\uFF0C\u5171\u540C\u7EF4\u62A4\uFF0C\u9010\u6B65\u5B8C\u5584\uFF0C\u5C06\u9879\u76EE\u505A\u5F97\u66F4\u5F3A\u3002\u540C\u65F6\u6574\u4E2A\u9879\u76EE\u672C\u7740\u4E00\u5207\u514D\u8D39\u7684\u539F\u5219\uFF0C\u539F\u5219\u4E0A\u4E0D\u4F1A\u6536\u53D6\u4EFB\u4F55\u8D39\u7528\u53CA\u7248\u6743\uFF0C\u53EF\u4EE5\u653E\u5FC3\u4F7F\u7528\u3002
  • \u5982\u679C\u4F60\u60F3\u52A0\u5165\u6211\u4EEC\uFF0C\u53EF\u4EE5\u591A\u63D0\u4F9B\u4E00\u4E9B\u597D\u7684\u5EFA\u8BAE\u6216\u8005\u63D0\u4EA4 pr\uFF0C\u6211\u4EEC\u4F1A\u6839\u636E\u4F60\u7684\u6D3B\u8DC3\u5EA6\u9080\u8BF7\u4F60\u52A0\u5165\u3002
__VP_STATIC_END__`,25),i=[o];function l(s,h,p,c,g,d){return t(),r("div",null,i)}var f=e(a,[["render",l]]);export{b as __pageData,f as default}; diff --git a/assets/guide_lib.md.5f86fd1c.js b/assets/guide_lib.md.5f86fd1c.js new file mode 100644 index 00000000..d98f2b1d --- /dev/null +++ b/assets/guide_lib.md.5f86fd1c.js @@ -0,0 +1,22 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u5F15\u5165\u5916\u90E8\u6A21\u5757","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u5B89\u88C5","slug":"\u5B89\u88C5"},{"level":2,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":3,"title":"\u5168\u5C40\u4F7F\u7528","slug":"\u5168\u5C40\u4F7F\u7528"},{"level":3,"title":"\u5C40\u90E8\u4F7F\u7528","slug":"\u5C40\u90E8\u4F7F\u7528"},{"level":2,"title":"\u6CE8\u610F","slug":"\u6CE8\u610F"}],"relativePath":"guide/lib.md","lastUpdated":1694442156385}',p={},e=t(`

\u5F15\u5165\u5916\u90E8\u6A21\u5757

\u9664\u4E86\u81EA\u5E26\u7EC4\u4EF6\u4EE5\u5916\uFF0C\u6709\u65F6\u6211\u4EEC\u8FD8\u9700\u8981\u5F15\u5165\u5176\u4ED6\u5916\u90E8\u6A21\u5757\u3002\u6211\u4EEC\u4EE5 ant-design-vue \u4E3A\u4F8B\uFF1A

\u5B89\u88C5

\u5B89\u88C5 ant-design-vue

# \u5728\u7EC8\u7AEF\u8F93\u5165\u4E0B\u9762\u7684\u547D\u4EE4\u5B8C\u6210\u5B89\u88C5
+yarn add ant-design-vue
+

\u4F7F\u7528

\u5168\u5C40\u4F7F\u7528

import { createApp } from 'vue';
+import App from './App.vue';
+import Antd from 'ant-design-vue';
+const app = createApp(App);
+app.use(Antd);
+app.mount('#app');
+

\u5C40\u90E8\u4F7F\u7528

<template>
+  <Button>text</Button>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Button } from 'ant-design-vue';
+  export default defineComponent({
+    components: {
+      Button,
+    },
+  });
+</script>
+

\u6CE8\u610F

  • \u5982\u679C\u7EC4\u4EF6\u6709\u4F9D\u8D56\u6837\u5F0F\uFF0C\u5219\u9700\u8981\u518D\u5F15\u5165\u6837\u5F0F\u6587\u4EF6
`,12),o=[e];function c(l,u,i,k,r,d){return s(),a("div",null,o)}var f=n(p,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/guide_lib.md.5f86fd1c.lean.js b/assets/guide_lib.md.5f86fd1c.lean.js new file mode 100644 index 00000000..72b46e26 --- /dev/null +++ b/assets/guide_lib.md.5f86fd1c.lean.js @@ -0,0 +1,22 @@ +import{_ as n,f as a,e as s,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u5F15\u5165\u5916\u90E8\u6A21\u5757","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u5B89\u88C5","slug":"\u5B89\u88C5"},{"level":2,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"},{"level":3,"title":"\u5168\u5C40\u4F7F\u7528","slug":"\u5168\u5C40\u4F7F\u7528"},{"level":3,"title":"\u5C40\u90E8\u4F7F\u7528","slug":"\u5C40\u90E8\u4F7F\u7528"},{"level":2,"title":"\u6CE8\u610F","slug":"\u6CE8\u610F"}],"relativePath":"guide/lib.md","lastUpdated":1694442156385}',p={},e=t(`__VP_STATIC_START__

\u5F15\u5165\u5916\u90E8\u6A21\u5757

\u9664\u4E86\u81EA\u5E26\u7EC4\u4EF6\u4EE5\u5916\uFF0C\u6709\u65F6\u6211\u4EEC\u8FD8\u9700\u8981\u5F15\u5165\u5176\u4ED6\u5916\u90E8\u6A21\u5757\u3002\u6211\u4EEC\u4EE5 ant-design-vue \u4E3A\u4F8B\uFF1A

\u5B89\u88C5

\u5B89\u88C5 ant-design-vue

# \u5728\u7EC8\u7AEF\u8F93\u5165\u4E0B\u9762\u7684\u547D\u4EE4\u5B8C\u6210\u5B89\u88C5
+yarn add ant-design-vue
+

\u4F7F\u7528

\u5168\u5C40\u4F7F\u7528

import { createApp } from 'vue';
+import App from './App.vue';
+import Antd from 'ant-design-vue';
+const app = createApp(App);
+app.use(Antd);
+app.mount('#app');
+

\u5C40\u90E8\u4F7F\u7528

<template>
+  <Button>text</Button>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Button } from 'ant-design-vue';
+  export default defineComponent({
+    components: {
+      Button,
+    },
+  });
+</script>
+

\u6CE8\u610F

  • \u5982\u679C\u7EC4\u4EF6\u6709\u4F9D\u8D56\u6837\u5F0F\uFF0C\u5219\u9700\u8981\u518D\u5F15\u5165\u6837\u5F0F\u6587\u4EF6
__VP_STATIC_END__`,12),o=[e];function c(l,u,i,k,r,d){return s(),a("div",null,o)}var f=n(p,[["render",c]]);export{h as __pageData,f as default}; diff --git a/assets/guide_menu.md.acdbde02.js b/assets/guide_menu.md.acdbde02.js new file mode 100644 index 00000000..51da82b0 --- /dev/null +++ b/assets/guide_menu.md.acdbde02.js @@ -0,0 +1,59 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"\u83DC\u5355","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u83DC\u5355\u9879\u7C7B\u578B","slug":"\u83DC\u5355\u9879\u7C7B\u578B"},{"level":2,"title":"\u83DC\u5355\u6A21\u5757","slug":"\u83DC\u5355\u6A21\u5757"},{"level":2,"title":"\u65B0\u589E\u83DC\u5355","slug":"\u65B0\u589E\u83DC\u5355"},{"level":2,"title":"\u83DC\u5355\u6392\u5E8F","slug":"\u83DC\u5355\u6392\u5E8F"}],"relativePath":"guide/menu.md","lastUpdated":1694442156385}',p={},o=t(`

\u83DC\u5355

\u9879\u76EE\u83DC\u5355\u914D\u7F6E\u5B58\u653E\u4E8E src/router/menus \u4E0B\u9762

\u63D0\u793A

\u83DC\u5355\u5FC5\u987B\u548C\u8DEF\u7531\u5339\u914D\u624D\u80FD\u663E\u793A

\u83DC\u5355\u9879\u7C7B\u578B

export interface Menu {
+  //  \u83DC\u5355\u540D
+  name: string;
+  // \u83DC\u5355\u56FE\u6807,\u5982\u679C\u6CA1\u6709\uFF0C\u5219\u4F1A\u5C1D\u8BD5\u4F7F\u7528route.meta.icon
+  icon?: string;
+  // \u83DC\u5355\u8DEF\u5F84
+  path: string;
+  // \u662F\u5426\u7981\u7528
+  disabled?: boolean;
+  // \u5B50\u83DC\u5355
+  children?: Menu[];
+  // \u83DC\u5355\u6807\u7B7E\u8BBE\u7F6E
+  tag: {
+    // \u4E3Atrue\u5219\u663E\u793A\u5C0F\u5706\u70B9
+    dot: boolean;
+    // \u5185\u5BB9
+    content: string';
+    // \u7C7B\u578B
+    type: 'error' | 'primary' | 'warn' | 'success';
+  };
+  // \u662F\u5426\u9690\u85CF\u83DC\u5355
+  hideMenu?: boolean;
+}
+

\u83DC\u5355\u6A21\u5757

\u4E00\u4E2A\u83DC\u5355\u6587\u4EF6\u4F1A\u88AB\u5F53\u4F5C\u4E00\u4E2A\u6A21\u5757

\u63D0\u793A

children \u7684 path \u5B57\u6BB5\u4E0D\u9700\u8981\u4EE5/\u5F00\u5934

import type { MenuModule } from '/@/router/types';
+import { t } from '/@/hooks/web/useI18n';
+const menu: MenuModule = {
+  orderNo: 10,
+  menu: {
+    name: t('routes.dashboard.dashboard'),
+    path: '/dashboard',
+
+    children: [
+      {
+        path: 'analysis',
+        name: t('routes.dashboard.analysis'),
+      },
+      {
+        path: 'workbench',
+        name: t('routes.dashboard.workbench'),
+      },
+    ],
+  },
+};
+export default menu;
+

\u4EE5\u4E0A\u6A21\u5757\u4F1A\u8F6C\u5316\u6210\u4EE5\u4E0B\u7ED3\u6784

[
+  path: '/dashboard',
+  name: t('routes.dashboard.dashboard'),
+  children: [
+    {
+      path: 'dashboard/analysis',
+      name: t('routes.dashboard.analysis'),
+    },
+    {
+      path: 'dashboard/workbench',
+      name: t('routes.dashboard.workbench'),
+    },
+  ],
+]
+

\u65B0\u589E\u83DC\u5355

\u76F4\u63A5\u5728 src/router/routes/modules \u5185\u65B0\u589E\u4E00\u4E2A\u6A21\u5757\u6587\u4EF6\u5373\u53EF\u3002

\u4E0D\u9700\u8981\u624B\u52A8\u5F15\u5165\uFF0C\u653E\u5728src/router/routes/modules \u5185\u7684\u6587\u4EF6\u4F1A\u81EA\u52A8\u88AB\u52A0\u8F7D\u3002

\u83DC\u5355\u6392\u5E8F

\u5728\u83DC\u5355\u6A21\u5757\u5185\uFF0C\u8BBE\u7F6E orderNo \u53D8\u91CF\uFF0C\u6570\u503C\u8D8A\u5927\uFF0C\u6392\u5E8F\u8D8A\u9760\u540E

`,16),e=[o];function c(r,l,u,i,k,d){return a(),s("div",null,e)}var b=n(p,[["render",c]]);export{m as __pageData,b as default}; diff --git a/assets/guide_menu.md.acdbde02.lean.js b/assets/guide_menu.md.acdbde02.lean.js new file mode 100644 index 00000000..428dcd2f --- /dev/null +++ b/assets/guide_menu.md.acdbde02.lean.js @@ -0,0 +1,59 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const m='{"title":"\u83DC\u5355","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u83DC\u5355\u9879\u7C7B\u578B","slug":"\u83DC\u5355\u9879\u7C7B\u578B"},{"level":2,"title":"\u83DC\u5355\u6A21\u5757","slug":"\u83DC\u5355\u6A21\u5757"},{"level":2,"title":"\u65B0\u589E\u83DC\u5355","slug":"\u65B0\u589E\u83DC\u5355"},{"level":2,"title":"\u83DC\u5355\u6392\u5E8F","slug":"\u83DC\u5355\u6392\u5E8F"}],"relativePath":"guide/menu.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

\u83DC\u5355

\u9879\u76EE\u83DC\u5355\u914D\u7F6E\u5B58\u653E\u4E8E src/router/menus \u4E0B\u9762

\u63D0\u793A

\u83DC\u5355\u5FC5\u987B\u548C\u8DEF\u7531\u5339\u914D\u624D\u80FD\u663E\u793A

\u83DC\u5355\u9879\u7C7B\u578B

export interface Menu {
+  //  \u83DC\u5355\u540D
+  name: string;
+  // \u83DC\u5355\u56FE\u6807,\u5982\u679C\u6CA1\u6709\uFF0C\u5219\u4F1A\u5C1D\u8BD5\u4F7F\u7528route.meta.icon
+  icon?: string;
+  // \u83DC\u5355\u8DEF\u5F84
+  path: string;
+  // \u662F\u5426\u7981\u7528
+  disabled?: boolean;
+  // \u5B50\u83DC\u5355
+  children?: Menu[];
+  // \u83DC\u5355\u6807\u7B7E\u8BBE\u7F6E
+  tag: {
+    // \u4E3Atrue\u5219\u663E\u793A\u5C0F\u5706\u70B9
+    dot: boolean;
+    // \u5185\u5BB9
+    content: string';
+    // \u7C7B\u578B
+    type: 'error' | 'primary' | 'warn' | 'success';
+  };
+  // \u662F\u5426\u9690\u85CF\u83DC\u5355
+  hideMenu?: boolean;
+}
+

\u83DC\u5355\u6A21\u5757

\u4E00\u4E2A\u83DC\u5355\u6587\u4EF6\u4F1A\u88AB\u5F53\u4F5C\u4E00\u4E2A\u6A21\u5757

\u63D0\u793A

children \u7684 path \u5B57\u6BB5\u4E0D\u9700\u8981\u4EE5/\u5F00\u5934

import type { MenuModule } from '/@/router/types';
+import { t } from '/@/hooks/web/useI18n';
+const menu: MenuModule = {
+  orderNo: 10,
+  menu: {
+    name: t('routes.dashboard.dashboard'),
+    path: '/dashboard',
+
+    children: [
+      {
+        path: 'analysis',
+        name: t('routes.dashboard.analysis'),
+      },
+      {
+        path: 'workbench',
+        name: t('routes.dashboard.workbench'),
+      },
+    ],
+  },
+};
+export default menu;
+

\u4EE5\u4E0A\u6A21\u5757\u4F1A\u8F6C\u5316\u6210\u4EE5\u4E0B\u7ED3\u6784

[
+  path: '/dashboard',
+  name: t('routes.dashboard.dashboard'),
+  children: [
+    {
+      path: 'dashboard/analysis',
+      name: t('routes.dashboard.analysis'),
+    },
+    {
+      path: 'dashboard/workbench',
+      name: t('routes.dashboard.workbench'),
+    },
+  ],
+]
+

\u65B0\u589E\u83DC\u5355

\u76F4\u63A5\u5728 src/router/routes/modules \u5185\u65B0\u589E\u4E00\u4E2A\u6A21\u5757\u6587\u4EF6\u5373\u53EF\u3002

\u4E0D\u9700\u8981\u624B\u52A8\u5F15\u5165\uFF0C\u653E\u5728src/router/routes/modules \u5185\u7684\u6587\u4EF6\u4F1A\u81EA\u52A8\u88AB\u52A0\u8F7D\u3002

\u83DC\u5355\u6392\u5E8F

\u5728\u83DC\u5355\u6A21\u5757\u5185\uFF0C\u8BBE\u7F6E orderNo \u53D8\u91CF\uFF0C\u6570\u503C\u8D8A\u5927\uFF0C\u6392\u5E8F\u8D8A\u9760\u540E

__VP_STATIC_END__`,16),e=[o];function c(r,l,u,i,k,d){return a(),s("div",null,e)}var b=n(p,[["render",c]]);export{m as __pageData,b as default}; diff --git a/assets/guide_mock.md.a486b33a.js b/assets/guide_mock.md.a486b33a.js new file mode 100644 index 00000000..39f9f35b --- /dev/null +++ b/assets/guide_mock.md.a486b33a.js @@ -0,0 +1,413 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"\u6570\u636E mock&\u8054\u8C03","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u5F00\u53D1\u73AF\u5883","slug":"\u5F00\u53D1\u73AF\u5883"},{"level":3,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":3,"title":"\u8DE8\u57DF\u5904\u7406","slug":"\u8DE8\u57DF\u5904\u7406"},{"level":3,"title":"\u6CA1\u6709\u8DE8\u57DF\u65F6\u7684\u914D\u7F6E","slug":"\u6CA1\u6709\u8DE8\u57DF\u65F6\u7684\u914D\u7F6E"},{"level":3,"title":"\u8DE8\u57DF\u539F\u7406\u89E3\u6790","slug":"\u8DE8\u57DF\u539F\u7406\u89E3\u6790"},{"level":2,"title":"\u751F\u4EA7\u73AF\u5883","slug":"\u751F\u4EA7\u73AF\u5883"},{"level":2,"title":"\u63A5\u53E3\u8BF7\u6C42","slug":"\u63A5\u53E3\u8BF7\u6C42"},{"level":2,"title":"axios \u914D\u7F6E","slug":"axios-\u914D\u7F6E"},{"level":3,"title":"index.ts \u914D\u7F6E\u8BF4\u660E","slug":"index-ts-\u914D\u7F6E\u8BF4\u660E"},{"level":3,"title":"\u66F4\u6539\u53C2\u6570\u683C\u5F0F","slug":"\u66F4\u6539\u53C2\u6570\u683C\u5F0F"},{"level":3,"title":"\u591A\u4E2A\u63A5\u53E3\u5730\u5740","slug":"\u591A\u4E2A\u63A5\u53E3\u5730\u5740"},{"level":3,"title":"\u5220\u9664\u8BF7\u6C42 URL \u643A\u5E26\u7684\u65F6\u95F4\u6233\u53C2\u6570","slug":"\u5220\u9664\u8BF7\u6C42-url-\u643A\u5E26\u7684\u65F6\u95F4\u6233\u53C2\u6570"},{"level":2,"title":"Mock \u670D\u52A1","slug":"mock-\u670D\u52A1"},{"level":3,"title":"\u672C\u5730 Mock","slug":"\u672C\u5730-mock"},{"level":3,"title":"\u7EBF\u4E0A mock","slug":"\u7EBF\u4E0A-mock"}],"relativePath":"guide/mock.md","lastUpdated":1694442156385}',p={},o=t(`

\u6570\u636E mock&\u8054\u8C03

\u5F00\u53D1\u73AF\u5883

\u5982\u679C\u524D\u7AEF\u5E94\u7528\u548C\u540E\u7AEF\u63A5\u53E3\u670D\u52A1\u5668\u6CA1\u6709\u8FD0\u884C\u5728\u540C\u4E00\u4E2A\u4E3B\u673A\u4E0A\uFF0C\u4F60\u9700\u8981\u5728\u5F00\u53D1\u73AF\u5883\u4E0B\u5C06\u63A5\u53E3\u8BF7\u6C42\u4EE3\u7406\u5230\u63A5\u53E3\u670D\u52A1\u5668\u3002

\u5982\u679C\u662F\u540C\u4E00\u4E2A\u4E3B\u673A\uFF0C\u53EF\u4EE5\u76F4\u63A5\u8BF7\u6C42\u5177\u4F53\u7684\u63A5\u53E3\u5730\u5740\u3002

\u914D\u7F6E

\u5F00\u53D1\u73AF\u5883\u65F6\u5019\uFF0C\u63A5\u53E3\u5730\u5740\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B

.env.development \u6587\u4EF6\u914D\u7F6E

# vite \u672C\u5730\u8DE8\u57DF\u4EE3\u7406
+VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+# \u63A5\u53E3\u5730\u5740
+VITE_GLOB_API_URL=/api
+

TIP

  • .env \u6587\u4EF6\u4E2D\u7684\u5B57\u6BB5\u5982\u679C\u662F\u5B57\u7B26\u4E32\uFF0C\u5219\u65E0\u9700\u52A0\u5F15\u53F7\uFF0C\u9ED8\u8BA4\u5168\u90E8\u4E3A\u5B57\u7B26\u4E32
  • VITE_PROXY \u4E0D\u80FD\u6362\u884C

\u8DE8\u57DF\u5904\u7406

\u5982\u679C\u4F60\u5728 src/api/ \u4E0B\u9762\u7684\u63A5\u53E3\u4E3A\u4E0B\u65B9\u4EE3\u7801\uFF0C\u4E14 .env.development \u6587\u4EF6\u914D\u7F6E\u5982\u4E0B\u6CE8\u91CA\uFF0C\u5219\u5728\u63A7\u5236\u53F0\u770B\u5230\u7684\u5730\u5740\u4E3A http://localhost:3100/basic-api/login\u3002

\u7531\u4E8E /basic-api \u5339\u914D\u5230\u4E86\u8BBE\u7F6E\u7684 VITE_PROXY\uFF0C\u6240\u4EE5\u4E0A\u65B9\u5B9E\u9645\u662F\u8BF7\u6C42 http://localhost:3000/login\uFF0C\u8FD9\u6837\u540C\u65F6\u4E5F\u89E3\u51B3\u4E86\u8DE8\u57DF\u95EE\u9898\u3002\uFF083100\u4E3A\u9879\u76EE\u7AEF\u53E3\u53F7\uFF0Chttp://localhost:3000\u4E3APROXY\u4EE3\u7406\u7684\u76EE\u6807\u5730\u5740\uFF09

// .env.development
+// VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+// VITE_GLOB_API_URL=/basic-api
+
+enum Api {
+  Login = '/login',
+}
+
+/**
+ * @description: \u7528\u6237\u767B\u9646
+ */
+export function loginApi(params: LoginParams) {
+  return http.request<LoginResultModel>({
+    url: Api.Login,
+    method: 'POST',
+    params,
+  });
+}
+

\u6CA1\u6709\u8DE8\u57DF\u65F6\u7684\u914D\u7F6E

\u5982\u679C\u6CA1\u6709\u8DE8\u57DF\u95EE\u9898\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5FFD\u7565 VITE_PROXY \u914D\u7F6E\uFF0C\u76F4\u63A5\u5C06\u63A5\u53E3\u5730\u5740\u8BBE\u7F6E\u5728 VITE_GLOB_API_URL

# \u4F8B\u5982\u63A5\u53E3\u5730\u5740\u4E3A http://localhost:3000 \u5219
+VITE_GLOB_API_URL=http://localhost:3000
+

\u5982\u679C\u6709\u8DE8\u57DF\u95EE\u9898\uFF0C\u5C06 VITE_GLOB_API_URL \u8BBE\u7F6E\u4E3A\u8DDF VITE_PROXY \u5185\u5176\u4E2D\u4E00\u4E2A\u6570\u7EC4\u7684\u7B2C\u4E00\u4E2A\u9879\u4E00\u81F4\u7684\u503C\u5373\u53EF\u3002

\u4E0B\u65B9\u7684\u63A5\u53E3\u5730\u5740\u8BBE\u7F6E\u4E3A /basic-api\uFF0C\u5F53\u8BF7\u6C42\u53D1\u51FA\u7684\u65F6\u5019\u4F1A\u7ECF\u8FC7 Vite \u7684 proxy \u4EE3\u7406\uFF0C\u5339\u914D\u5230\u4E86\u6211\u4EEC\u8BBE\u7F6E\u7684 VITE_PROXY \u89C4\u5219\uFF0C\u5C06 /basic-api \u8F6C\u5316\u4E3A http://localhost:3000 \u8FDB\u884C\u8BF7\u6C42

# \u4F8B\u5982\u63A5\u53E3\u5730\u5740\u4E3A http://localhost:3000 \u5219
+VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+# \u63A5\u53E3\u5730\u5740
+VITE_GLOB_API_URL=/basic-api
+

\u8DE8\u57DF\u539F\u7406\u89E3\u6790

\u5728 vite.config.ts \u914D\u7F6E\u6587\u4EF6\u4E2D\uFF0C\u63D0\u4F9B\u4E86 server \u7684 proxy \u529F\u80FD\uFF0C\u7528\u4E8E\u4EE3\u7406 API \u8BF7\u6C42\u3002

server: {
+  proxy: {
+    "/basic-api":{
+      target: 'http://localhost:3000',
+      changeOrigin: true,
+      ws: true,
+      rewrite: (path) => path.replace(new RegExp(\`^/basic-api\`), ''),
+    }
+  },
+},
+

\u6CE8\u610F

\u4ECE\u6D4F\u89C8\u5668\u63A7\u5236\u53F0\u7684 Network \u770B\uFF0C\u8BF7\u6C42\u662F http://localhost:3000/basic-api/xxx\uFF0C\u8FD9\u662F\u56E0\u4E3A proxy \u914D\u7F6E\u4E0D\u4F1A\u6539\u53D8\u672C\u5730\u8BF7\u6C42\u7684 url\u3002

\u751F\u4EA7\u73AF\u5883

\u751F\u4EA7\u73AF\u5883\u63A5\u53E3\u5730\u5740\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B .env.production \u6587\u4EF6\u914D\u7F6E\u3002

\u751F\u4EA7\u73AF\u5883\u63A5\u53E3\u5730\u5740\u503C\u9700\u8981\u4FEE\u6539 VITE_GLOB_API_URL\uFF0C\u5982\u679C\u51FA\u73B0\u8DE8\u57DF\u95EE\u9898\uFF0C\u53EF\u4EE5\u4F7F\u7528 nginx \u6216\u8005\u540E\u53F0\u5F00\u542F cors \u8FDB\u884C\u5904\u7406

\u6253\u5305\u540E\u5982\u4F55\u8FDB\u884C\u5730\u5740\u4FEE\u6539?

VITE_GLOB_* \u5F00\u5934\u7684\u53D8\u91CF\u4F1A\u5728\u6253\u5305\u7684\u65F6\u5019\u6CE8\u5165 _app.config.js \u6587\u4EF6\u5185\u3002

\u5728 dist/_app.config.js \u4FEE\u6539\u76F8\u5E94\u7684\u63A5\u53E3\u5730\u5740\u540E\u5237\u65B0\u9875\u9762\u5373\u53EF\uFF0C\u4E0D\u9700\u8981\u5728\u6839\u636E\u4E0D\u540C\u73AF\u5883\u6253\u5305\u591A\u6B21\uFF0C\u4E00\u6B21\u6253\u5305\u53EF\u4EE5\u7528\u4E8E\u591A\u4E2A\u4E0D\u540C\u63A5\u53E3\u73AF\u5883\u7684\u90E8\u7F72\u3002

\u63A5\u53E3\u8BF7\u6C42

\u5728 vue-vben-admin \u4E2D:

  1. \u9875\u9762\u4EA4\u4E92\u64CD\u4F5C\uFF1B
  2. \u8C03\u7528\u7EDF\u4E00\u7BA1\u7406\u7684 api \u8BF7\u6C42\u51FD\u6570\uFF1B
  3. \u4F7F\u7528\u5C01\u88C5\u7684 axios.ts \u53D1\u9001\u8BF7\u6C42\uFF1B
  4. \u83B7\u53D6\u670D\u52A1\u7AEF\u8FD4\u56DE\u6570\u636E
  5. \u66F4\u65B0 data\uFF1B

\u63A5\u53E3\u7EDF\u4E00\u5B58\u653E\u4E8E src/api/ \u4E0B\u9762\u7BA1\u7406

\u4EE5\u767B\u9646\u63A5\u53E3\u4E3A\u4F8B:

\u5728 src/api/ \u5185\u65B0\u5EFA\u6A21\u5757\u6587\u4EF6\uFF0C\u5176\u4E2D\u53C2\u6570\u4E0E\u8FD4\u56DE\u503C\u6700\u597D\u5B9A\u4E49\u4E00\u4E0B\u7C7B\u578B\uFF0C\u65B9\u4FBF\u6821\u9A8C\u3002\u867D\u7136\u9EBB\u70E6\uFF0C\u4F46\u662F\u540E\u7EED\u7EF4\u62A4\u5B57\u6BB5\u5F88\u65B9\u4FBF\u3002

TIP

\u7C7B\u578B\u5B9A\u4E49\u6587\u4EF6\u53EF\u4EE5\u62BD\u53D6\u51FA\u53BB\u7EDF\u4E00\u7BA1\u7406\uFF0C\u5177\u4F53\u53C2\u8003\u9879\u76EE

import { defHttp } from '/@/utils/http/axios';
+import { LoginParams, LoginResultModel } from './model/userModel';
+
+enum Api {
+  Login = '/login',
+}
+
+export function loginApi(params: LoginParams) {
+  return defHttp.request<LoginResultModel>({
+    url: Api.Login,
+    method: 'POST',
+    params,
+  });
+}
+

axios \u914D\u7F6E

axios \u8BF7\u6C42\u5C01\u88C5\u5B58\u653E\u4E8E src/utils/http/axios \u6587\u4EF6\u5939\u5185\u90E8

\u9664 index.ts \u6587\u4EF6\u5185\u5BB9\u9700\u8981\u6839\u636E\u9879\u76EE\u81EA\u884C\u4FEE\u6539\u5916\uFF0C\u5176\u4F59\u6587\u4EF6\u65E0\u9700\u4FEE\u6539


+\u251C\u2500\u2500 Axios.ts // axios\u5B9E\u4F8B
+\u251C\u2500\u2500 axiosCancel.ts // axiosCancel\u5B9E\u4F8B\uFF0C\u53D6\u6D88\u91CD\u590D\u8BF7\u6C42
+\u251C\u2500\u2500 axiosTransform.ts // \u6570\u636E\u8F6C\u6362\u7C7B
+\u251C\u2500\u2500 checkStatus.ts // \u8FD4\u56DE\u72B6\u6001\u503C\u6821\u9A8C
+\u251C\u2500\u2500 index.ts // \u63A5\u53E3\u8FD4\u56DE\u7EDF\u4E00\u5904\u7406
+
+

index.ts \u914D\u7F6E\u8BF4\u660E

const axios = new VAxios({
+  // \u8BA4\u8BC1\u65B9\u6848\uFF0C\u4F8B\u5982: Bearer
+  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
+  authenticationScheme: '',
+  // \u63A5\u53E3\u8D85\u65F6\u65F6\u95F4 \u5355\u4F4D\u6BEB\u79D2
+  timeout: 10 * 1000,
+  // \u63A5\u53E3\u53EF\u80FD\u4F1A\u6709\u901A\u7528\u7684\u5730\u5740\u90E8\u5206\uFF0C\u53EF\u4EE5\u7EDF\u4E00\u62BD\u53D6\u51FA\u6765
+  prefixUrl: prefix,
+  headers: { 'Content-Type': ContentTypeEnum.JSON },
+  // \u6570\u636E\u5904\u7406\u65B9\u5F0F\uFF0C\u89C1\u4E0B\u65B9\u8BF4\u660E
+  transform,
+  // \u914D\u7F6E\u9879\uFF0C\u4E0B\u9762\u7684\u9009\u9879\u90FD\u53EF\u4EE5\u5728\u72EC\u7ACB\u7684\u63A5\u53E3\u8BF7\u6C42\u4E2D\u8986\u76D6
+  requestOptions: {
+    // \u9ED8\u8BA4\u5C06prefix \u6DFB\u52A0\u5230url
+    joinPrefix: true,
+    // \u662F\u5426\u8FD4\u56DE\u539F\u751F\u54CD\u5E94\u5934 \u6BD4\u5982\uFF1A\u9700\u8981\u83B7\u53D6\u54CD\u5E94\u5934\u65F6\u4F7F\u7528\u8BE5\u5C5E\u6027
+    isReturnNativeResponse: false,
+    // \u9700\u8981\u5BF9\u8FD4\u56DE\u6570\u636E\u8FDB\u884C\u5904\u7406
+    isTransformRequestResult: true,
+    // post\u8BF7\u6C42\u7684\u65F6\u5019\u6DFB\u52A0\u53C2\u6570\u5230url
+    joinParamsToUrl: false,
+    // \u683C\u5F0F\u5316\u63D0\u4EA4\u53C2\u6570\u65F6\u95F4
+    formatDate: true,
+    // \u6D88\u606F\u63D0\u793A\u7C7B\u578B
+    errorMessageMode: 'message',
+    // \u63A5\u53E3\u5730\u5740
+    apiUrl: globSetting.apiUrl,
+    //  \u662F\u5426\u52A0\u5165\u65F6\u95F4\u6233
+    joinTime: true,
+    // \u5FFD\u7565\u91CD\u590D\u8BF7\u6C42
+    ignoreCancelToken: true,
+  },
+});
+

transform \u6570\u636E\u5904\u7406\u8BF4\u660E

\u7C7B\u578B\u5B9A\u4E49\uFF0C\u89C1 axiosTransform.ts \u6587\u4EF6

export abstract class AxiosTransform {
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u524D\u5904\u7406\u914D\u7F6E
+   */
+  beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig;
+
+  /**
+   * @description: \u8BF7\u6C42\u6210\u529F\u5904\u7406
+   */
+  transformRequestData?: (res: AxiosResponse<Result>, options: RequestOptions) => any;
+
+  /**
+   * @description: \u8BF7\u6C42\u5931\u8D25\u5904\u7406
+   */
+  requestCatch?: (e: Error) => Promise<any>;
+
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u524D\u7684\u62E6\u622A\u5668
+   */
+  requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig;
+
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u540E\u7684\u62E6\u622A\u5668
+   */
+  responseInterceptors?: (res: AxiosResponse<any>) => AxiosResponse<any>;
+
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u524D\u7684\u62E6\u622A\u5668\u9519\u8BEF\u5904\u7406
+   */
+  requestInterceptorsCatch?: (error: Error) => void;
+
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u540E\u7684\u62E6\u622A\u5668\u9519\u8BEF\u5904\u7406
+   */
+  responseInterceptorsCatch?: (error: Error) => void;
+}
+
+
+

\u9879\u76EE\u9ED8\u8BA4 transform \u5904\u7406\u903B\u8F91\uFF0C\u53EF\u4EE5\u6839\u636E\u5404\u81EA\u9879\u76EE\u8FDB\u884C\u5904\u7406\u3002\u4E00\u822C\u9700\u8981\u66F4\u6539\u7684\u90E8\u5206\u4E3A\u4E0B\u65B9\u4EE3\u7801\uFF0C\u89C1\u4EE3\u7801\u6CE8\u91CA\u8BF4\u660E

/**
+ * @description: \u6570\u636E\u5904\u7406\uFF0C\u65B9\u4FBF\u533A\u5206\u591A\u79CD\u5904\u7406\u65B9\u5F0F
+ */
+const transform: AxiosTransform = {
+  /**
+   * @description: \u5904\u7406\u8BF7\u6C42\u6570\u636E\u3002\u5982\u679C\u6570\u636E\u4E0D\u662F\u9884\u671F\u683C\u5F0F\uFF0C\u53EF\u76F4\u63A5\u629B\u51FA\u9519\u8BEF
+   */
+  transformRequestHook: (res: AxiosResponse<Result>, options: RequestOptions) => {
+    const { t } = useI18n();
+    const { isTransformResponse, isReturnNativeResponse } = options;
+    // \u662F\u5426\u8FD4\u56DE\u539F\u751F\u54CD\u5E94\u5934 \u6BD4\u5982\uFF1A\u9700\u8981\u83B7\u53D6\u54CD\u5E94\u5934\u65F6\u4F7F\u7528\u8BE5\u5C5E\u6027
+    if (isReturnNativeResponse) {
+      return res;
+    }
+    // \u4E0D\u8FDB\u884C\u4EFB\u4F55\u5904\u7406\uFF0C\u76F4\u63A5\u8FD4\u56DE
+    // \u7528\u4E8E\u9875\u9762\u4EE3\u7801\u53EF\u80FD\u9700\u8981\u76F4\u63A5\u83B7\u53D6code\uFF0Cdata\uFF0Cmessage\u8FD9\u4E9B\u4FE1\u606F\u65F6\u5F00\u542F
+    if (!isTransformResponse) {
+      return res.data;
+    }
+    // \u9519\u8BEF\u7684\u65F6\u5019\u8FD4\u56DE
+
+    const { data } = res;
+    if (!data) {
+      // return '[HTTP] Request has no return value';
+      throw new Error(t('sys.api.apiRequestFailed'));
+    }
+    //  \u8FD9\u91CC code\uFF0Cresult\uFF0Cmessage\u4E3A \u540E\u53F0\u7EDF\u4E00\u7684\u5B57\u6BB5\uFF0C\u9700\u8981\u5728 types.ts\u5185\u4FEE\u6539\u4E3A\u9879\u76EE\u81EA\u5DF1\u7684\u63A5\u53E3\u8FD4\u56DE\u683C\u5F0F
+    const { code, result, message } = data;
+
+    // \u8FD9\u91CC\u903B\u8F91\u53EF\u4EE5\u6839\u636E\u9879\u76EE\u8FDB\u884C\u4FEE\u6539
+    const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
+    if (hasSuccess) {
+      return result;
+    }
+
+    // \u5728\u6B64\u5904\u6839\u636E\u81EA\u5DF1\u9879\u76EE\u7684\u5B9E\u9645\u60C5\u51B5\u5BF9\u4E0D\u540C\u7684code\u6267\u884C\u4E0D\u540C\u7684\u64CD\u4F5C
+    // \u5982\u679C\u4E0D\u5E0C\u671B\u4E2D\u65AD\u5F53\u524D\u8BF7\u6C42\uFF0C\u8BF7return\u6570\u636E\uFF0C\u5426\u5219\u76F4\u63A5\u629B\u51FA\u5F02\u5E38\u5373\u53EF
+    let timeoutMsg = '';
+    switch (code) {
+      case ResultEnum.TIMEOUT:
+        timeoutMsg = t('sys.api.timeoutMessage');
+      default:
+        if (message) {
+          timeoutMsg = message;
+        }
+    }
+
+    // errorMessageMode=\u2018modal\u2019\u7684\u65F6\u5019\u4F1A\u663E\u793Amodal\u9519\u8BEF\u5F39\u7A97\uFF0C\u800C\u4E0D\u662F\u6D88\u606F\u63D0\u793A\uFF0C\u7528\u4E8E\u4E00\u4E9B\u6BD4\u8F83\u91CD\u8981\u7684\u9519\u8BEF
+    // errorMessageMode='none' \u4E00\u822C\u662F\u8C03\u7528\u65F6\u660E\u786E\u8868\u793A\u4E0D\u5E0C\u671B\u81EA\u52A8\u5F39\u51FA\u9519\u8BEF\u63D0\u793A
+    if (options.errorMessageMode === 'modal') {
+      createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg });
+    } else if (options.errorMessageMode === 'message') {
+      createMessage.error(timeoutMsg);
+    }
+
+    throw new Error(timeoutMsg || t('sys.api.apiRequestFailed'));
+  },
+
+  // \u8BF7\u6C42\u4E4B\u524D\u5904\u7406config
+  beforeRequestHook: (config, options) => {
+    const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options;
+
+    if (joinPrefix) {
+      config.url = \`\${urlPrefix}\${config.url}\`;
+    }
+
+    if (apiUrl && isString(apiUrl)) {
+      config.url = \`\${apiUrl}\${config.url}\`;
+    }
+    const params = config.params || {};
+    if (config.method?.toUpperCase() === RequestEnum.GET) {
+      if (!isString(params)) {
+        // \u7ED9 get \u8BF7\u6C42\u52A0\u4E0A\u65F6\u95F4\u6233\u53C2\u6570\uFF0C\u907F\u514D\u4ECE\u7F13\u5B58\u4E2D\u62FF\u6570\u636E\u3002
+        config.params = Object.assign(params || {}, joinTimestamp(joinTime, false));
+      } else {
+        // \u517C\u5BB9restful\u98CE\u683C
+        config.url = config.url + params + \`\${joinTimestamp(joinTime, true)}\`;
+        config.params = undefined;
+      }
+    } else {
+      if (!isString(params)) {
+        formatDate && formatRequestDate(params);
+        config.data = params;
+        config.params = undefined;
+        if (joinParamsToUrl) {
+          config.url = setObjToUrlParams(config.url as string, config.data);
+        }
+      } else {
+        // \u517C\u5BB9restful\u98CE\u683C
+        config.url = config.url + params;
+        config.params = undefined;
+      }
+    }
+    return config;
+  },
+
+  /**
+   * @description: \u8BF7\u6C42\u62E6\u622A\u5668\u5904\u7406
+   */
+  requestInterceptors: (config, options) => {
+    // \u8BF7\u6C42\u4E4B\u524D\u5904\u7406config
+    const token = getToken();
+    if (token) {
+      // jwt token
+      config.headers.Authorization = options.authenticationScheme
+        ? \`\${options.authenticationScheme} \${token}\`
+        : token;
+    }
+    return config;
+  },
+
+  /**
+   * @description: \u54CD\u5E94\u62E6\u622A\u5668\u5904\u7406
+   */
+  responseInterceptors: (res: AxiosResponse<any>) => {
+    return res;
+  },
+
+  /**
+   * @description: \u54CD\u5E94\u9519\u8BEF\u5904\u7406
+   */
+  responseInterceptorsCatch: (error: any) => {
+    const { t } = useI18n();
+    const errorLogStore = useErrorLogStoreWithOut();
+    errorLogStore.addAjaxErrorInfo(error);
+    const { response, code, message, config } = error || {};
+    const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
+    const msg: string = response?.data?.error?.message ?? '';
+    const err: string = error?.toString?.() ?? '';
+    let errMessage = '';
+
+    try {
+      if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
+        errMessage = t('sys.api.apiTimeoutMessage');
+      }
+      if (err?.includes('Network Error')) {
+        errMessage = t('sys.api.networkExceptionMsg');
+      }
+
+      if (errMessage) {
+        if (errorMessageMode === 'modal') {
+          createErrorModal({ title: t('sys.api.errorTip'), content: errMessage });
+        } else if (errorMessageMode === 'message') {
+          createMessage.error(errMessage);
+        }
+        return Promise.reject(error);
+      }
+    } catch (error) {
+      throw new Error(error);
+    }
+
+    checkStatus(error?.response?.status, msg, errorMessageMode);
+    return Promise.reject(error);
+  },
+};
+

\u66F4\u6539\u53C2\u6570\u683C\u5F0F

\u9879\u76EE\u63A5\u53E3\u9ED8\u8BA4\u4E3A Json \u53C2\u6570\u683C\u5F0F\uFF0C\u5373 headers: { 'Content-Type': ContentTypeEnum.JSON },

\u5982\u679C\u9700\u8981\u66F4\u6539\u4E3A form-data \u683C\u5F0F\uFF0C\u66F4\u6539 headers \u7684 'Content-Type \u4E3A ContentTypeEnum.FORM_URLENCODED \u5373\u53EF

\u591A\u4E2A\u63A5\u53E3\u5730\u5740

\u5F53\u9879\u76EE\u4E2D\u9700\u8981\u7528\u5230\u591A\u4E2A\u63A5\u53E3\u5730\u5740\u65F6, \u53EF\u4EE5\u5728 src/utils/http/axios/index.ts \u5BFC\u51FA\u591A\u4E2A axios \u5B9E\u4F8B

// \u76EE\u524D\u53EA\u5BFC\u51FA\u4E00\u4E2A\u9ED8\u8BA4\u5B9E\u4F8B\uFF0C\u63A5\u53E3\u5730\u5740\u5BF9\u5E94\u7684\u662F\u73AF\u5883\u53D8\u91CF\u4E2D\u7684 VITE_GLOB_API_URL \u63A5\u53E3\u5730\u5740
+export const defHttp = createAxios();
+
+// \u9700\u8981\u6709\u5176\u4ED6\u63A5\u53E3\u5730\u5740\u7684\u53EF\u4EE5\u5728\u540E\u9762\u6DFB\u52A0
+
+// other api url
+export const otherHttp = createAxios({
+  requestOptions: {
+    apiUrl: 'xxx',
+  },
+});
+

\u5220\u9664\u8BF7\u6C42 URL \u643A\u5E26\u7684\u65F6\u95F4\u6233\u53C2\u6570

\u5982\u679C\u4E0D\u9700\u8981 url \u4E0A\u9762\u9ED8\u8BA4\u643A\u5E26\u7684\u65F6\u95F4\u6233\u53C2\u6570 ?_t=xxx

const axios = new VAxios({
+  requestOptions: {
+    // \u662F\u5426\u52A0\u5165\u65F6\u95F4\u6233
+    joinTime: false,
+  },
+});
+

Mock \u670D\u52A1

Mock \u6570\u636E\u662F\u524D\u7AEF\u5F00\u53D1\u8FC7\u7A0B\u4E2D\u5FC5\u4E0D\u53EF\u5C11\u7684\u4E00\u73AF\uFF0C\u662F\u5206\u79BB\u524D\u540E\u7AEF\u5F00\u53D1\u7684\u5173\u952E\u94FE\u8DEF\u3002\u901A\u8FC7\u9884\u5148\u8DDF\u670D\u52A1\u5668\u7AEF\u7EA6\u5B9A\u597D\u7684\u63A5\u53E3\uFF0C\u6A21\u62DF\u8BF7\u6C42\u6570\u636E\u751A\u81F3\u903B\u8F91\uFF0C\u80FD\u591F\u8BA9\u524D\u7AEF\u5F00\u53D1\u72EC\u7ACB\u81EA\u4E3B\uFF0C\u4E0D\u4F1A\u88AB\u670D\u52A1\u7AEF\u7684\u5F00\u53D1\u8FDB\u7A0B\u6240\u963B\u585E\u3002

\u672C\u9879\u76EE\u4F7F\u7528 vite-plugin-mock \u6765\u8FDB\u884C mock \u6570\u636E\u5904\u7406\u3002\u9879\u76EE\u5185 mock \u670D\u52A1\u5206\u672C\u5730\u548C\u7EBF\u4E0A\u3002

\u672C\u5730 Mock

\u672C\u5730 mock \u91C7\u7528 Node.js \u4E2D\u95F4\u4EF6\u8FDB\u884C\u53C2\u6570\u62E6\u622A\uFF08\u4E0D\u91C7\u7528 mock.js \u7684\u539F\u56E0\u662F\u672C\u5730\u5F00\u53D1\u770B\u4E0D\u5230\u8BF7\u6C42\u53C2\u6570\u548C\u54CD\u5E94\u7ED3\u679C\uFF09\u3002

\u5982\u4F55\u65B0\u589E mock \u63A5\u53E3

\u5982\u679C\u4F60\u60F3\u6DFB\u52A0 mock \u6570\u636E\uFF0C\u53EA\u8981\u5728\u6839\u76EE\u5F55\u4E0B\u627E\u5230 mock \u6587\u4EF6\uFF0C\u6DFB\u52A0\u5BF9\u5E94\u7684\u63A5\u53E3\uFF0C\u5BF9\u5176\u8FDB\u884C\u62E6\u622A\u548C\u6A21\u62DF\u6570\u636E\u3002

\u5728 mock \u6587\u4EF6\u5939\u5185\u65B0\u5EFA\u6587\u4EF6

TIP

\u6587\u4EF6\u65B0\u589E\u540E\u4F1A\u81EA\u52A8\u66F4\u65B0\uFF0C\u4E0D\u9700\u8981\u624B\u52A8\u91CD\u542F\uFF0C\u53EF\u4EE5\u5728\u4EE3\u7801\u63A7\u5236\u53F0\u67E5\u770B\u65E5\u5FD7\u4FE1\u606F mock \u6587\u4EF6\u5939\u5185\u4F1A\u81EA\u52A8\u6CE8\u518C\uFF0C\u6392\u9664\u4EE5_\u5F00\u5934\u7684\u6587\u4EF6\u5939\u53CA\u6587\u4EF6

\u4F8B:

import { MockMethod } from 'vite-plugin-mock';
+import { resultPageSuccess } from '../_util';
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 60; index++) {
+    result.push({
+      id: \`\${index}\`,
+      beginTime: '@datetime',
+      endTime: '@datetime',
+      address: '@city()',
+      name: '@cname()',
+      'no|100000-10000000': 100000,
+      'status|1': ['\u6B63\u5E38', '\u542F\u7528', '\u505C\u7528'],
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/api/table/getDemoList',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];
+

TIP

mock \u7684\u503C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 mockjs \u7684\u8BED\u6CD5\u3002

\u63A5\u53E3\u683C\u5F0F

{
+  url: string; // mock \u63A5\u53E3\u5730\u5740
+  method?: MethodType; // \u8BF7\u6C42\u65B9\u5F0F
+  timeout?: number; // \u5EF6\u65F6\u65F6\u95F4
+  statusCode: number; // \u54CD\u5E94\u72B6\u6001\u7801
+  response: ((opt: { // \u54CD\u5E94\u7ED3\u679C
+      body: any;
+      query: any;
+  }) => any) | object;
+}
+

\u53C2\u6570\u83B7\u53D6

GET \u63A5\u53E3\uFF1A ({ query }) => { }

POST \u63A5\u53E3\uFF1A ({ body }) => { }

util \u8BF4\u660E

\u53EF\u5728 \u4EE3\u7801 \u4E2D\u67E5\u770B

TIP

util \u53EA\u4F5C\u4E3A\u670D\u52A1\u5904\u7406\u7ED3\u679C\u6570\u636E\u4F7F\u7528\u3002\u53EF\u4EE5\u4E0D\u7528\uFF0C\u5982\u9700\u4F7F\u7528\u53EF\u81EA\u884C\u5C01\u88C5\uFF0C\u9700\u8981\u5C06\u5BF9\u5E94\u7684\u5B57\u6BB5\u6539\u4E3A\u63A5\u53E3\u7684\u8FD4\u56DE\u7ED3\u6784

\u5339\u914D

\u5728 src/api \u4E0B\u9762\uFF0C\u5982\u679C\u63A5\u53E3\u5339\u914D\u5230 mock\uFF0C\u5219\u4F1A\u4F18\u5148\u4F7F\u7528 mock \u8FDB\u884C\u54CD\u5E94

import { defHttp } from '/@/utils/http/axios';
+import { LoginParams, LoginResultModel } from './model/userModel';
+
+enum Api {
+  Login = '/login',
+}
+
+/**
+ * @description: user login api
+ */
+export function loginApi(params: LoginParams) {
+  return defHttp.request<LoginResultModel>(
+    {
+      url: Api.Login,
+      method: 'POST',
+      params,
+    },
+    {
+      errorMessageMode: 'modal',
+    }
+  );
+}
+// \u4F1A\u5339\u914D\u5230\u4E0A\u65B9\u7684
+export default [
+  {
+    url: '/api/login',
+    timeout: 1000,
+    method: 'POST',
+    response: ({ body }) => {
+      return resultPageSuccess({});
+    },
+  },
+] as MockMethod[];
+

\u63A5\u53E3\u6709\u4E86\uFF0C\u5982\u4F55\u53BB\u6389 mock

\u5F53\u540E\u53F0\u63A5\u53E3\u5DF2\u7ECF\u5F00\u53D1\u5B8C\u6210\uFF0C\u53EA\u9700\u8981\u5C06\u76F8\u5E94\u7684 mock \u51FD\u6570\u53BB\u6389\u5373\u53EF\u3002

\u4EE5\u4E0A\u65B9\u63A5\u53E3\u4E3A\u4F8B\uFF0C\u5047\u5982\u540E\u53F0\u63A5\u53E3 login \u5DF2\u7ECF\u5F00\u53D1\u5B8C\u6210\uFF0C\u5219\u53EA\u9700\u8981\u5220\u9664/\u6CE8\u91CA\u6389\u4E0B\u65B9\u4EE3\u7801\u5373\u53EF

export default [
+  {
+    url: '/api/login',
+    timeout: 1000,
+    method: 'POST',
+    response: ({ body }) => {
+      return resultPageSuccess({});
+    },
+  },
+] as MockMethod[];
+

\u7EBF\u4E0A mock

\u7531\u4E8E\u8BE5\u9879\u76EE\u662F\u4E00\u4E2A\u5C55\u793A\u7C7B\u9879\u76EE\uFF0C\u7EBF\u4E0A\u4E5F\u662F\u7528 mock \u6570\u636E\uFF0C\u6240\u4EE5\u5728\u6253\u5305\u540E\u540C\u65F6\u4E5F\u96C6\u6210\u4E86 mock\u3002\u901A\u5E38\u9879\u76EE\u7EBF\u4E0A\u4E00\u822C\u4E3A\u6B63\u5F0F\u63A5\u53E3\u3002

\u9879\u76EE\u7EBF\u4E0A mock \u91C7\u7528\u7684\u662F mockjs \u8FDB\u884C mock \u6570\u636E\u6A21\u62DF\u3002

\u7EBF\u4E0A\u5982\u4F55\u5F00\u542F mock

\u6CE8\u610F

\u7EBF\u4E0A\u5F00\u542F mock \u53EA\u9002\u7528\u4E8E\u4E00\u4E9B\u7B80\u5355\u7684\u793A\u4F8B\u7F51\u7AD9\u53CA\u9884\u89C8\u7F51\u7AD9\u3002\u4E00\u5B9A\u4E0D\u8981\u5728\u6B63\u5F0F\u7684\u751F\u4EA7\u73AF\u5883\u5F00\u542F\uFF01\uFF01\uFF01

  1. \u4FEE\u6539 .env.production \u6587\u4EF6\u5185\u7684 VITE_USE_MOCK \u7684\u503C\u4E3A true
VITE_USE_MOCK = true;
+
  1. \u5728 mock/_createProductionServer.ts \u6587\u4EF6\u4E2D\u5F15\u5165\u9700\u8981\u7684 mock \u6587\u4EF6
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
+
+const modules = import.meta.globEager('./**/*.ts');
+
+const mockModules: any[] = [];
+Object.keys(modules).forEach((key) => {
+  if (key.includes('/_')) {
+    return;
+  }
+  mockModules.push(...modules[key].default);
+});
+
+export function setupProdMockServer() {
+  createProdMockServer(mockModules);
+}
+
  1. \u5728 build/vite/plugin/mock.ts \u91CC\u9762\u5F15\u5165
import { viteMockServe } from 'vite-plugin-mock';
+
+export function configMockPlugin(isBuild: boolean) {
+  return viteMockServe({
+    injectCode: \`
+      import { setupProdMockServer } from '../mock/_createProductionServer';
+
+      setupProdMockServer();
+      \`,
+  });
+}
+

\u4E3A\u4EC0\u4E48\u901A\u8FC7\u63D2\u4EF6\u6CE8\u5165\u4EE3\u7801\u800C\u4E0D\u662F\u76F4\u63A5\u5728 main.ts \u5185\u63D2\u5165

\u5728\u63D2\u4EF6\u5185\u901A\u8FC7 injectCode \u63D2\u5165\u4EE3\u7801\uFF0C\u65B9\u4FBF\u63A7\u5236 mockjs \u662F\u5426\u88AB\u6253\u5305\u5230\u6700\u7EC8\u4EE3\u7801\u5185\u3002\u5982\u679C\u5728 main.ts \u5185\u5224\u65AD\uFF0C\u5982\u679C\u5173\u95ED\u4E86 mock \u529F\u80FD\uFF0Cmockjs \u4E5F\u4F1A\u6253\u5305\u5230\u6784\u5EFA\u6587\u4EF6\u5185\uFF0C\u8FD9\u6837\u4F1A\u589E\u52A0\u6253\u5305\u4F53\u79EF\u3002

\u5230\u8FD9\u91CC\u7EBF\u4E0A mock \u5C31\u914D\u7F6E\u5B8C\u6210\u4E86\u3002\u7EBF\u4E0A\u4E0E\u672C\u5730\u5DEE\u5F02\u4E0D\u5927\uFF0C\u6BD4\u8F83\u5927\u7684\u533A\u522B\u662F\u7EBF\u4E0A\u5728\u63A7\u5236\u53F0\u5185\u770B\u4E0D\u5230\u63A5\u53E3\u8BF7\u6C42\u65E5\u5FD7\u3002

`,95),e=[o];function c(l,u,r,k,i,d){return a(),s("div",null,e)}var h=n(p,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/guide_mock.md.a486b33a.lean.js b/assets/guide_mock.md.a486b33a.lean.js new file mode 100644 index 00000000..6140a9bb --- /dev/null +++ b/assets/guide_mock.md.a486b33a.lean.js @@ -0,0 +1,413 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"\u6570\u636E mock&\u8054\u8C03","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u5F00\u53D1\u73AF\u5883","slug":"\u5F00\u53D1\u73AF\u5883"},{"level":3,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":3,"title":"\u8DE8\u57DF\u5904\u7406","slug":"\u8DE8\u57DF\u5904\u7406"},{"level":3,"title":"\u6CA1\u6709\u8DE8\u57DF\u65F6\u7684\u914D\u7F6E","slug":"\u6CA1\u6709\u8DE8\u57DF\u65F6\u7684\u914D\u7F6E"},{"level":3,"title":"\u8DE8\u57DF\u539F\u7406\u89E3\u6790","slug":"\u8DE8\u57DF\u539F\u7406\u89E3\u6790"},{"level":2,"title":"\u751F\u4EA7\u73AF\u5883","slug":"\u751F\u4EA7\u73AF\u5883"},{"level":2,"title":"\u63A5\u53E3\u8BF7\u6C42","slug":"\u63A5\u53E3\u8BF7\u6C42"},{"level":2,"title":"axios \u914D\u7F6E","slug":"axios-\u914D\u7F6E"},{"level":3,"title":"index.ts \u914D\u7F6E\u8BF4\u660E","slug":"index-ts-\u914D\u7F6E\u8BF4\u660E"},{"level":3,"title":"\u66F4\u6539\u53C2\u6570\u683C\u5F0F","slug":"\u66F4\u6539\u53C2\u6570\u683C\u5F0F"},{"level":3,"title":"\u591A\u4E2A\u63A5\u53E3\u5730\u5740","slug":"\u591A\u4E2A\u63A5\u53E3\u5730\u5740"},{"level":3,"title":"\u5220\u9664\u8BF7\u6C42 URL \u643A\u5E26\u7684\u65F6\u95F4\u6233\u53C2\u6570","slug":"\u5220\u9664\u8BF7\u6C42-url-\u643A\u5E26\u7684\u65F6\u95F4\u6233\u53C2\u6570"},{"level":2,"title":"Mock \u670D\u52A1","slug":"mock-\u670D\u52A1"},{"level":3,"title":"\u672C\u5730 Mock","slug":"\u672C\u5730-mock"},{"level":3,"title":"\u7EBF\u4E0A mock","slug":"\u7EBF\u4E0A-mock"}],"relativePath":"guide/mock.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

\u6570\u636E mock&\u8054\u8C03

\u5F00\u53D1\u73AF\u5883

\u5982\u679C\u524D\u7AEF\u5E94\u7528\u548C\u540E\u7AEF\u63A5\u53E3\u670D\u52A1\u5668\u6CA1\u6709\u8FD0\u884C\u5728\u540C\u4E00\u4E2A\u4E3B\u673A\u4E0A\uFF0C\u4F60\u9700\u8981\u5728\u5F00\u53D1\u73AF\u5883\u4E0B\u5C06\u63A5\u53E3\u8BF7\u6C42\u4EE3\u7406\u5230\u63A5\u53E3\u670D\u52A1\u5668\u3002

\u5982\u679C\u662F\u540C\u4E00\u4E2A\u4E3B\u673A\uFF0C\u53EF\u4EE5\u76F4\u63A5\u8BF7\u6C42\u5177\u4F53\u7684\u63A5\u53E3\u5730\u5740\u3002

\u914D\u7F6E

\u5F00\u53D1\u73AF\u5883\u65F6\u5019\uFF0C\u63A5\u53E3\u5730\u5740\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B

.env.development \u6587\u4EF6\u914D\u7F6E

# vite \u672C\u5730\u8DE8\u57DF\u4EE3\u7406
+VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+# \u63A5\u53E3\u5730\u5740
+VITE_GLOB_API_URL=/api
+

TIP

  • .env \u6587\u4EF6\u4E2D\u7684\u5B57\u6BB5\u5982\u679C\u662F\u5B57\u7B26\u4E32\uFF0C\u5219\u65E0\u9700\u52A0\u5F15\u53F7\uFF0C\u9ED8\u8BA4\u5168\u90E8\u4E3A\u5B57\u7B26\u4E32
  • VITE_PROXY \u4E0D\u80FD\u6362\u884C

\u8DE8\u57DF\u5904\u7406

\u5982\u679C\u4F60\u5728 src/api/ \u4E0B\u9762\u7684\u63A5\u53E3\u4E3A\u4E0B\u65B9\u4EE3\u7801\uFF0C\u4E14 .env.development \u6587\u4EF6\u914D\u7F6E\u5982\u4E0B\u6CE8\u91CA\uFF0C\u5219\u5728\u63A7\u5236\u53F0\u770B\u5230\u7684\u5730\u5740\u4E3A http://localhost:3100/basic-api/login\u3002

\u7531\u4E8E /basic-api \u5339\u914D\u5230\u4E86\u8BBE\u7F6E\u7684 VITE_PROXY\uFF0C\u6240\u4EE5\u4E0A\u65B9\u5B9E\u9645\u662F\u8BF7\u6C42 http://localhost:3000/login\uFF0C\u8FD9\u6837\u540C\u65F6\u4E5F\u89E3\u51B3\u4E86\u8DE8\u57DF\u95EE\u9898\u3002\uFF083100\u4E3A\u9879\u76EE\u7AEF\u53E3\u53F7\uFF0Chttp://localhost:3000\u4E3APROXY\u4EE3\u7406\u7684\u76EE\u6807\u5730\u5740\uFF09

// .env.development
+// VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+// VITE_GLOB_API_URL=/basic-api
+
+enum Api {
+  Login = '/login',
+}
+
+/**
+ * @description: \u7528\u6237\u767B\u9646
+ */
+export function loginApi(params: LoginParams) {
+  return http.request<LoginResultModel>({
+    url: Api.Login,
+    method: 'POST',
+    params,
+  });
+}
+

\u6CA1\u6709\u8DE8\u57DF\u65F6\u7684\u914D\u7F6E

\u5982\u679C\u6CA1\u6709\u8DE8\u57DF\u95EE\u9898\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5FFD\u7565 VITE_PROXY \u914D\u7F6E\uFF0C\u76F4\u63A5\u5C06\u63A5\u53E3\u5730\u5740\u8BBE\u7F6E\u5728 VITE_GLOB_API_URL

# \u4F8B\u5982\u63A5\u53E3\u5730\u5740\u4E3A http://localhost:3000 \u5219
+VITE_GLOB_API_URL=http://localhost:3000
+

\u5982\u679C\u6709\u8DE8\u57DF\u95EE\u9898\uFF0C\u5C06 VITE_GLOB_API_URL \u8BBE\u7F6E\u4E3A\u8DDF VITE_PROXY \u5185\u5176\u4E2D\u4E00\u4E2A\u6570\u7EC4\u7684\u7B2C\u4E00\u4E2A\u9879\u4E00\u81F4\u7684\u503C\u5373\u53EF\u3002

\u4E0B\u65B9\u7684\u63A5\u53E3\u5730\u5740\u8BBE\u7F6E\u4E3A /basic-api\uFF0C\u5F53\u8BF7\u6C42\u53D1\u51FA\u7684\u65F6\u5019\u4F1A\u7ECF\u8FC7 Vite \u7684 proxy \u4EE3\u7406\uFF0C\u5339\u914D\u5230\u4E86\u6211\u4EEC\u8BBE\u7F6E\u7684 VITE_PROXY \u89C4\u5219\uFF0C\u5C06 /basic-api \u8F6C\u5316\u4E3A http://localhost:3000 \u8FDB\u884C\u8BF7\u6C42

# \u4F8B\u5982\u63A5\u53E3\u5730\u5740\u4E3A http://localhost:3000 \u5219
+VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+# \u63A5\u53E3\u5730\u5740
+VITE_GLOB_API_URL=/basic-api
+

\u8DE8\u57DF\u539F\u7406\u89E3\u6790

\u5728 vite.config.ts \u914D\u7F6E\u6587\u4EF6\u4E2D\uFF0C\u63D0\u4F9B\u4E86 server \u7684 proxy \u529F\u80FD\uFF0C\u7528\u4E8E\u4EE3\u7406 API \u8BF7\u6C42\u3002

server: {
+  proxy: {
+    "/basic-api":{
+      target: 'http://localhost:3000',
+      changeOrigin: true,
+      ws: true,
+      rewrite: (path) => path.replace(new RegExp(\`^/basic-api\`), ''),
+    }
+  },
+},
+

\u6CE8\u610F

\u4ECE\u6D4F\u89C8\u5668\u63A7\u5236\u53F0\u7684 Network \u770B\uFF0C\u8BF7\u6C42\u662F http://localhost:3000/basic-api/xxx\uFF0C\u8FD9\u662F\u56E0\u4E3A proxy \u914D\u7F6E\u4E0D\u4F1A\u6539\u53D8\u672C\u5730\u8BF7\u6C42\u7684 url\u3002

\u751F\u4EA7\u73AF\u5883

\u751F\u4EA7\u73AF\u5883\u63A5\u53E3\u5730\u5740\u5728\u9879\u76EE\u6839\u76EE\u5F55\u4E0B .env.production \u6587\u4EF6\u914D\u7F6E\u3002

\u751F\u4EA7\u73AF\u5883\u63A5\u53E3\u5730\u5740\u503C\u9700\u8981\u4FEE\u6539 VITE_GLOB_API_URL\uFF0C\u5982\u679C\u51FA\u73B0\u8DE8\u57DF\u95EE\u9898\uFF0C\u53EF\u4EE5\u4F7F\u7528 nginx \u6216\u8005\u540E\u53F0\u5F00\u542F cors \u8FDB\u884C\u5904\u7406

\u6253\u5305\u540E\u5982\u4F55\u8FDB\u884C\u5730\u5740\u4FEE\u6539?

VITE_GLOB_* \u5F00\u5934\u7684\u53D8\u91CF\u4F1A\u5728\u6253\u5305\u7684\u65F6\u5019\u6CE8\u5165 _app.config.js \u6587\u4EF6\u5185\u3002

\u5728 dist/_app.config.js \u4FEE\u6539\u76F8\u5E94\u7684\u63A5\u53E3\u5730\u5740\u540E\u5237\u65B0\u9875\u9762\u5373\u53EF\uFF0C\u4E0D\u9700\u8981\u5728\u6839\u636E\u4E0D\u540C\u73AF\u5883\u6253\u5305\u591A\u6B21\uFF0C\u4E00\u6B21\u6253\u5305\u53EF\u4EE5\u7528\u4E8E\u591A\u4E2A\u4E0D\u540C\u63A5\u53E3\u73AF\u5883\u7684\u90E8\u7F72\u3002

\u63A5\u53E3\u8BF7\u6C42

\u5728 vue-vben-admin \u4E2D:

  1. \u9875\u9762\u4EA4\u4E92\u64CD\u4F5C\uFF1B
  2. \u8C03\u7528\u7EDF\u4E00\u7BA1\u7406\u7684 api \u8BF7\u6C42\u51FD\u6570\uFF1B
  3. \u4F7F\u7528\u5C01\u88C5\u7684 axios.ts \u53D1\u9001\u8BF7\u6C42\uFF1B
  4. \u83B7\u53D6\u670D\u52A1\u7AEF\u8FD4\u56DE\u6570\u636E
  5. \u66F4\u65B0 data\uFF1B

\u63A5\u53E3\u7EDF\u4E00\u5B58\u653E\u4E8E src/api/ \u4E0B\u9762\u7BA1\u7406

\u4EE5\u767B\u9646\u63A5\u53E3\u4E3A\u4F8B:

\u5728 src/api/ \u5185\u65B0\u5EFA\u6A21\u5757\u6587\u4EF6\uFF0C\u5176\u4E2D\u53C2\u6570\u4E0E\u8FD4\u56DE\u503C\u6700\u597D\u5B9A\u4E49\u4E00\u4E0B\u7C7B\u578B\uFF0C\u65B9\u4FBF\u6821\u9A8C\u3002\u867D\u7136\u9EBB\u70E6\uFF0C\u4F46\u662F\u540E\u7EED\u7EF4\u62A4\u5B57\u6BB5\u5F88\u65B9\u4FBF\u3002

TIP

\u7C7B\u578B\u5B9A\u4E49\u6587\u4EF6\u53EF\u4EE5\u62BD\u53D6\u51FA\u53BB\u7EDF\u4E00\u7BA1\u7406\uFF0C\u5177\u4F53\u53C2\u8003\u9879\u76EE

import { defHttp } from '/@/utils/http/axios';
+import { LoginParams, LoginResultModel } from './model/userModel';
+
+enum Api {
+  Login = '/login',
+}
+
+export function loginApi(params: LoginParams) {
+  return defHttp.request<LoginResultModel>({
+    url: Api.Login,
+    method: 'POST',
+    params,
+  });
+}
+

axios \u914D\u7F6E

axios \u8BF7\u6C42\u5C01\u88C5\u5B58\u653E\u4E8E src/utils/http/axios \u6587\u4EF6\u5939\u5185\u90E8

\u9664 index.ts \u6587\u4EF6\u5185\u5BB9\u9700\u8981\u6839\u636E\u9879\u76EE\u81EA\u884C\u4FEE\u6539\u5916\uFF0C\u5176\u4F59\u6587\u4EF6\u65E0\u9700\u4FEE\u6539


+\u251C\u2500\u2500 Axios.ts // axios\u5B9E\u4F8B
+\u251C\u2500\u2500 axiosCancel.ts // axiosCancel\u5B9E\u4F8B\uFF0C\u53D6\u6D88\u91CD\u590D\u8BF7\u6C42
+\u251C\u2500\u2500 axiosTransform.ts // \u6570\u636E\u8F6C\u6362\u7C7B
+\u251C\u2500\u2500 checkStatus.ts // \u8FD4\u56DE\u72B6\u6001\u503C\u6821\u9A8C
+\u251C\u2500\u2500 index.ts // \u63A5\u53E3\u8FD4\u56DE\u7EDF\u4E00\u5904\u7406
+
+

index.ts \u914D\u7F6E\u8BF4\u660E

const axios = new VAxios({
+  // \u8BA4\u8BC1\u65B9\u6848\uFF0C\u4F8B\u5982: Bearer
+  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
+  authenticationScheme: '',
+  // \u63A5\u53E3\u8D85\u65F6\u65F6\u95F4 \u5355\u4F4D\u6BEB\u79D2
+  timeout: 10 * 1000,
+  // \u63A5\u53E3\u53EF\u80FD\u4F1A\u6709\u901A\u7528\u7684\u5730\u5740\u90E8\u5206\uFF0C\u53EF\u4EE5\u7EDF\u4E00\u62BD\u53D6\u51FA\u6765
+  prefixUrl: prefix,
+  headers: { 'Content-Type': ContentTypeEnum.JSON },
+  // \u6570\u636E\u5904\u7406\u65B9\u5F0F\uFF0C\u89C1\u4E0B\u65B9\u8BF4\u660E
+  transform,
+  // \u914D\u7F6E\u9879\uFF0C\u4E0B\u9762\u7684\u9009\u9879\u90FD\u53EF\u4EE5\u5728\u72EC\u7ACB\u7684\u63A5\u53E3\u8BF7\u6C42\u4E2D\u8986\u76D6
+  requestOptions: {
+    // \u9ED8\u8BA4\u5C06prefix \u6DFB\u52A0\u5230url
+    joinPrefix: true,
+    // \u662F\u5426\u8FD4\u56DE\u539F\u751F\u54CD\u5E94\u5934 \u6BD4\u5982\uFF1A\u9700\u8981\u83B7\u53D6\u54CD\u5E94\u5934\u65F6\u4F7F\u7528\u8BE5\u5C5E\u6027
+    isReturnNativeResponse: false,
+    // \u9700\u8981\u5BF9\u8FD4\u56DE\u6570\u636E\u8FDB\u884C\u5904\u7406
+    isTransformRequestResult: true,
+    // post\u8BF7\u6C42\u7684\u65F6\u5019\u6DFB\u52A0\u53C2\u6570\u5230url
+    joinParamsToUrl: false,
+    // \u683C\u5F0F\u5316\u63D0\u4EA4\u53C2\u6570\u65F6\u95F4
+    formatDate: true,
+    // \u6D88\u606F\u63D0\u793A\u7C7B\u578B
+    errorMessageMode: 'message',
+    // \u63A5\u53E3\u5730\u5740
+    apiUrl: globSetting.apiUrl,
+    //  \u662F\u5426\u52A0\u5165\u65F6\u95F4\u6233
+    joinTime: true,
+    // \u5FFD\u7565\u91CD\u590D\u8BF7\u6C42
+    ignoreCancelToken: true,
+  },
+});
+

transform \u6570\u636E\u5904\u7406\u8BF4\u660E

\u7C7B\u578B\u5B9A\u4E49\uFF0C\u89C1 axiosTransform.ts \u6587\u4EF6

export abstract class AxiosTransform {
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u524D\u5904\u7406\u914D\u7F6E
+   */
+  beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig;
+
+  /**
+   * @description: \u8BF7\u6C42\u6210\u529F\u5904\u7406
+   */
+  transformRequestData?: (res: AxiosResponse<Result>, options: RequestOptions) => any;
+
+  /**
+   * @description: \u8BF7\u6C42\u5931\u8D25\u5904\u7406
+   */
+  requestCatch?: (e: Error) => Promise<any>;
+
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u524D\u7684\u62E6\u622A\u5668
+   */
+  requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig;
+
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u540E\u7684\u62E6\u622A\u5668
+   */
+  responseInterceptors?: (res: AxiosResponse<any>) => AxiosResponse<any>;
+
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u524D\u7684\u62E6\u622A\u5668\u9519\u8BEF\u5904\u7406
+   */
+  requestInterceptorsCatch?: (error: Error) => void;
+
+  /**
+   * @description: \u8BF7\u6C42\u4E4B\u540E\u7684\u62E6\u622A\u5668\u9519\u8BEF\u5904\u7406
+   */
+  responseInterceptorsCatch?: (error: Error) => void;
+}
+
+
+

\u9879\u76EE\u9ED8\u8BA4 transform \u5904\u7406\u903B\u8F91\uFF0C\u53EF\u4EE5\u6839\u636E\u5404\u81EA\u9879\u76EE\u8FDB\u884C\u5904\u7406\u3002\u4E00\u822C\u9700\u8981\u66F4\u6539\u7684\u90E8\u5206\u4E3A\u4E0B\u65B9\u4EE3\u7801\uFF0C\u89C1\u4EE3\u7801\u6CE8\u91CA\u8BF4\u660E

/**
+ * @description: \u6570\u636E\u5904\u7406\uFF0C\u65B9\u4FBF\u533A\u5206\u591A\u79CD\u5904\u7406\u65B9\u5F0F
+ */
+const transform: AxiosTransform = {
+  /**
+   * @description: \u5904\u7406\u8BF7\u6C42\u6570\u636E\u3002\u5982\u679C\u6570\u636E\u4E0D\u662F\u9884\u671F\u683C\u5F0F\uFF0C\u53EF\u76F4\u63A5\u629B\u51FA\u9519\u8BEF
+   */
+  transformRequestHook: (res: AxiosResponse<Result>, options: RequestOptions) => {
+    const { t } = useI18n();
+    const { isTransformResponse, isReturnNativeResponse } = options;
+    // \u662F\u5426\u8FD4\u56DE\u539F\u751F\u54CD\u5E94\u5934 \u6BD4\u5982\uFF1A\u9700\u8981\u83B7\u53D6\u54CD\u5E94\u5934\u65F6\u4F7F\u7528\u8BE5\u5C5E\u6027
+    if (isReturnNativeResponse) {
+      return res;
+    }
+    // \u4E0D\u8FDB\u884C\u4EFB\u4F55\u5904\u7406\uFF0C\u76F4\u63A5\u8FD4\u56DE
+    // \u7528\u4E8E\u9875\u9762\u4EE3\u7801\u53EF\u80FD\u9700\u8981\u76F4\u63A5\u83B7\u53D6code\uFF0Cdata\uFF0Cmessage\u8FD9\u4E9B\u4FE1\u606F\u65F6\u5F00\u542F
+    if (!isTransformResponse) {
+      return res.data;
+    }
+    // \u9519\u8BEF\u7684\u65F6\u5019\u8FD4\u56DE
+
+    const { data } = res;
+    if (!data) {
+      // return '[HTTP] Request has no return value';
+      throw new Error(t('sys.api.apiRequestFailed'));
+    }
+    //  \u8FD9\u91CC code\uFF0Cresult\uFF0Cmessage\u4E3A \u540E\u53F0\u7EDF\u4E00\u7684\u5B57\u6BB5\uFF0C\u9700\u8981\u5728 types.ts\u5185\u4FEE\u6539\u4E3A\u9879\u76EE\u81EA\u5DF1\u7684\u63A5\u53E3\u8FD4\u56DE\u683C\u5F0F
+    const { code, result, message } = data;
+
+    // \u8FD9\u91CC\u903B\u8F91\u53EF\u4EE5\u6839\u636E\u9879\u76EE\u8FDB\u884C\u4FEE\u6539
+    const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
+    if (hasSuccess) {
+      return result;
+    }
+
+    // \u5728\u6B64\u5904\u6839\u636E\u81EA\u5DF1\u9879\u76EE\u7684\u5B9E\u9645\u60C5\u51B5\u5BF9\u4E0D\u540C\u7684code\u6267\u884C\u4E0D\u540C\u7684\u64CD\u4F5C
+    // \u5982\u679C\u4E0D\u5E0C\u671B\u4E2D\u65AD\u5F53\u524D\u8BF7\u6C42\uFF0C\u8BF7return\u6570\u636E\uFF0C\u5426\u5219\u76F4\u63A5\u629B\u51FA\u5F02\u5E38\u5373\u53EF
+    let timeoutMsg = '';
+    switch (code) {
+      case ResultEnum.TIMEOUT:
+        timeoutMsg = t('sys.api.timeoutMessage');
+      default:
+        if (message) {
+          timeoutMsg = message;
+        }
+    }
+
+    // errorMessageMode=\u2018modal\u2019\u7684\u65F6\u5019\u4F1A\u663E\u793Amodal\u9519\u8BEF\u5F39\u7A97\uFF0C\u800C\u4E0D\u662F\u6D88\u606F\u63D0\u793A\uFF0C\u7528\u4E8E\u4E00\u4E9B\u6BD4\u8F83\u91CD\u8981\u7684\u9519\u8BEF
+    // errorMessageMode='none' \u4E00\u822C\u662F\u8C03\u7528\u65F6\u660E\u786E\u8868\u793A\u4E0D\u5E0C\u671B\u81EA\u52A8\u5F39\u51FA\u9519\u8BEF\u63D0\u793A
+    if (options.errorMessageMode === 'modal') {
+      createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg });
+    } else if (options.errorMessageMode === 'message') {
+      createMessage.error(timeoutMsg);
+    }
+
+    throw new Error(timeoutMsg || t('sys.api.apiRequestFailed'));
+  },
+
+  // \u8BF7\u6C42\u4E4B\u524D\u5904\u7406config
+  beforeRequestHook: (config, options) => {
+    const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options;
+
+    if (joinPrefix) {
+      config.url = \`\${urlPrefix}\${config.url}\`;
+    }
+
+    if (apiUrl && isString(apiUrl)) {
+      config.url = \`\${apiUrl}\${config.url}\`;
+    }
+    const params = config.params || {};
+    if (config.method?.toUpperCase() === RequestEnum.GET) {
+      if (!isString(params)) {
+        // \u7ED9 get \u8BF7\u6C42\u52A0\u4E0A\u65F6\u95F4\u6233\u53C2\u6570\uFF0C\u907F\u514D\u4ECE\u7F13\u5B58\u4E2D\u62FF\u6570\u636E\u3002
+        config.params = Object.assign(params || {}, joinTimestamp(joinTime, false));
+      } else {
+        // \u517C\u5BB9restful\u98CE\u683C
+        config.url = config.url + params + \`\${joinTimestamp(joinTime, true)}\`;
+        config.params = undefined;
+      }
+    } else {
+      if (!isString(params)) {
+        formatDate && formatRequestDate(params);
+        config.data = params;
+        config.params = undefined;
+        if (joinParamsToUrl) {
+          config.url = setObjToUrlParams(config.url as string, config.data);
+        }
+      } else {
+        // \u517C\u5BB9restful\u98CE\u683C
+        config.url = config.url + params;
+        config.params = undefined;
+      }
+    }
+    return config;
+  },
+
+  /**
+   * @description: \u8BF7\u6C42\u62E6\u622A\u5668\u5904\u7406
+   */
+  requestInterceptors: (config, options) => {
+    // \u8BF7\u6C42\u4E4B\u524D\u5904\u7406config
+    const token = getToken();
+    if (token) {
+      // jwt token
+      config.headers.Authorization = options.authenticationScheme
+        ? \`\${options.authenticationScheme} \${token}\`
+        : token;
+    }
+    return config;
+  },
+
+  /**
+   * @description: \u54CD\u5E94\u62E6\u622A\u5668\u5904\u7406
+   */
+  responseInterceptors: (res: AxiosResponse<any>) => {
+    return res;
+  },
+
+  /**
+   * @description: \u54CD\u5E94\u9519\u8BEF\u5904\u7406
+   */
+  responseInterceptorsCatch: (error: any) => {
+    const { t } = useI18n();
+    const errorLogStore = useErrorLogStoreWithOut();
+    errorLogStore.addAjaxErrorInfo(error);
+    const { response, code, message, config } = error || {};
+    const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
+    const msg: string = response?.data?.error?.message ?? '';
+    const err: string = error?.toString?.() ?? '';
+    let errMessage = '';
+
+    try {
+      if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
+        errMessage = t('sys.api.apiTimeoutMessage');
+      }
+      if (err?.includes('Network Error')) {
+        errMessage = t('sys.api.networkExceptionMsg');
+      }
+
+      if (errMessage) {
+        if (errorMessageMode === 'modal') {
+          createErrorModal({ title: t('sys.api.errorTip'), content: errMessage });
+        } else if (errorMessageMode === 'message') {
+          createMessage.error(errMessage);
+        }
+        return Promise.reject(error);
+      }
+    } catch (error) {
+      throw new Error(error);
+    }
+
+    checkStatus(error?.response?.status, msg, errorMessageMode);
+    return Promise.reject(error);
+  },
+};
+

\u66F4\u6539\u53C2\u6570\u683C\u5F0F

\u9879\u76EE\u63A5\u53E3\u9ED8\u8BA4\u4E3A Json \u53C2\u6570\u683C\u5F0F\uFF0C\u5373 headers: { 'Content-Type': ContentTypeEnum.JSON },

\u5982\u679C\u9700\u8981\u66F4\u6539\u4E3A form-data \u683C\u5F0F\uFF0C\u66F4\u6539 headers \u7684 'Content-Type \u4E3A ContentTypeEnum.FORM_URLENCODED \u5373\u53EF

\u591A\u4E2A\u63A5\u53E3\u5730\u5740

\u5F53\u9879\u76EE\u4E2D\u9700\u8981\u7528\u5230\u591A\u4E2A\u63A5\u53E3\u5730\u5740\u65F6, \u53EF\u4EE5\u5728 src/utils/http/axios/index.ts \u5BFC\u51FA\u591A\u4E2A axios \u5B9E\u4F8B

// \u76EE\u524D\u53EA\u5BFC\u51FA\u4E00\u4E2A\u9ED8\u8BA4\u5B9E\u4F8B\uFF0C\u63A5\u53E3\u5730\u5740\u5BF9\u5E94\u7684\u662F\u73AF\u5883\u53D8\u91CF\u4E2D\u7684 VITE_GLOB_API_URL \u63A5\u53E3\u5730\u5740
+export const defHttp = createAxios();
+
+// \u9700\u8981\u6709\u5176\u4ED6\u63A5\u53E3\u5730\u5740\u7684\u53EF\u4EE5\u5728\u540E\u9762\u6DFB\u52A0
+
+// other api url
+export const otherHttp = createAxios({
+  requestOptions: {
+    apiUrl: 'xxx',
+  },
+});
+

\u5220\u9664\u8BF7\u6C42 URL \u643A\u5E26\u7684\u65F6\u95F4\u6233\u53C2\u6570

\u5982\u679C\u4E0D\u9700\u8981 url \u4E0A\u9762\u9ED8\u8BA4\u643A\u5E26\u7684\u65F6\u95F4\u6233\u53C2\u6570 ?_t=xxx

const axios = new VAxios({
+  requestOptions: {
+    // \u662F\u5426\u52A0\u5165\u65F6\u95F4\u6233
+    joinTime: false,
+  },
+});
+

Mock \u670D\u52A1

Mock \u6570\u636E\u662F\u524D\u7AEF\u5F00\u53D1\u8FC7\u7A0B\u4E2D\u5FC5\u4E0D\u53EF\u5C11\u7684\u4E00\u73AF\uFF0C\u662F\u5206\u79BB\u524D\u540E\u7AEF\u5F00\u53D1\u7684\u5173\u952E\u94FE\u8DEF\u3002\u901A\u8FC7\u9884\u5148\u8DDF\u670D\u52A1\u5668\u7AEF\u7EA6\u5B9A\u597D\u7684\u63A5\u53E3\uFF0C\u6A21\u62DF\u8BF7\u6C42\u6570\u636E\u751A\u81F3\u903B\u8F91\uFF0C\u80FD\u591F\u8BA9\u524D\u7AEF\u5F00\u53D1\u72EC\u7ACB\u81EA\u4E3B\uFF0C\u4E0D\u4F1A\u88AB\u670D\u52A1\u7AEF\u7684\u5F00\u53D1\u8FDB\u7A0B\u6240\u963B\u585E\u3002

\u672C\u9879\u76EE\u4F7F\u7528 vite-plugin-mock \u6765\u8FDB\u884C mock \u6570\u636E\u5904\u7406\u3002\u9879\u76EE\u5185 mock \u670D\u52A1\u5206\u672C\u5730\u548C\u7EBF\u4E0A\u3002

\u672C\u5730 Mock

\u672C\u5730 mock \u91C7\u7528 Node.js \u4E2D\u95F4\u4EF6\u8FDB\u884C\u53C2\u6570\u62E6\u622A\uFF08\u4E0D\u91C7\u7528 mock.js \u7684\u539F\u56E0\u662F\u672C\u5730\u5F00\u53D1\u770B\u4E0D\u5230\u8BF7\u6C42\u53C2\u6570\u548C\u54CD\u5E94\u7ED3\u679C\uFF09\u3002

\u5982\u4F55\u65B0\u589E mock \u63A5\u53E3

\u5982\u679C\u4F60\u60F3\u6DFB\u52A0 mock \u6570\u636E\uFF0C\u53EA\u8981\u5728\u6839\u76EE\u5F55\u4E0B\u627E\u5230 mock \u6587\u4EF6\uFF0C\u6DFB\u52A0\u5BF9\u5E94\u7684\u63A5\u53E3\uFF0C\u5BF9\u5176\u8FDB\u884C\u62E6\u622A\u548C\u6A21\u62DF\u6570\u636E\u3002

\u5728 mock \u6587\u4EF6\u5939\u5185\u65B0\u5EFA\u6587\u4EF6

TIP

\u6587\u4EF6\u65B0\u589E\u540E\u4F1A\u81EA\u52A8\u66F4\u65B0\uFF0C\u4E0D\u9700\u8981\u624B\u52A8\u91CD\u542F\uFF0C\u53EF\u4EE5\u5728\u4EE3\u7801\u63A7\u5236\u53F0\u67E5\u770B\u65E5\u5FD7\u4FE1\u606F mock \u6587\u4EF6\u5939\u5185\u4F1A\u81EA\u52A8\u6CE8\u518C\uFF0C\u6392\u9664\u4EE5_\u5F00\u5934\u7684\u6587\u4EF6\u5939\u53CA\u6587\u4EF6

\u4F8B:

import { MockMethod } from 'vite-plugin-mock';
+import { resultPageSuccess } from '../_util';
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 60; index++) {
+    result.push({
+      id: \`\${index}\`,
+      beginTime: '@datetime',
+      endTime: '@datetime',
+      address: '@city()',
+      name: '@cname()',
+      'no|100000-10000000': 100000,
+      'status|1': ['\u6B63\u5E38', '\u542F\u7528', '\u505C\u7528'],
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/api/table/getDemoList',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];
+

TIP

mock \u7684\u503C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 mockjs \u7684\u8BED\u6CD5\u3002

\u63A5\u53E3\u683C\u5F0F

{
+  url: string; // mock \u63A5\u53E3\u5730\u5740
+  method?: MethodType; // \u8BF7\u6C42\u65B9\u5F0F
+  timeout?: number; // \u5EF6\u65F6\u65F6\u95F4
+  statusCode: number; // \u54CD\u5E94\u72B6\u6001\u7801
+  response: ((opt: { // \u54CD\u5E94\u7ED3\u679C
+      body: any;
+      query: any;
+  }) => any) | object;
+}
+

\u53C2\u6570\u83B7\u53D6

GET \u63A5\u53E3\uFF1A ({ query }) => { }

POST \u63A5\u53E3\uFF1A ({ body }) => { }

util \u8BF4\u660E

\u53EF\u5728 \u4EE3\u7801 \u4E2D\u67E5\u770B

TIP

util \u53EA\u4F5C\u4E3A\u670D\u52A1\u5904\u7406\u7ED3\u679C\u6570\u636E\u4F7F\u7528\u3002\u53EF\u4EE5\u4E0D\u7528\uFF0C\u5982\u9700\u4F7F\u7528\u53EF\u81EA\u884C\u5C01\u88C5\uFF0C\u9700\u8981\u5C06\u5BF9\u5E94\u7684\u5B57\u6BB5\u6539\u4E3A\u63A5\u53E3\u7684\u8FD4\u56DE\u7ED3\u6784

\u5339\u914D

\u5728 src/api \u4E0B\u9762\uFF0C\u5982\u679C\u63A5\u53E3\u5339\u914D\u5230 mock\uFF0C\u5219\u4F1A\u4F18\u5148\u4F7F\u7528 mock \u8FDB\u884C\u54CD\u5E94

import { defHttp } from '/@/utils/http/axios';
+import { LoginParams, LoginResultModel } from './model/userModel';
+
+enum Api {
+  Login = '/login',
+}
+
+/**
+ * @description: user login api
+ */
+export function loginApi(params: LoginParams) {
+  return defHttp.request<LoginResultModel>(
+    {
+      url: Api.Login,
+      method: 'POST',
+      params,
+    },
+    {
+      errorMessageMode: 'modal',
+    }
+  );
+}
+// \u4F1A\u5339\u914D\u5230\u4E0A\u65B9\u7684
+export default [
+  {
+    url: '/api/login',
+    timeout: 1000,
+    method: 'POST',
+    response: ({ body }) => {
+      return resultPageSuccess({});
+    },
+  },
+] as MockMethod[];
+

\u63A5\u53E3\u6709\u4E86\uFF0C\u5982\u4F55\u53BB\u6389 mock

\u5F53\u540E\u53F0\u63A5\u53E3\u5DF2\u7ECF\u5F00\u53D1\u5B8C\u6210\uFF0C\u53EA\u9700\u8981\u5C06\u76F8\u5E94\u7684 mock \u51FD\u6570\u53BB\u6389\u5373\u53EF\u3002

\u4EE5\u4E0A\u65B9\u63A5\u53E3\u4E3A\u4F8B\uFF0C\u5047\u5982\u540E\u53F0\u63A5\u53E3 login \u5DF2\u7ECF\u5F00\u53D1\u5B8C\u6210\uFF0C\u5219\u53EA\u9700\u8981\u5220\u9664/\u6CE8\u91CA\u6389\u4E0B\u65B9\u4EE3\u7801\u5373\u53EF

export default [
+  {
+    url: '/api/login',
+    timeout: 1000,
+    method: 'POST',
+    response: ({ body }) => {
+      return resultPageSuccess({});
+    },
+  },
+] as MockMethod[];
+

\u7EBF\u4E0A mock

\u7531\u4E8E\u8BE5\u9879\u76EE\u662F\u4E00\u4E2A\u5C55\u793A\u7C7B\u9879\u76EE\uFF0C\u7EBF\u4E0A\u4E5F\u662F\u7528 mock \u6570\u636E\uFF0C\u6240\u4EE5\u5728\u6253\u5305\u540E\u540C\u65F6\u4E5F\u96C6\u6210\u4E86 mock\u3002\u901A\u5E38\u9879\u76EE\u7EBF\u4E0A\u4E00\u822C\u4E3A\u6B63\u5F0F\u63A5\u53E3\u3002

\u9879\u76EE\u7EBF\u4E0A mock \u91C7\u7528\u7684\u662F mockjs \u8FDB\u884C mock \u6570\u636E\u6A21\u62DF\u3002

\u7EBF\u4E0A\u5982\u4F55\u5F00\u542F mock

\u6CE8\u610F

\u7EBF\u4E0A\u5F00\u542F mock \u53EA\u9002\u7528\u4E8E\u4E00\u4E9B\u7B80\u5355\u7684\u793A\u4F8B\u7F51\u7AD9\u53CA\u9884\u89C8\u7F51\u7AD9\u3002\u4E00\u5B9A\u4E0D\u8981\u5728\u6B63\u5F0F\u7684\u751F\u4EA7\u73AF\u5883\u5F00\u542F\uFF01\uFF01\uFF01

  1. \u4FEE\u6539 .env.production \u6587\u4EF6\u5185\u7684 VITE_USE_MOCK \u7684\u503C\u4E3A true
VITE_USE_MOCK = true;
+
  1. \u5728 mock/_createProductionServer.ts \u6587\u4EF6\u4E2D\u5F15\u5165\u9700\u8981\u7684 mock \u6587\u4EF6
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
+
+const modules = import.meta.globEager('./**/*.ts');
+
+const mockModules: any[] = [];
+Object.keys(modules).forEach((key) => {
+  if (key.includes('/_')) {
+    return;
+  }
+  mockModules.push(...modules[key].default);
+});
+
+export function setupProdMockServer() {
+  createProdMockServer(mockModules);
+}
+
  1. \u5728 build/vite/plugin/mock.ts \u91CC\u9762\u5F15\u5165
import { viteMockServe } from 'vite-plugin-mock';
+
+export function configMockPlugin(isBuild: boolean) {
+  return viteMockServe({
+    injectCode: \`
+      import { setupProdMockServer } from '../mock/_createProductionServer';
+
+      setupProdMockServer();
+      \`,
+  });
+}
+

\u4E3A\u4EC0\u4E48\u901A\u8FC7\u63D2\u4EF6\u6CE8\u5165\u4EE3\u7801\u800C\u4E0D\u662F\u76F4\u63A5\u5728 main.ts \u5185\u63D2\u5165

\u5728\u63D2\u4EF6\u5185\u901A\u8FC7 injectCode \u63D2\u5165\u4EE3\u7801\uFF0C\u65B9\u4FBF\u63A7\u5236 mockjs \u662F\u5426\u88AB\u6253\u5305\u5230\u6700\u7EC8\u4EE3\u7801\u5185\u3002\u5982\u679C\u5728 main.ts \u5185\u5224\u65AD\uFF0C\u5982\u679C\u5173\u95ED\u4E86 mock \u529F\u80FD\uFF0Cmockjs \u4E5F\u4F1A\u6253\u5305\u5230\u6784\u5EFA\u6587\u4EF6\u5185\uFF0C\u8FD9\u6837\u4F1A\u589E\u52A0\u6253\u5305\u4F53\u79EF\u3002

\u5230\u8FD9\u91CC\u7EBF\u4E0A mock \u5C31\u914D\u7F6E\u5B8C\u6210\u4E86\u3002\u7EBF\u4E0A\u4E0E\u672C\u5730\u5DEE\u5F02\u4E0D\u5927\uFF0C\u6BD4\u8F83\u5927\u7684\u533A\u522B\u662F\u7EBF\u4E0A\u5728\u63A7\u5236\u53F0\u5185\u770B\u4E0D\u5230\u63A5\u53E3\u8BF7\u6C42\u65E5\u5FD7\u3002

__VP_STATIC_END__`,95),e=[o];function c(l,u,r,k,i,d){return a(),s("div",null,e)}var h=n(p,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/guide_router.md.5cf0d342.js b/assets/guide_router.md.5cf0d342.js new file mode 100644 index 00000000..f4b140af --- /dev/null +++ b/assets/guide_router.md.5cf0d342.js @@ -0,0 +1,261 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u8DEF\u7531","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":3,"title":"\u6A21\u5757\u8BF4\u660E","slug":"\u6A21\u5757\u8BF4\u660E"},{"level":3,"title":"\u591A\u7EA7\u8DEF\u7531","slug":"\u591A\u7EA7\u8DEF\u7531"},{"level":3,"title":"Meta \u914D\u7F6E\u8BF4\u660E","slug":"meta-\u914D\u7F6E\u8BF4\u660E"},{"level":3,"title":"\u5916\u90E8\u9875\u9762\u5D4C\u5957","slug":"\u5916\u90E8\u9875\u9762\u5D4C\u5957"},{"level":3,"title":"\u5916\u94FE","slug":"\u5916\u94FE"},{"level":3,"title":"\u52A8\u6001\u8DEF\u7531Tab\u81EA\u52A8\u5173\u95ED\u529F\u80FD","slug":"\u52A8\u6001\u8DEF\u7531tab\u81EA\u52A8\u5173\u95ED\u529F\u80FD"},{"level":2,"title":"\u56FE\u6807","slug":"\u56FE\u6807"},{"level":2,"title":"\u65B0\u589E\u8DEF\u7531","slug":"\u65B0\u589E\u8DEF\u7531"},{"level":3,"title":"\u5982\u4F55\u65B0\u589E\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757","slug":"\u5982\u4F55\u65B0\u589E\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757"},{"level":3,"title":"\u9A8C\u8BC1","slug":"\u9A8C\u8BC1"},{"level":2,"title":"\u8DEF\u7531\u5237\u65B0","slug":"\u8DEF\u7531\u5237\u65B0"},{"level":3,"title":"\u5B9E\u73B0","slug":"\u5B9E\u73B0"},{"level":3,"title":"Redirect","slug":"redirect"},{"level":2,"title":"\u9875\u9762\u8DF3\u8F6C","slug":"\u9875\u9762\u8DF3\u8F6C"},{"level":3,"title":"\u65B9\u5F0F","slug":"\u65B9\u5F0F"},{"level":2,"title":"\u591A\u6807\u7B7E\u9875","slug":"\u591A\u6807\u7B7E\u9875"},{"level":3,"title":"\u5982\u4F55\u5F00\u542F\u9875\u9762\u7F13\u5B58","slug":"\u5982\u4F55\u5F00\u542F\u9875\u9762\u7F13\u5B58"},{"level":3,"title":"\u5982\u4F55\u8BA9\u67D0\u4E2A\u9875\u9762\u4E0D\u7F13\u5B58","slug":"\u5982\u4F55\u8BA9\u67D0\u4E2A\u9875\u9762\u4E0D\u7F13\u5B58"},{"level":2,"title":"\u5982\u4F55\u66F4\u6539\u9996\u9875\u8DEF\u7531","slug":"\u5982\u4F55\u66F4\u6539\u9996\u9875\u8DEF\u7531"}],"relativePath":"guide/router.md","lastUpdated":1694442156385}',p={},o=t(`

\u8DEF\u7531

\u9879\u76EE\u8DEF\u7531\u914D\u7F6E\u5B58\u653E\u4E8E src/router/routes \u4E0B\u9762\u3002 src/router/routes/modules\u7528\u4E8E\u5B58\u653E\u8DEF\u7531\u6A21\u5757\uFF0C\u5728\u8BE5\u76EE\u5F55\u4E0B\u7684\u6587\u4EF6\u4F1A\u81EA\u52A8\u6CE8\u518C\u3002

\u914D\u7F6E

\u6A21\u5757\u8BF4\u660E

\u5728 src/router/routes/modules \u5185\u7684 .ts \u6587\u4EF6\u4F1A\u88AB\u89C6\u4E3A\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757\u3002

\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757\u5305\u542B\u4EE5\u4E0B\u7ED3\u6784

import type { AppRouteModule } from '/@/router/types';
+
+import { LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+
+const dashboard: AppRouteModule = {
+  path: '/dashboard',
+  name: 'Dashboard',
+  component: LAYOUT,
+  redirect: '/dashboard/analysis',
+  meta: {
+    icon: 'ion:grid-outline',
+    title: t('routes.dashboard.dashboard'),
+  },
+  children: [
+    {
+      path: 'analysis',
+      name: 'Analysis',
+      component: () => import('/@/views/dashboard/analysis/index.vue'),
+      meta: {
+        affix: true,
+        title: t('routes.dashboard.analysis'),
+      },
+    },
+    {
+      path: 'workbench',
+      name: 'Workbench',
+      component: () => import('/@/views/dashboard/workbench/index.vue'),
+      meta: {
+        title: t('routes.dashboard.workbench'),
+      },
+    },
+  ],
+};
+export default dashboard;
+

\u591A\u7EA7\u8DEF\u7531

\u6CE8\u610F\u4E8B\u9879

  • \u6574\u4E2A\u9879\u76EE\u6240\u6709\u8DEF\u7531 name \u4E0D\u80FD\u91CD\u590D
  • \u6240\u6709\u7684\u591A\u7EA7\u8DEF\u7531\u6700\u7EC8\u90FD\u4F1A\u8F6C\u6210\u4E8C\u7EA7\u8DEF\u7531\uFF0C\u6240\u4EE5\u4E0D\u80FD\u5185\u5D4C\u5B50\u8DEF\u7531
  • \u9664\u4E86 layout \u5BF9\u5E94\u7684 path \u524D\u9762\u9700\u8981\u52A0 /\uFF0C\u5176\u4F59\u5B50\u8DEF\u7531\u90FD\u4E0D\u8981\u4EE5/\u5F00\u5934

\u793A\u4F8B

import type { AppRouteModule } from '/@/router/types';
+import { getParentLayout, LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+const permission: AppRouteModule = {
+  path: '/level',
+  name: 'Level',
+  component: LAYOUT,
+  redirect: '/level/menu1/menu1-1/menu1-1-1',
+  meta: {
+    icon: 'ion:menu-outline',
+    title: t('routes.demo.level.level'),
+  },
+
+  children: [
+    {
+      path: 'tabs/:id', 
+      name: 'TabsParams',
+      component: getParentLayout('TabsParams'),
+      meta: {
+        carryParam: true,
+        hidePathForChildren: true, // \u672C\u7EA7path\u5C06\u4F1A\u5728\u5B50\u7EA7\u83DC\u5355\u4E2D\u5408\u6210\u5B8C\u6574path\u65F6\u4F1A\u5FFD\u7565\u8FD9\u4E00\u5C42\u7EA7
+      },
+      children: [
+        path: 'tabs/id1', // \u5176\u4E0A\u7EA7\u6709\u6807\u8BB0hidePathForChildren\uFF0C\u6240\u4EE5\u672C\u7EA7\u5728\u751F\u6210\u83DC\u5355\u65F6\u6700\u7EC8\u7684path\u4E3A  /level/tabs/id1
+        name: 'TabsParams',
+        component: getParentLayout('TabsParams'),
+        meta: {
+          carryParam: true,
+          ignoreRoute: true,  // \u672C\u8DEF\u7531\u4EC5\u7528\u4E8E\u83DC\u5355\u751F\u6210\uFF0C\u4E0D\u4F1A\u5728\u5B9E\u9645\u7684\u8DEF\u7531\u8868\u4E2D\u51FA\u73B0
+        },
+      ]
+    },
+    {
+      path: 'menu1',
+      name: 'Menu1Demo',
+      component: getParentLayout('Menu1Demo'),
+      meta: {
+        title: 'Menu1',
+      },
+      redirect: '/level/menu1/menu1-1/menu1-1-1',
+      children: [
+        {
+          path: 'menu1-1',
+          name: 'Menu11Demo',
+          component: getParentLayout('Menu11Demo'),
+          meta: {
+            title: 'Menu1-1',
+          },
+          redirect: '/level/menu1/menu1-1/menu1-1-1',
+          children: [
+            {
+              path: 'menu1-1-1',
+              name: 'Menu111Demo',
+              component: () => import('/@/views/demo/level/Menu111.vue'),
+              meta: {
+                title: 'Menu111',
+              },
+            },
+          ],
+        },
+      ],
+    },
+  ],
+};
+
+export default permission;
+

Meta \u914D\u7F6E\u8BF4\u660E

export interface RouteMeta {
+  // \u8DEF\u7531title  \u4E00\u822C\u5FC5\u586B
+  title: string;
+  // \u52A8\u6001\u8DEF\u7531\u53EF\u6253\u5F00Tab\u9875\u6570
+  dynamicLevel?: number;
+  // \u52A8\u6001\u8DEF\u7531\u7684\u5B9E\u9645Path, \u5373\u53BB\u9664\u8DEF\u7531\u7684\u52A8\u6001\u90E8\u5206;
+  realPath?: string;
+  // \u662F\u5426\u5FFD\u7565\u6743\u9650\uFF0C\u53EA\u5728\u6743\u9650\u6A21\u5F0F\u4E3ARole\u7684\u65F6\u5019\u6709\u6548
+  ignoreAuth?: boolean;
+  // \u53EF\u4EE5\u8BBF\u95EE\u7684\u89D2\u8272\uFF0C\u53EA\u5728\u6743\u9650\u6A21\u5F0F\u4E3ARole\u7684\u65F6\u5019\u6709\u6548
+  roles?: RoleEnum[];
+  // \u662F\u5426\u5FFD\u7565KeepAlive\u7F13\u5B58
+  ignoreKeepAlive?: boolean;
+  // \u662F\u5426\u56FA\u5B9A\u6807\u7B7E
+  affix?: boolean;
+  // \u56FE\u6807\uFF0C\u4E5F\u662F\u83DC\u5355\u56FE\u6807
+  icon?: string;
+  // \u5185\u5D4Ciframe\u7684\u5730\u5740
+  frameSrc?: string;
+  // \u6307\u5B9A\u8BE5\u8DEF\u7531\u5207\u6362\u7684\u52A8\u753B\u540D
+  transitionName?: string;
+  // \u9690\u85CF\u8BE5\u8DEF\u7531\u5728\u9762\u5305\u5C51\u4E0A\u9762\u7684\u663E\u793A
+  hideBreadcrumb?: boolean;
+  // \u5982\u679C\u8BE5\u8DEF\u7531\u4F1A\u643A\u5E26\u53C2\u6570\uFF0C\u4E14\u9700\u8981\u5728tab\u9875\u4E0A\u9762\u663E\u793A\u3002\u5219\u9700\u8981\u8BBE\u7F6E\u4E3Atrue
+  carryParam?: boolean;
+  // \u9690\u85CF\u6240\u6709\u5B50\u83DC\u5355
+  hideChildrenInMenu?: boolean;
+  // \u5F53\u524D\u6FC0\u6D3B\u7684\u83DC\u5355\u3002\u7528\u4E8E\u914D\u7F6E\u8BE6\u60C5\u9875\u65F6\u5DE6\u4FA7\u6FC0\u6D3B\u7684\u83DC\u5355\u8DEF\u5F84
+  currentActiveMenu?: string;
+  // \u5F53\u524D\u8DEF\u7531\u4E0D\u518D\u6807\u7B7E\u9875\u663E\u793A
+  hideTab?: boolean;
+  // \u5F53\u524D\u8DEF\u7531\u4E0D\u518D\u83DC\u5355\u663E\u793A
+  hideMenu?: boolean;
+  // \u83DC\u5355\u6392\u5E8F\uFF0C\u53EA\u5BF9\u7B2C\u4E00\u7EA7\u6709\u6548
+  orderNo?: number;
+  // \u5FFD\u7565\u8DEF\u7531\u3002\u7528\u4E8E\u5728ROUTE_MAPPING\u4EE5\u53CABACK\u6743\u9650\u6A21\u5F0F\u4E0B\uFF0C\u751F\u6210\u5BF9\u5E94\u7684\u83DC\u5355\u800C\u5FFD\u7565\u8DEF\u7531\u30022.5.3\u4EE5\u4E0A\u7248\u672C\u6709\u6548
+  ignoreRoute?: boolean;
+  // \u662F\u5426\u5728\u5B50\u7EA7\u83DC\u5355\u7684\u5B8C\u6574path\u4E2D\u5FFD\u7565\u672C\u7EA7path\u30022.5.3\u4EE5\u4E0A\u7248\u672C\u6709\u6548
+  hidePathForChildren?: boolean;
+}
+

\u5916\u90E8\u9875\u9762\u5D4C\u5957

\u53EA\u9700\u8981\u5C06 frameSrc \u8BBE\u7F6E\u4E3A\u9700\u8981\u8DF3\u8F6C\u7684\u5730\u5740\u5373\u53EF

const IFrame = () => import('/@/views/sys/iframe/FrameBlank.vue');
+{
+  path: 'doc',
+  name: 'Doc',
+  component: IFrame,
+  meta: {
+    frameSrc: 'https://vvbin.cn/doc-next/',
+    title: t('routes.demo.iframe.doc'),
+  },
+},
+

\u5916\u94FE

\u53EA\u9700\u8981\u5C06 path \u8BBE\u7F6E\u4E3A\u9700\u8981\u8DF3\u8F6C\u7684HTTP \u5730\u5740\u5373\u53EF

{
+  path: 'https://vvbin.cn/doc-next/',
+  name: 'DocExternal',
+  component: IFrame,
+  meta: {
+    title: t('routes.demo.iframe.docExternal'),
+  },
+}
+

\u52A8\u6001\u8DEF\u7531Tab\u81EA\u52A8\u5173\u95ED\u529F\u80FD

\u82E5\u9700\u8981\u5F00\u542F\u8BE5\u529F\u80FD\uFF0C\u9700\u8981\u5728\u52A8\u6001\u8DEF\u7531\u7684meta\u4E2D\u8BBE\u7F6E\u5982\u4E0B\u4E24\u4E2A\u53C2\u6570\uFF1A

  • dynamicLevel \u6700\u5927\u80FD\u6253\u5F00\u7684Tab\u6807\u7B7E\u9875\u6570
  • realPath \u52A8\u6001\u8DEF\u7531\u5B9E\u9645\u8DEF\u5F84(\u8003\u8651\u5230\u52A8\u6001\u8DEF\u7531\u6709\u65F6\u5019\u53EF\u80FD\u5B58\u5728N\u5C42\u7684\u60C5\u51B5, \u4F8B\uFF1A/:id/:subId/:...), \u4E3A\u4E86\u51CF\u5C11\u8BA1\u7B97\u5F00\u9500, \u4F7F\u7528\u914D\u7F6E\u65B9\u5F0F\u4E8B\u5148\u89C4\u5B9A\u597D\u8DEF\u7531\u7684\u5B9E\u9645\u8DEF\u5F84(\u6CE8\u610F: \u8BE5\u53C2\u6570\u82E5\u4E0D\u8BBE\u7F6E\uFF0C\u5C06\u65E0\u6CD5\u4F7F\u7528\u8BE5\u529F\u80FD)
{
+  path: 'detail/:id',
+  name: 'TabDetail',
+  component: () => import('/@/views/demo/feat/tabs/TabDetail.vue'),
+  meta: {
+    currentActiveMenu: '/feat/tabs',
+    title: t('routes.demo.feat.tabDetail'),
+    hideMenu: true,
+    dynamicLevel: 3,
+    realPath: '/feat/tabs/detail',
+  },
+}
+

\u56FE\u6807

\u8FD9\u91CC\u7684 icon \u914D\u7F6E\uFF0C\u4F1A\u540C\u6B65\u5230 \u83DC\u5355\uFF08icon \u7684\u503C\u53EF\u4EE5\u67E5\u770B\u6B64\u5904\uFF09\u3002

\u65B0\u589E\u8DEF\u7531

\u5982\u4F55\u65B0\u589E\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757

  1. \u5728 src/router/routes/modules \u5185\u65B0\u589E\u4E00\u4E2A\u6A21\u5757\u6587\u4EF6\u3002

\u793A\u4F8B\uFF0C\u65B0\u589E test.ts \u6587\u4EF6

import type { AppRouteModule } from '/@/router/types';
+import { LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+
+const dashboard: AppRouteModule = {
+  path: '/about',
+  name: 'About',
+  component: LAYOUT,
+  redirect: '/about/index',
+  meta: {
+    icon: 'simple-icons:about-dot-me',
+    title: t('routes.dashboard.about'),
+  },
+  children: [
+    {
+      path: 'index',
+      name: 'AboutPage',
+      component: () => import('/@/views/sys/about/index.vue'),
+      meta: {
+        title: t('routes.dashboard.about'),
+        icon: 'simple-icons:about-dot-me',
+      },
+    },
+  ],
+};
+
+export default dashboard;
+

\u6B64\u65F6\u8DEF\u7531\u5DF2\u6DFB\u52A0\u5B8C\u6210\uFF0C\u4E0D\u9700\u8981\u624B\u52A8\u5F15\u5165\uFF0C\u653E\u5728src/router/routes/modules \u5185\u7684\u6587\u4EF6\u4F1A\u81EA\u52A8\u88AB\u52A0\u8F7D\u3002

\u9A8C\u8BC1

\u8BBF\u95EE ip:\u7AEF\u53E3/about/index \u51FA\u73B0\u5BF9\u5E94\u7EC4\u4EF6\u5185\u5BB9\u5373\u4EE3\u8868\u6210\u529F

\u8DEF\u7531\u5237\u65B0

\u9879\u76EE\u4E2D\u91C7\u7528\u7684\u662F\u91CD\u5B9A\u5411\u65B9\u5F0F

\u5B9E\u73B0

import { useRedo } from '/@/hooks/web/usePage';
+import { defineComponent } from 'vue';
+export default defineComponent({
+  setup() {
+    const redo = useRedo();
+    // \u6267\u884C\u5237\u65B0
+    redo();
+    return {};
+  },
+});
+

Redirect

src/views/sys/redirect/index.vue

import { defineComponent, unref } from 'vue';
+import { useRouter } from 'vue-router';
+export default defineComponent({
+  name: 'Redirect',
+  setup() {
+    const { currentRoute, replace } = useRouter();
+    const { params, query } = unref(currentRoute);
+    const { path } = params;
+    const _path = Array.isArray(path) ? path.join('/') : path;
+    replace({
+      path: '/' + _path,
+      query,
+    });
+    return {};
+  },
+});
+

\u9875\u9762\u8DF3\u8F6C

\u9875\u9762\u8DF3\u8F6C\u5EFA\u8BAE\u91C7\u7528\u9879\u76EE\u63D0\u4F9B\u7684 useGo

\u65B9\u5F0F

import { useGo } from '/@/hooks/web/usePage';
+import { defineComponent } from 'vue';
+export default defineComponent({
+  setup() {
+    const go = useGo();
+
+    // \u6267\u884C\u5237\u65B0
+    go();
+    go(PageEnum.Home);
+    return {};
+  },
+});
+

\u591A\u6807\u7B7E\u9875

\u6807\u7B7E\u9875\u4F7F\u7528\u7684\u662F keep-alive \u548C router-view \u5B9E\u73B0\uFF0C\u5B9E\u73B0\u5207\u6362 tab \u540E\u8FD8\u80FD\u4FDD\u5B58\u5207\u6362\u4E4B\u524D\u7684\u72B6\u6001\u3002

\u5982\u4F55\u5F00\u542F\u9875\u9762\u7F13\u5B58

\u5F00\u542F\u7F13\u5B58\u6709 3 \u4E2A\u6761\u4EF6

  1. \u5728 src/settings/projectSetting.ts \u5185\u5C06openKeepAlive \u8BBE\u7F6E\u4E3A true
  2. \u8DEF\u7531\u8BBE\u7F6E name\uFF0C\u4E14\u4E0D\u80FD\u91CD\u590D
  3. \u8DEF\u7531\u5BF9\u5E94\u7684\u7EC4\u4EF6\u52A0\u4E0A name\uFF0C\u4E0E\u8DEF\u7531\u8BBE\u7F6E\u7684 name \u4FDD\u6301\u4E00\u81F4
 {
+   ...,
+    // name
+    name: 'Login',
+    // \u5BF9\u5E94\u7EC4\u4EF6\u7EC4\u4EF6\u7684name
+    component: () => import('/@/views/sys/login/index.vue'),
+    ...
+  },
+
+  // /@/views/sys/login/index.vue
+  export default defineComponent({
+    // \u9700\u8981\u548C\u8DEF\u7531\u7684name\u4E00\u81F4
+    name:"Login"
+  });
+

\u6CE8\u610F

keep-alive \u751F\u6548\u7684\u524D\u63D0\u662F\uFF1A\u9700\u8981\u5C06\u8DEF\u7531\u7684 name \u5C5E\u6027\u53CA\u5BF9\u5E94\u7684\u9875\u9762\u7684 name \u8BBE\u7F6E\u6210\u4E00\u6837\u3002\u56E0\u4E3A\uFF1A

include - \u5B57\u7B26\u4E32\u6216\u6B63\u5219\u8868\u8FBE\u5F0F\uFF0C\u53EA\u6709\u540D\u79F0\u5339\u914D\u7684\u7EC4\u4EF6\u4F1A\u88AB\u7F13\u5B58

\u5982\u4F55\u8BA9\u67D0\u4E2A\u9875\u9762\u4E0D\u7F13\u5B58

\u53EF\u5728 router.meta \u4E0B\u914D\u7F6E

\u53EF\u4EE5\u5C06 ignoreKeepAlive \u914D\u7F6E\u6210 true \u5373\u53EF\u5173\u95ED\u7F13\u5B58\u3002

export interface RouteMeta {
+  // \u662F\u5426\u5FFD\u7565KeepAlive\u7F13\u5B58
+  ignoreKeepAlive?: boolean;
+}
+

\u5982\u4F55\u66F4\u6539\u9996\u9875\u8DEF\u7531

\u9996\u9875\u8DEF\u7531\u6307\u7684\u662F\u5E94\u7528\u7A0B\u5E8F\u4E2D\u7684\u9ED8\u8BA4\u8DEF\u7531\uFF0C\u5F53\u4E0D\u8F93\u5165\u5176\u4ED6\u4EFB\u4F55\u8DEF\u7531\u65F6\uFF0C\u4F1A\u81EA\u52A8\u91CD\u5B9A\u5411\u5230\u8BE5\u8DEF\u7531\u4E0B\uFF0C\u5E76\u4E14\u8BE5\u8DEF\u7531\u5728Tab\u4E0A\u662F\u56FA\u5B9A\u7684\uFF0C\u5373\u4F7F\u8BBE\u7F6Eaffix: false\u4E5F\u4E0D\u5141\u8BB8\u5173\u95ED

\u4F8B\uFF1A\u9996\u9875\u8DEF\u7531\u914D\u7F6E\u7684\u662F/dashboard/analysis\uFF0C\u90A3\u4E48\u5F53\u76F4\u63A5\u8BBF\u95EE http://localhost:3100/ \u4F1A\u81EA\u52A8\u8DF3\u8F6C\u5230http://localhost:3100/#/dashboard/analysis \u4E0A(\u7528\u6237\u5DF2\u767B\u5F55\u7684\u60C5\u51B5\u4E0B)

\u53EF\u4EE5\u5C06pageEnum.ts\u4E2D\u7684BASE_HOME\u66F4\u6539\u4E3A\u9700\u8981\u4F60\u60F3\u8BBE\u7F6E\u7684\u9996\u9875\u5373\u53EF

export enum PageEnum {
+    // basic home path
+    // \u66F4\u6539\u6B64\u5904\u5373\u53EF
+    BASE_HOME = '/dashboard',
+}
+
+
`,60),e=[o];function c(l,u,r,i,k,d){return a(),s("div",null,e)}var g=n(p,[["render",c]]);export{h as __pageData,g as default}; diff --git a/assets/guide_router.md.5cf0d342.lean.js b/assets/guide_router.md.5cf0d342.lean.js new file mode 100644 index 00000000..71906e31 --- /dev/null +++ b/assets/guide_router.md.5cf0d342.lean.js @@ -0,0 +1,261 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u8DEF\u7531","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u914D\u7F6E","slug":"\u914D\u7F6E"},{"level":3,"title":"\u6A21\u5757\u8BF4\u660E","slug":"\u6A21\u5757\u8BF4\u660E"},{"level":3,"title":"\u591A\u7EA7\u8DEF\u7531","slug":"\u591A\u7EA7\u8DEF\u7531"},{"level":3,"title":"Meta \u914D\u7F6E\u8BF4\u660E","slug":"meta-\u914D\u7F6E\u8BF4\u660E"},{"level":3,"title":"\u5916\u90E8\u9875\u9762\u5D4C\u5957","slug":"\u5916\u90E8\u9875\u9762\u5D4C\u5957"},{"level":3,"title":"\u5916\u94FE","slug":"\u5916\u94FE"},{"level":3,"title":"\u52A8\u6001\u8DEF\u7531Tab\u81EA\u52A8\u5173\u95ED\u529F\u80FD","slug":"\u52A8\u6001\u8DEF\u7531tab\u81EA\u52A8\u5173\u95ED\u529F\u80FD"},{"level":2,"title":"\u56FE\u6807","slug":"\u56FE\u6807"},{"level":2,"title":"\u65B0\u589E\u8DEF\u7531","slug":"\u65B0\u589E\u8DEF\u7531"},{"level":3,"title":"\u5982\u4F55\u65B0\u589E\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757","slug":"\u5982\u4F55\u65B0\u589E\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757"},{"level":3,"title":"\u9A8C\u8BC1","slug":"\u9A8C\u8BC1"},{"level":2,"title":"\u8DEF\u7531\u5237\u65B0","slug":"\u8DEF\u7531\u5237\u65B0"},{"level":3,"title":"\u5B9E\u73B0","slug":"\u5B9E\u73B0"},{"level":3,"title":"Redirect","slug":"redirect"},{"level":2,"title":"\u9875\u9762\u8DF3\u8F6C","slug":"\u9875\u9762\u8DF3\u8F6C"},{"level":3,"title":"\u65B9\u5F0F","slug":"\u65B9\u5F0F"},{"level":2,"title":"\u591A\u6807\u7B7E\u9875","slug":"\u591A\u6807\u7B7E\u9875"},{"level":3,"title":"\u5982\u4F55\u5F00\u542F\u9875\u9762\u7F13\u5B58","slug":"\u5982\u4F55\u5F00\u542F\u9875\u9762\u7F13\u5B58"},{"level":3,"title":"\u5982\u4F55\u8BA9\u67D0\u4E2A\u9875\u9762\u4E0D\u7F13\u5B58","slug":"\u5982\u4F55\u8BA9\u67D0\u4E2A\u9875\u9762\u4E0D\u7F13\u5B58"},{"level":2,"title":"\u5982\u4F55\u66F4\u6539\u9996\u9875\u8DEF\u7531","slug":"\u5982\u4F55\u66F4\u6539\u9996\u9875\u8DEF\u7531"}],"relativePath":"guide/router.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

\u8DEF\u7531

\u9879\u76EE\u8DEF\u7531\u914D\u7F6E\u5B58\u653E\u4E8E src/router/routes \u4E0B\u9762\u3002 src/router/routes/modules\u7528\u4E8E\u5B58\u653E\u8DEF\u7531\u6A21\u5757\uFF0C\u5728\u8BE5\u76EE\u5F55\u4E0B\u7684\u6587\u4EF6\u4F1A\u81EA\u52A8\u6CE8\u518C\u3002

\u914D\u7F6E

\u6A21\u5757\u8BF4\u660E

\u5728 src/router/routes/modules \u5185\u7684 .ts \u6587\u4EF6\u4F1A\u88AB\u89C6\u4E3A\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757\u3002

\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757\u5305\u542B\u4EE5\u4E0B\u7ED3\u6784

import type { AppRouteModule } from '/@/router/types';
+
+import { LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+
+const dashboard: AppRouteModule = {
+  path: '/dashboard',
+  name: 'Dashboard',
+  component: LAYOUT,
+  redirect: '/dashboard/analysis',
+  meta: {
+    icon: 'ion:grid-outline',
+    title: t('routes.dashboard.dashboard'),
+  },
+  children: [
+    {
+      path: 'analysis',
+      name: 'Analysis',
+      component: () => import('/@/views/dashboard/analysis/index.vue'),
+      meta: {
+        affix: true,
+        title: t('routes.dashboard.analysis'),
+      },
+    },
+    {
+      path: 'workbench',
+      name: 'Workbench',
+      component: () => import('/@/views/dashboard/workbench/index.vue'),
+      meta: {
+        title: t('routes.dashboard.workbench'),
+      },
+    },
+  ],
+};
+export default dashboard;
+

\u591A\u7EA7\u8DEF\u7531

\u6CE8\u610F\u4E8B\u9879

  • \u6574\u4E2A\u9879\u76EE\u6240\u6709\u8DEF\u7531 name \u4E0D\u80FD\u91CD\u590D
  • \u6240\u6709\u7684\u591A\u7EA7\u8DEF\u7531\u6700\u7EC8\u90FD\u4F1A\u8F6C\u6210\u4E8C\u7EA7\u8DEF\u7531\uFF0C\u6240\u4EE5\u4E0D\u80FD\u5185\u5D4C\u5B50\u8DEF\u7531
  • \u9664\u4E86 layout \u5BF9\u5E94\u7684 path \u524D\u9762\u9700\u8981\u52A0 /\uFF0C\u5176\u4F59\u5B50\u8DEF\u7531\u90FD\u4E0D\u8981\u4EE5/\u5F00\u5934

\u793A\u4F8B

import type { AppRouteModule } from '/@/router/types';
+import { getParentLayout, LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+const permission: AppRouteModule = {
+  path: '/level',
+  name: 'Level',
+  component: LAYOUT,
+  redirect: '/level/menu1/menu1-1/menu1-1-1',
+  meta: {
+    icon: 'ion:menu-outline',
+    title: t('routes.demo.level.level'),
+  },
+
+  children: [
+    {
+      path: 'tabs/:id', 
+      name: 'TabsParams',
+      component: getParentLayout('TabsParams'),
+      meta: {
+        carryParam: true,
+        hidePathForChildren: true, // \u672C\u7EA7path\u5C06\u4F1A\u5728\u5B50\u7EA7\u83DC\u5355\u4E2D\u5408\u6210\u5B8C\u6574path\u65F6\u4F1A\u5FFD\u7565\u8FD9\u4E00\u5C42\u7EA7
+      },
+      children: [
+        path: 'tabs/id1', // \u5176\u4E0A\u7EA7\u6709\u6807\u8BB0hidePathForChildren\uFF0C\u6240\u4EE5\u672C\u7EA7\u5728\u751F\u6210\u83DC\u5355\u65F6\u6700\u7EC8\u7684path\u4E3A  /level/tabs/id1
+        name: 'TabsParams',
+        component: getParentLayout('TabsParams'),
+        meta: {
+          carryParam: true,
+          ignoreRoute: true,  // \u672C\u8DEF\u7531\u4EC5\u7528\u4E8E\u83DC\u5355\u751F\u6210\uFF0C\u4E0D\u4F1A\u5728\u5B9E\u9645\u7684\u8DEF\u7531\u8868\u4E2D\u51FA\u73B0
+        },
+      ]
+    },
+    {
+      path: 'menu1',
+      name: 'Menu1Demo',
+      component: getParentLayout('Menu1Demo'),
+      meta: {
+        title: 'Menu1',
+      },
+      redirect: '/level/menu1/menu1-1/menu1-1-1',
+      children: [
+        {
+          path: 'menu1-1',
+          name: 'Menu11Demo',
+          component: getParentLayout('Menu11Demo'),
+          meta: {
+            title: 'Menu1-1',
+          },
+          redirect: '/level/menu1/menu1-1/menu1-1-1',
+          children: [
+            {
+              path: 'menu1-1-1',
+              name: 'Menu111Demo',
+              component: () => import('/@/views/demo/level/Menu111.vue'),
+              meta: {
+                title: 'Menu111',
+              },
+            },
+          ],
+        },
+      ],
+    },
+  ],
+};
+
+export default permission;
+

Meta \u914D\u7F6E\u8BF4\u660E

export interface RouteMeta {
+  // \u8DEF\u7531title  \u4E00\u822C\u5FC5\u586B
+  title: string;
+  // \u52A8\u6001\u8DEF\u7531\u53EF\u6253\u5F00Tab\u9875\u6570
+  dynamicLevel?: number;
+  // \u52A8\u6001\u8DEF\u7531\u7684\u5B9E\u9645Path, \u5373\u53BB\u9664\u8DEF\u7531\u7684\u52A8\u6001\u90E8\u5206;
+  realPath?: string;
+  // \u662F\u5426\u5FFD\u7565\u6743\u9650\uFF0C\u53EA\u5728\u6743\u9650\u6A21\u5F0F\u4E3ARole\u7684\u65F6\u5019\u6709\u6548
+  ignoreAuth?: boolean;
+  // \u53EF\u4EE5\u8BBF\u95EE\u7684\u89D2\u8272\uFF0C\u53EA\u5728\u6743\u9650\u6A21\u5F0F\u4E3ARole\u7684\u65F6\u5019\u6709\u6548
+  roles?: RoleEnum[];
+  // \u662F\u5426\u5FFD\u7565KeepAlive\u7F13\u5B58
+  ignoreKeepAlive?: boolean;
+  // \u662F\u5426\u56FA\u5B9A\u6807\u7B7E
+  affix?: boolean;
+  // \u56FE\u6807\uFF0C\u4E5F\u662F\u83DC\u5355\u56FE\u6807
+  icon?: string;
+  // \u5185\u5D4Ciframe\u7684\u5730\u5740
+  frameSrc?: string;
+  // \u6307\u5B9A\u8BE5\u8DEF\u7531\u5207\u6362\u7684\u52A8\u753B\u540D
+  transitionName?: string;
+  // \u9690\u85CF\u8BE5\u8DEF\u7531\u5728\u9762\u5305\u5C51\u4E0A\u9762\u7684\u663E\u793A
+  hideBreadcrumb?: boolean;
+  // \u5982\u679C\u8BE5\u8DEF\u7531\u4F1A\u643A\u5E26\u53C2\u6570\uFF0C\u4E14\u9700\u8981\u5728tab\u9875\u4E0A\u9762\u663E\u793A\u3002\u5219\u9700\u8981\u8BBE\u7F6E\u4E3Atrue
+  carryParam?: boolean;
+  // \u9690\u85CF\u6240\u6709\u5B50\u83DC\u5355
+  hideChildrenInMenu?: boolean;
+  // \u5F53\u524D\u6FC0\u6D3B\u7684\u83DC\u5355\u3002\u7528\u4E8E\u914D\u7F6E\u8BE6\u60C5\u9875\u65F6\u5DE6\u4FA7\u6FC0\u6D3B\u7684\u83DC\u5355\u8DEF\u5F84
+  currentActiveMenu?: string;
+  // \u5F53\u524D\u8DEF\u7531\u4E0D\u518D\u6807\u7B7E\u9875\u663E\u793A
+  hideTab?: boolean;
+  // \u5F53\u524D\u8DEF\u7531\u4E0D\u518D\u83DC\u5355\u663E\u793A
+  hideMenu?: boolean;
+  // \u83DC\u5355\u6392\u5E8F\uFF0C\u53EA\u5BF9\u7B2C\u4E00\u7EA7\u6709\u6548
+  orderNo?: number;
+  // \u5FFD\u7565\u8DEF\u7531\u3002\u7528\u4E8E\u5728ROUTE_MAPPING\u4EE5\u53CABACK\u6743\u9650\u6A21\u5F0F\u4E0B\uFF0C\u751F\u6210\u5BF9\u5E94\u7684\u83DC\u5355\u800C\u5FFD\u7565\u8DEF\u7531\u30022.5.3\u4EE5\u4E0A\u7248\u672C\u6709\u6548
+  ignoreRoute?: boolean;
+  // \u662F\u5426\u5728\u5B50\u7EA7\u83DC\u5355\u7684\u5B8C\u6574path\u4E2D\u5FFD\u7565\u672C\u7EA7path\u30022.5.3\u4EE5\u4E0A\u7248\u672C\u6709\u6548
+  hidePathForChildren?: boolean;
+}
+

\u5916\u90E8\u9875\u9762\u5D4C\u5957

\u53EA\u9700\u8981\u5C06 frameSrc \u8BBE\u7F6E\u4E3A\u9700\u8981\u8DF3\u8F6C\u7684\u5730\u5740\u5373\u53EF

const IFrame = () => import('/@/views/sys/iframe/FrameBlank.vue');
+{
+  path: 'doc',
+  name: 'Doc',
+  component: IFrame,
+  meta: {
+    frameSrc: 'https://vvbin.cn/doc-next/',
+    title: t('routes.demo.iframe.doc'),
+  },
+},
+

\u5916\u94FE

\u53EA\u9700\u8981\u5C06 path \u8BBE\u7F6E\u4E3A\u9700\u8981\u8DF3\u8F6C\u7684HTTP \u5730\u5740\u5373\u53EF

{
+  path: 'https://vvbin.cn/doc-next/',
+  name: 'DocExternal',
+  component: IFrame,
+  meta: {
+    title: t('routes.demo.iframe.docExternal'),
+  },
+}
+

\u52A8\u6001\u8DEF\u7531Tab\u81EA\u52A8\u5173\u95ED\u529F\u80FD

\u82E5\u9700\u8981\u5F00\u542F\u8BE5\u529F\u80FD\uFF0C\u9700\u8981\u5728\u52A8\u6001\u8DEF\u7531\u7684meta\u4E2D\u8BBE\u7F6E\u5982\u4E0B\u4E24\u4E2A\u53C2\u6570\uFF1A

  • dynamicLevel \u6700\u5927\u80FD\u6253\u5F00\u7684Tab\u6807\u7B7E\u9875\u6570
  • realPath \u52A8\u6001\u8DEF\u7531\u5B9E\u9645\u8DEF\u5F84(\u8003\u8651\u5230\u52A8\u6001\u8DEF\u7531\u6709\u65F6\u5019\u53EF\u80FD\u5B58\u5728N\u5C42\u7684\u60C5\u51B5, \u4F8B\uFF1A/:id/:subId/:...), \u4E3A\u4E86\u51CF\u5C11\u8BA1\u7B97\u5F00\u9500, \u4F7F\u7528\u914D\u7F6E\u65B9\u5F0F\u4E8B\u5148\u89C4\u5B9A\u597D\u8DEF\u7531\u7684\u5B9E\u9645\u8DEF\u5F84(\u6CE8\u610F: \u8BE5\u53C2\u6570\u82E5\u4E0D\u8BBE\u7F6E\uFF0C\u5C06\u65E0\u6CD5\u4F7F\u7528\u8BE5\u529F\u80FD)
{
+  path: 'detail/:id',
+  name: 'TabDetail',
+  component: () => import('/@/views/demo/feat/tabs/TabDetail.vue'),
+  meta: {
+    currentActiveMenu: '/feat/tabs',
+    title: t('routes.demo.feat.tabDetail'),
+    hideMenu: true,
+    dynamicLevel: 3,
+    realPath: '/feat/tabs/detail',
+  },
+}
+

\u56FE\u6807

\u8FD9\u91CC\u7684 icon \u914D\u7F6E\uFF0C\u4F1A\u540C\u6B65\u5230 \u83DC\u5355\uFF08icon \u7684\u503C\u53EF\u4EE5\u67E5\u770B\u6B64\u5904\uFF09\u3002

\u65B0\u589E\u8DEF\u7531

\u5982\u4F55\u65B0\u589E\u4E00\u4E2A\u8DEF\u7531\u6A21\u5757

  1. \u5728 src/router/routes/modules \u5185\u65B0\u589E\u4E00\u4E2A\u6A21\u5757\u6587\u4EF6\u3002

\u793A\u4F8B\uFF0C\u65B0\u589E test.ts \u6587\u4EF6

import type { AppRouteModule } from '/@/router/types';
+import { LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+
+const dashboard: AppRouteModule = {
+  path: '/about',
+  name: 'About',
+  component: LAYOUT,
+  redirect: '/about/index',
+  meta: {
+    icon: 'simple-icons:about-dot-me',
+    title: t('routes.dashboard.about'),
+  },
+  children: [
+    {
+      path: 'index',
+      name: 'AboutPage',
+      component: () => import('/@/views/sys/about/index.vue'),
+      meta: {
+        title: t('routes.dashboard.about'),
+        icon: 'simple-icons:about-dot-me',
+      },
+    },
+  ],
+};
+
+export default dashboard;
+

\u6B64\u65F6\u8DEF\u7531\u5DF2\u6DFB\u52A0\u5B8C\u6210\uFF0C\u4E0D\u9700\u8981\u624B\u52A8\u5F15\u5165\uFF0C\u653E\u5728src/router/routes/modules \u5185\u7684\u6587\u4EF6\u4F1A\u81EA\u52A8\u88AB\u52A0\u8F7D\u3002

\u9A8C\u8BC1

\u8BBF\u95EE ip:\u7AEF\u53E3/about/index \u51FA\u73B0\u5BF9\u5E94\u7EC4\u4EF6\u5185\u5BB9\u5373\u4EE3\u8868\u6210\u529F

\u8DEF\u7531\u5237\u65B0

\u9879\u76EE\u4E2D\u91C7\u7528\u7684\u662F\u91CD\u5B9A\u5411\u65B9\u5F0F

\u5B9E\u73B0

import { useRedo } from '/@/hooks/web/usePage';
+import { defineComponent } from 'vue';
+export default defineComponent({
+  setup() {
+    const redo = useRedo();
+    // \u6267\u884C\u5237\u65B0
+    redo();
+    return {};
+  },
+});
+

Redirect

src/views/sys/redirect/index.vue

import { defineComponent, unref } from 'vue';
+import { useRouter } from 'vue-router';
+export default defineComponent({
+  name: 'Redirect',
+  setup() {
+    const { currentRoute, replace } = useRouter();
+    const { params, query } = unref(currentRoute);
+    const { path } = params;
+    const _path = Array.isArray(path) ? path.join('/') : path;
+    replace({
+      path: '/' + _path,
+      query,
+    });
+    return {};
+  },
+});
+

\u9875\u9762\u8DF3\u8F6C

\u9875\u9762\u8DF3\u8F6C\u5EFA\u8BAE\u91C7\u7528\u9879\u76EE\u63D0\u4F9B\u7684 useGo

\u65B9\u5F0F

import { useGo } from '/@/hooks/web/usePage';
+import { defineComponent } from 'vue';
+export default defineComponent({
+  setup() {
+    const go = useGo();
+
+    // \u6267\u884C\u5237\u65B0
+    go();
+    go(PageEnum.Home);
+    return {};
+  },
+});
+

\u591A\u6807\u7B7E\u9875

\u6807\u7B7E\u9875\u4F7F\u7528\u7684\u662F keep-alive \u548C router-view \u5B9E\u73B0\uFF0C\u5B9E\u73B0\u5207\u6362 tab \u540E\u8FD8\u80FD\u4FDD\u5B58\u5207\u6362\u4E4B\u524D\u7684\u72B6\u6001\u3002

\u5982\u4F55\u5F00\u542F\u9875\u9762\u7F13\u5B58

\u5F00\u542F\u7F13\u5B58\u6709 3 \u4E2A\u6761\u4EF6

  1. \u5728 src/settings/projectSetting.ts \u5185\u5C06openKeepAlive \u8BBE\u7F6E\u4E3A true
  2. \u8DEF\u7531\u8BBE\u7F6E name\uFF0C\u4E14\u4E0D\u80FD\u91CD\u590D
  3. \u8DEF\u7531\u5BF9\u5E94\u7684\u7EC4\u4EF6\u52A0\u4E0A name\uFF0C\u4E0E\u8DEF\u7531\u8BBE\u7F6E\u7684 name \u4FDD\u6301\u4E00\u81F4
 {
+   ...,
+    // name
+    name: 'Login',
+    // \u5BF9\u5E94\u7EC4\u4EF6\u7EC4\u4EF6\u7684name
+    component: () => import('/@/views/sys/login/index.vue'),
+    ...
+  },
+
+  // /@/views/sys/login/index.vue
+  export default defineComponent({
+    // \u9700\u8981\u548C\u8DEF\u7531\u7684name\u4E00\u81F4
+    name:"Login"
+  });
+

\u6CE8\u610F

keep-alive \u751F\u6548\u7684\u524D\u63D0\u662F\uFF1A\u9700\u8981\u5C06\u8DEF\u7531\u7684 name \u5C5E\u6027\u53CA\u5BF9\u5E94\u7684\u9875\u9762\u7684 name \u8BBE\u7F6E\u6210\u4E00\u6837\u3002\u56E0\u4E3A\uFF1A

include - \u5B57\u7B26\u4E32\u6216\u6B63\u5219\u8868\u8FBE\u5F0F\uFF0C\u53EA\u6709\u540D\u79F0\u5339\u914D\u7684\u7EC4\u4EF6\u4F1A\u88AB\u7F13\u5B58

\u5982\u4F55\u8BA9\u67D0\u4E2A\u9875\u9762\u4E0D\u7F13\u5B58

\u53EF\u5728 router.meta \u4E0B\u914D\u7F6E

\u53EF\u4EE5\u5C06 ignoreKeepAlive \u914D\u7F6E\u6210 true \u5373\u53EF\u5173\u95ED\u7F13\u5B58\u3002

export interface RouteMeta {
+  // \u662F\u5426\u5FFD\u7565KeepAlive\u7F13\u5B58
+  ignoreKeepAlive?: boolean;
+}
+

\u5982\u4F55\u66F4\u6539\u9996\u9875\u8DEF\u7531

\u9996\u9875\u8DEF\u7531\u6307\u7684\u662F\u5E94\u7528\u7A0B\u5E8F\u4E2D\u7684\u9ED8\u8BA4\u8DEF\u7531\uFF0C\u5F53\u4E0D\u8F93\u5165\u5176\u4ED6\u4EFB\u4F55\u8DEF\u7531\u65F6\uFF0C\u4F1A\u81EA\u52A8\u91CD\u5B9A\u5411\u5230\u8BE5\u8DEF\u7531\u4E0B\uFF0C\u5E76\u4E14\u8BE5\u8DEF\u7531\u5728Tab\u4E0A\u662F\u56FA\u5B9A\u7684\uFF0C\u5373\u4F7F\u8BBE\u7F6Eaffix: false\u4E5F\u4E0D\u5141\u8BB8\u5173\u95ED

\u4F8B\uFF1A\u9996\u9875\u8DEF\u7531\u914D\u7F6E\u7684\u662F/dashboard/analysis\uFF0C\u90A3\u4E48\u5F53\u76F4\u63A5\u8BBF\u95EE http://localhost:3100/ \u4F1A\u81EA\u52A8\u8DF3\u8F6C\u5230http://localhost:3100/#/dashboard/analysis \u4E0A(\u7528\u6237\u5DF2\u767B\u5F55\u7684\u60C5\u51B5\u4E0B)

\u53EF\u4EE5\u5C06pageEnum.ts\u4E2D\u7684BASE_HOME\u66F4\u6539\u4E3A\u9700\u8981\u4F60\u60F3\u8BBE\u7F6E\u7684\u9996\u9875\u5373\u53EF

export enum PageEnum {
+    // basic home path
+    // \u66F4\u6539\u6B64\u5904\u5373\u53EF
+    BASE_HOME = '/dashboard',
+}
+
+
__VP_STATIC_END__`,60),e=[o];function c(l,u,r,i,k,d){return a(),s("div",null,e)}var g=n(p,[["render",c]]);export{h as __pageData,g as default}; diff --git a/assets/guide_settings.md.87a2cccb.js b/assets/guide_settings.md.87a2cccb.js new file mode 100644 index 00000000..263e0bf1 --- /dev/null +++ b/assets/guide_settings.md.87a2cccb.js @@ -0,0 +1,370 @@ +import{_ as n,f as s,e as a,N as p}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"\u9879\u76EE\u914D\u7F6E\u9879","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u73AF\u5883\u53D8\u91CF\u914D\u7F6E","slug":"\u73AF\u5883\u53D8\u91CF\u914D\u7F6E"},{"level":3,"title":"\u914D\u7F6E\u9879\u8BF4\u660E","slug":"\u914D\u7F6E\u9879\u8BF4\u660E"},{"level":3,"title":".env","slug":"env"},{"level":3,"title":".env.development","slug":"env-development"},{"level":3,"title":".env.production","slug":"env-production"},{"level":2,"title":"\u751F\u4EA7\u73AF\u5883\u52A8\u6001\u914D\u7F6E","slug":"\u751F\u4EA7\u73AF\u5883\u52A8\u6001\u914D\u7F6E"},{"level":3,"title":"\u8BF4\u660E","slug":"\u8BF4\u660E"},{"level":3,"title":"\u4F5C\u7528","slug":"\u4F5C\u7528"},{"level":3,"title":"\u5982\u4F55\u83B7\u53D6\u5168\u5C40\u53D8\u91CF","slug":"\u5982\u4F55\u83B7\u53D6\u5168\u5C40\u53D8\u91CF"},{"level":3,"title":"\u5982\u4F55\u65B0\u589E(\u65B0\u589E\u4E00\u4E2A\u53EF\u52A8\u6001\u4FEE\u6539\u7684\u914D\u7F6E\u9879)","slug":"\u5982\u4F55\u65B0\u589E-\u65B0\u589E\u4E00\u4E2A\u53EF\u52A8\u6001\u4FEE\u6539\u7684\u914D\u7F6E\u9879"},{"level":2,"title":"\u9879\u76EE\u914D\u7F6E","slug":"\u9879\u76EE\u914D\u7F6E"},{"level":3,"title":"\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84","slug":"\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84"},{"level":3,"title":"\u8BF4\u660E","slug":"\u8BF4\u660E-1"},{"level":2,"title":"\u7F13\u5B58\u914D\u7F6E","slug":"\u7F13\u5B58\u914D\u7F6E"},{"level":2,"title":"\u591A\u8BED\u8A00\u914D\u7F6E","slug":"\u591A\u8BED\u8A00\u914D\u7F6E"},{"level":2,"title":"\u4E3B\u9898\u8272\u914D\u7F6E","slug":"\u4E3B\u9898\u8272\u914D\u7F6E"},{"level":2,"title":"\u6837\u5F0F\u914D\u7F6E","slug":"\u6837\u5F0F\u914D\u7F6E"},{"level":3,"title":"css \u524D\u7F00\u8BBE\u7F6E","slug":"css-\u524D\u7F00\u8BBE\u7F6E"},{"level":3,"title":"\u524D\u7F00\u4F7F\u7528","slug":"\u524D\u7F00\u4F7F\u7528"},{"level":2,"title":"\u989C\u8272\u914D\u7F6E","slug":"\u989C\u8272\u914D\u7F6E"},{"level":2,"title":"\u7EC4\u4EF6\u9ED8\u8BA4\u53C2\u6570\u914D\u7F6E","slug":"\u7EC4\u4EF6\u9ED8\u8BA4\u53C2\u6570\u914D\u7F6E"}],"relativePath":"guide/settings.md","lastUpdated":1694442156385}',t={},o=p(`

\u9879\u76EE\u914D\u7F6E\u9879

\u7528\u4E8E\u4FEE\u6539\u9879\u76EE\u7684\u914D\u8272\u3001\u5E03\u5C40\u3001\u7F13\u5B58\u3001\u591A\u8BED\u8A00\u3001\u7EC4\u4EF6\u9ED8\u8BA4\u914D\u7F6E

\u73AF\u5883\u53D8\u91CF\u914D\u7F6E

\u9879\u76EE\u7684\u73AF\u5883\u53D8\u91CF\u914D\u7F6E\u4F4D\u4E8E\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u7684 .env\u3001.env.development\u3001.env.production

\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 Vite \u6587\u6863

.env                # \u5728\u6240\u6709\u7684\u73AF\u5883\u4E2D\u88AB\u8F7D\u5165
+.env.local          # \u5728\u6240\u6709\u7684\u73AF\u5883\u4E2D\u88AB\u8F7D\u5165\uFF0C\u4F46\u4F1A\u88AB git \u5FFD\u7565
+.env.[mode]         # \u53EA\u5728\u6307\u5B9A\u7684\u6A21\u5F0F\u4E2D\u88AB\u8F7D\u5165
+.env.[mode].local   # \u53EA\u5728\u6307\u5B9A\u7684\u6A21\u5F0F\u4E2D\u88AB\u8F7D\u5165\uFF0C\u4F46\u4F1A\u88AB git \u5FFD\u7565
+
+

\u6E29\u99A8\u63D0\u9192

  • \u53EA\u6709\u4EE5 VITE_ \u5F00\u5934\u7684\u53D8\u91CF\u4F1A\u88AB\u5D4C\u5165\u5230\u5BA2\u6237\u7AEF\u4FA7\u7684\u5305\u4E2D\uFF0C\u4F60\u53EF\u4EE5\u9879\u76EE\u4EE3\u7801\u4E2D\u8FD9\u6837\u8BBF\u95EE\u5B83\u4EEC\uFF1A
console.log(import.meta.env.VITE_PROT);
+
  • \u4EE5 VITE_GLOB_* \u5F00\u5934\u7684\u7684\u53D8\u91CF\uFF0C\u5728\u6253\u5305\u7684\u65F6\u5019\uFF0C\u4F1A\u88AB\u52A0\u5165_app.config.js\u914D\u7F6E\u6587\u4EF6\u5F53\u4E2D.

\u914D\u7F6E\u9879\u8BF4\u660E

.env

\u6240\u6709\u73AF\u5883\u9002\u7528

# \u7AEF\u53E3\u53F7
+VITE_PORT=3100
+# \u7F51\u7AD9\u6807\u9898
+VITE_GLOB_APP_TITLE=vben admin
+# \u7B80\u79F0\uFF0C\u7528\u4E8E\u914D\u7F6E\u6587\u4EF6\u540D\u5B57 \u4E0D\u8981\u51FA\u73B0\u7A7A\u683C\u3001\u6570\u5B57\u5F00\u5934\u7B49\u7279\u6B8A\u5B57\u7B26
+VITE_GLOB_APP_SHORT_NAME=vben_admin
+

.env.development

\u5F00\u53D1\u73AF\u5883\u9002\u7528

# \u662F\u5426\u5F00\u542Fmock\u6570\u636E\uFF0C\u5173\u95ED\u65F6\u9700\u8981\u81EA\u884C\u5BF9\u63A5\u540E\u53F0\u63A5\u53E3
+VITE_USE_MOCK=true
+# \u8D44\u6E90\u516C\u5171\u8DEF\u5F84,\u9700\u8981\u4EE5 /\u5F00\u5934\u548C\u7ED3\u5C3E
+VITE_PUBLIC_PATH=/
+# \u662F\u5426\u5220\u9664Console.log
+VITE_DROP_CONSOLE=false
+# \u672C\u5730\u5F00\u53D1\u4EE3\u7406\uFF0C\u53EF\u4EE5\u89E3\u51B3\u8DE8\u57DF\u53CA\u591A\u5730\u5740\u4EE3\u7406
+# \u5982\u679C\u63A5\u53E3\u5730\u5740\u5339\u914D\u5230\uFF0C\u5219\u4F1A\u8F6C\u53D1\u5230http://localhost:3000\uFF0C\u9632\u6B62\u672C\u5730\u51FA\u73B0\u8DE8\u57DF\u95EE\u9898
+# \u53EF\u4EE5\u6709\u591A\u4E2A\uFF0C\u6CE8\u610F\u591A\u4E2A\u4E0D\u80FD\u6362\u884C\uFF0C\u5426\u5219\u4EE3\u7406\u5C06\u4F1A\u5931\u6548
+VITE_PROXY=[["/api","http://localhost:3000"],["api1","http://localhost:3001"],["/upload","http://localhost:3001/upload"]]
+# \u63A5\u53E3\u5730\u5740
+# \u5982\u679C\u6CA1\u6709\u8DE8\u57DF\u95EE\u9898\uFF0C\u76F4\u63A5\u5728\u8FD9\u91CC\u914D\u7F6E\u5373\u53EF
+VITE_GLOB_API_URL=/api
+# \u6587\u4EF6\u4E0A\u4F20\u63A5\u53E3  \u53EF\u9009
+VITE_GLOB_UPLOAD_URL=/upload
+# \u63A5\u53E3\u5730\u5740\u524D\u7F00\uFF0C\u6709\u4E9B\u7CFB\u7EDF\u6240\u6709\u63A5\u53E3\u5730\u5740\u90FD\u6709\u524D\u7F00\uFF0C\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EDF\u4E00\u52A0\uFF0C\u65B9\u4FBF\u5207\u6362
+VITE_GLOB_API_URL_PREFIX=
+

\u6CE8\u610F

\u8FD9\u91CC\u914D\u7F6E\u7684 VITE_PROXY \u4EE5\u53CA VITE_GLOB_API_URL, /api \u9700\u8981\u662F\u552F\u4E00\u7684\uFF0C\u4E0D\u8981\u548C\u63A5\u53E3\u6709\u7684\u540D\u5B57\u51B2\u7A81

\u5982\u679C\u4F60\u7684\u63A5\u53E3\u662F http://localhost:3000/api \u4E4B\u7C7B\u7684\uFF0C\u8BF7\u8003\u8651\u5C06 VITE_GLOB_API_URL=/xxxx \u6362\u6210\u522B\u7684\u540D\u5B57

.env.production

\u751F\u4EA7\u73AF\u5883\u9002\u7528

# \u662F\u5426\u5F00\u542Fmock
+VITE_USE_MOCK=true
+# \u63A5\u53E3\u5730\u5740 \u53EF\u4EE5\u7531nginx\u505A\u8F6C\u53D1\u6216\u8005\u76F4\u63A5\u5199\u5B9E\u9645\u5730\u5740
+VITE_GLOB_API_URL=/api
+# \u6587\u4EF6\u4E0A\u4F20\u5730\u5740 \u53EF\u4EE5\u7531nginx\u505A\u8F6C\u53D1\u6216\u8005\u76F4\u63A5\u5199\u5B9E\u9645\u5730\u5740
+VITE_GLOB_UPLOAD_URL=/upload
+# \u63A5\u53E3\u5730\u5740\u524D\u7F00\uFF0C\u6709\u4E9B\u7CFB\u7EDF\u6240\u6709\u63A5\u53E3\u5730\u5740\u90FD\u6709\u524D\u7F00\uFF0C\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EDF\u4E00\u52A0\uFF0C\u65B9\u4FBF\u5207\u6362
+VITE_GLOB_API_URL_PREFIX=
+# \u662F\u5426\u5220\u9664Console.log
+VITE_DROP_CONSOLE=true
+# \u8D44\u6E90\u516C\u5171\u8DEF\u5F84,\u9700\u8981\u4EE5 / \u5F00\u5934\u548C\u7ED3\u5C3E
+VITE_PUBLIC_PATH=/
+# \u6253\u5305\u662F\u5426\u8F93\u51FAgz\uFF5Cbr\u6587\u4EF6
+# \u53EF\u9009: gzip | brotli | none
+# \u4E5F\u53EF\u4EE5\u6709\u591A\u4E2A, \u4F8B\u5982 \u2018gzip\u2019|'brotli',\u8FD9\u6837\u4F1A\u540C\u65F6\u751F\u6210 .gz\u548C.br\u6587\u4EF6
+VITE_BUILD_COMPRESS = 'gzip'
+# \u6253\u5305\u662F\u5426\u538B\u7F29\u56FE\u7247
+VITE_USE_IMAGEMIN = false
+# \u6253\u5305\u662F\u5426\u5F00\u542Fpwa\u529F\u80FD
+VITE_USE_PWA = false
+# \u662F\u5426\u517C\u5BB9\u65E7\u7248\u6D4F\u89C8\u5668\u3002\u5F00\u542F\u540E\u6253\u5305\u65F6\u95F4\u4F1A\u6162\u4E00\u500D\u5DE6\u53F3\u3002\u4F1A\u591A\u6253\u51FA\u65E7\u6D4F\u89C8\u5668\u517C\u5BB9\u5305,\u4E14\u4F1A\u6839\u636E\u6D4F\u89C8\u5668\u517C\u5BB9\u6027\u81EA\u52A8\u4F7F\u7528\u76F8\u5E94\u7684\u7248\u672C
+VITE_LEGACY = false
+

\u751F\u4EA7\u73AF\u5883\u52A8\u6001\u914D\u7F6E

\u8BF4\u660E

\u5F53\u6267\u884Cyarn build\u6784\u5EFA\u9879\u76EE\u4E4B\u540E\uFF0C\u4F1A\u81EA\u52A8\u751F\u6210 _app.config.js \u6587\u4EF6\u5E76\u63D2\u5165 index.html\u3002

\u6CE8\u610F: \u5F00\u53D1\u73AF\u5883\u4E0D\u4F1A\u751F\u6210

// _app.config.js
+// \u53D8\u91CF\u540D\u547D\u540D\u89C4\u5219  __PRODUCTION__xxx_CONF__   xxx\uFF1A\u4E3A.env\u914D\u7F6E\u7684VITE_GLOB_APP_SHORT_NAME
+window.__PRODUCTION__VUE_VBEN_ADMIN__CONF__ = {
+  VITE_GLOB_APP_TITLE: 'vben admin',
+  VITE_GLOB_APP_SHORT_NAME: 'vue_vben_admin',
+  VITE_GLOB_API_URL: '/app',
+  VITE_GLOB_API_URL_PREFIX: '/',
+  VITE_GLOB_UPLOAD_URL: '/upload',
+};
+

\u4F5C\u7528

_app.config.js \u7528\u4E8E\u9879\u76EE\u5728\u6253\u5305\u540E\uFF0C\u9700\u8981\u52A8\u6001\u4FEE\u6539\u914D\u7F6E\u7684\u9700\u6C42\uFF0C\u5982\u63A5\u53E3\u5730\u5740\u3002\u4E0D\u7528\u91CD\u65B0\u8FDB\u884C\u6253\u5305\uFF0C\u53EF\u5728\u6253\u5305\u540E\u4FEE\u6539 /dist/_app.config.js \u5185\u7684\u53D8\u91CF\uFF0C\u5237\u65B0\u5373\u53EF\u66F4\u65B0\u4EE3\u7801\u5185\u7684\u5C40\u90E8\u53D8\u91CF\u3002

\u5982\u4F55\u83B7\u53D6\u5168\u5C40\u53D8\u91CF

\u60F3\u8981\u83B7\u53D6 _app.config.js \u5185\u7684\u53D8\u91CF\uFF0C\u53EF\u4EE5\u4F7F\u7528 src/hooks/setting/index.ts \u63D0\u4F9B\u7684\u51FD\u6570\u6765\u8FDB\u884C\u83B7\u53D6

\u5982\u4F55\u65B0\u589E(\u65B0\u589E\u4E00\u4E2A\u53EF\u52A8\u6001\u4FEE\u6539\u7684\u914D\u7F6E\u9879)

  1. \u9996\u5148\u5728 .env \u6216\u8005\u5BF9\u5E94\u7684\u5F00\u53D1\u73AF\u5883\u914D\u7F6E\u6587\u4EF6\u5185\uFF0C\u65B0\u589E\u9700\u8981\u53EF\u52A8\u6001\u914D\u7F6E\u7684\u53D8\u91CF\uFF0C\u9700\u8981\u4EE5 VITE_GLOB_\u5F00\u5934

  2. VITE_GLOB_ \u5F00\u5934\u7684\u53D8\u91CF\u4F1A\u81EA\u52A8\u52A0\u5165\u73AF\u5883\u53D8\u91CF\uFF0C\u901A\u8FC7\u5728 types/config.d.ts \u5185\u4FEE\u6539 GlobEnvConfig \u548C GlobConfig \u4E24\u4E2A\u73AF\u5883\u53D8\u91CF\u7684\u503C\u6765\u5B9A\u4E49\u65B0\u6DFB\u52A0\u7684\u7C7B\u578B

  3. useGlobSetting \u51FD\u6570\u4E2D\u6DFB\u52A0\u521A\u65B0\u589E\u7684\u8FD4\u56DE\u503C\u5373\u53EF

const {
+  VITE_GLOB_APP_TITLE,
+  VITE_GLOB_API_URL,
+  VITE_GLOB_APP_SHORT_NAME,
+  VITE_GLOB_API_URL_PREFIX,
+  VITE_GLOB_UPLOAD_URL,
+} = ENV;
+
+export const useGlobSetting = (): SettingWrap => {
+  // Take global configuration
+  const glob: Readonly<GlobConfig> = {
+    title: VITE_GLOB_APP_TITLE,
+    apiUrl: VITE_GLOB_API_URL,
+    shortName: VITE_GLOB_APP_SHORT_NAME,
+    urlPrefix: VITE_GLOB_API_URL_PREFIX,
+    uploadUrl: VITE_GLOB_UPLOAD_URL
+  };
+  return glob as Readonly<GlobConfig>;
+};
+
+

\u9879\u76EE\u914D\u7F6E

WARNING

\u9879\u76EE\u914D\u7F6E\u6587\u4EF6\u7528\u4E8E\u914D\u7F6E\u9879\u76EE\u5185\u5C55\u793A\u7684\u5185\u5BB9\u3001\u5E03\u5C40\u3001\u6587\u672C\u7B49\u6548\u679C\uFF0C\u5B58\u4E8ElocalStorage\u4E2D\u3002\u5982\u679C\u66F4\u6539\u4E86\u9879\u76EE\u914D\u7F6E\uFF0C\u9700\u8981\u624B\u52A8\u6E05\u7A7A localStorage \u7F13\u5B58\uFF0C\u5237\u65B0\u91CD\u65B0\u767B\u5F55\u540E\u65B9\u53EF\u751F\u6548\u3002

\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84

src/settings/projectSetting.ts

\u8BF4\u660E

// ! \u6539\u52A8\u540E\u9700\u8981\u6E05\u7A7A\u6D4F\u89C8\u5668\u7F13\u5B58
+const setting: ProjectConfig = {
+  // \u662F\u5426\u663E\u793ASettingButton
+  showSettingButton: true,
+
+  // \u662F\u5426\u663E\u793A\u4E3B\u9898\u5207\u6362\u6309\u94AE
+  showDarkModeToggle: true,
+
+  // \u8BBE\u7F6E\u6309\u94AE\u4F4D\u7F6E \u53EF\u9009\u9879
+  // SettingButtonPositionEnum.AUTO: \u81EA\u52A8\u9009\u62E9
+  // SettingButtonPositionEnum.HEADER: \u4F4D\u4E8E\u5934\u90E8
+  // SettingButtonPositionEnum.FIXED: \u56FA\u5B9A\u5728\u53F3\u4FA7
+  settingButtonPosition: SettingButtonPositionEnum.AUTO,
+
+  // \u6743\u9650\u6A21\u5F0F,\u9ED8\u8BA4\u524D\u7AEF\u89D2\u8272\u6743\u9650\u6A21\u5F0F
+  // ROUTE_MAPPING: \u524D\u7AEF\u6A21\u5F0F\uFF08\u83DC\u5355\u7531\u8DEF\u7531\u751F\u6210\uFF0C\u9ED8\u8BA4\uFF09
+  // ROLE\uFF1A\u524D\u7AEF\u6A21\u5F0F\uFF08\u83DC\u5355\u8DEF\u7531\u5206\u5F00\uFF09
+  permissionMode: PermissionModeEnum.ROUTE_MAPPING,
+  // \u6743\u9650\u7F13\u5B58\u5B58\u653E\u4F4D\u7F6E\u3002\u9ED8\u8BA4\u5B58\u653E\u4E8ElocalStorage
+  permissionCacheType: CacheTypeEnum.LOCAL,
+  // \u4F1A\u8BDD\u8D85\u65F6\u5904\u7406\u65B9\u6848
+  // SessionTimeoutProcessingEnum.ROUTE_JUMP: \u8DEF\u7531\u8DF3\u8F6C\u5230\u767B\u5F55\u9875
+  // SessionTimeoutProcessingEnum.PAGE_COVERAGE: \u751F\u6210\u767B\u5F55\u5F39\u7A97\uFF0C\u8986\u76D6\u5F53\u524D\u9875\u9762
+  sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
+  // \u9879\u76EE\u4E3B\u9898\u8272
+  themeColor: primaryColor,
+  // \u7F51\u7AD9\u7070\u8272\u6A21\u5F0F\uFF0C\u7528\u4E8E\u53EF\u80FD\u60BC\u5FF5\u7684\u65E5\u671F\u5F00\u542F
+  grayMode: false,
+  // \u8272\u5F31\u6A21\u5F0F
+  colorWeak: false,
+  // \u662F\u5426\u53D6\u6D88\u83DC\u5355,\u9876\u90E8,\u591A\u6807\u7B7E\u9875\u663E\u793A, \u7528\u4E8E\u53EF\u80FD\u5185\u5D4C\u5728\u522B\u7684\u7CFB\u7EDF\u5185
+  fullContent: false,
+  // \u4E3B\u9898\u5185\u5BB9\u5BBD\u5EA6
+  contentMode: ContentEnum.FULL,
+  // \u662F\u5426\u663E\u793Alogo
+  showLogo: true,
+  // \u662F\u5426\u663E\u793A\u5E95\u90E8\u4FE1\u606F copyright
+  showFooter: true,
+  // \u5934\u90E8\u914D\u7F6E
+  headerSetting: {
+    // \u80CC\u666F\u8272
+    bgColor: '#ffffff',
+    // \u56FA\u5B9A\u5934\u90E8
+    fixed: true,
+    // \u662F\u5426\u663E\u793A\u9876\u90E8
+    show: true,
+    // \u4E3B\u9898
+    theme: MenuThemeEnum.LIGHT,
+    // \u5F00\u542F\u9501\u5C4F\u529F\u80FD
+    useLockPage: true,
+    // \u663E\u793A\u5168\u5C4F\u6309\u94AE
+    showFullScreen: true,
+    // \u663E\u793A\u6587\u6863\u6309\u94AE
+    showDoc: true,
+    // \u663E\u793A\u6D88\u606F\u4E2D\u5FC3\u6309\u94AE
+    showNotice: true,
+    // \u663E\u793A\u83DC\u5355\u641C\u7D22\u6309\u94AE
+    showSearch: true,
+  },
+  // \u83DC\u5355\u914D\u7F6E
+  menuSetting: {
+    // \u80CC\u666F\u8272
+    bgColor: '#273352',
+    // \u662F\u5426\u56FA\u5B9A\u4F4F\u83DC\u5355
+    fixed: true,
+    // \u83DC\u5355\u6298\u53E0
+    collapsed: false,
+    // \u6298\u53E0\u83DC\u5355\u65F6\u5019\u662F\u5426\u663E\u793A\u83DC\u5355\u540D
+    collapsedShowTitle: false,
+    // \u662F\u5426\u53EF\u62D6\u62FD
+    canDrag: true,
+    // \u662F\u5426\u663E\u793A
+    show: true,
+    // \u83DC\u5355\u5BBD\u5EA6
+    menuWidth: 180,
+    // \u83DC\u5355\u6A21\u5F0F
+    mode: MenuModeEnum.INLINE,
+    // \u83DC\u5355\u7C7B\u578B
+    type: MenuTypeEnum.SIDEBAR,
+    // \u83DC\u5355\u4E3B\u9898
+    theme: MenuThemeEnum.DARK,
+    // \u5206\u5272\u83DC\u5355
+    split: false,
+    // \u9876\u90E8\u83DC\u5355\u5E03\u5C40
+    topMenuAlign: 'start',
+    // \u6298\u53E0\u89E6\u53D1\u5668\u7684\u4F4D\u7F6E
+    trigger: TriggerEnum.HEADER,
+    // \u624B\u98CE\u7434\u6A21\u5F0F\uFF0C\u53EA\u5C55\u793A\u4E00\u4E2A\u83DC\u5355
+    accordion: true,
+    // \u5728\u8DEF\u7531\u5207\u6362\u7684\u65F6\u5019\u5173\u95ED\u5DE6\u4FA7\u6DF7\u5408\u83DC\u5355\u5C55\u5F00\u83DC\u5355
+    closeMixSidebarOnChange: false,
+    // \u5DE6\u4FA7\u6DF7\u5408\u83DC\u5355\u6A21\u5757\u5207\u6362\u89E6\u53D1\u65B9\u5F0F
+    mixSideTrigger: MixSidebarTriggerEnum.CLICK,
+    // \u662F\u5426\u56FA\u5B9A\u5DE6\u4FA7\u6DF7\u5408\u83DC\u5355
+    mixSideFixed: false,
+  },
+  // \u591A\u6807\u7B7E
+  multiTabsSetting: {
+    // \u5237\u65B0\u540E\u662F\u5426\u4FDD\u7559\u5DF2\u7ECF\u6253\u5F00\u7684\u6807\u7B7E\u9875
+    cache: false,
+    // \u5F00\u542F
+    show: true,
+    // \u5F00\u542F\u5FEB\u901F\u64CD\u4F5C
+    showQuick: true,
+    // \u662F\u5426\u53EF\u4EE5\u62D6\u62FD
+    canDrag: true,
+    // \u662F\u5426\u663E\u793A\u5237\u65B0\u6309\u94AE
+    showRedo: true,
+    // \u662F\u5426\u663E\u793A\u6298\u53E0\u6309\u94AE
+    showFold: true,
+  },
+
+  // \u52A8\u753B\u914D\u7F6E
+  transitionSetting: {
+    //  \u662F\u5426\u5F00\u542F\u5207\u6362\u52A8\u753B
+    enable: true,
+    // \u52A8\u753B\u540D
+    basicTransition: RouterTransitionEnum.FADE_SIDE,
+    // \u662F\u5426\u6253\u5F00\u9875\u9762\u5207\u6362loading
+    openPageLoading: true,
+    // \u662F\u5426\u6253\u5F00\u9875\u9762\u5207\u6362\u9876\u90E8\u8FDB\u5EA6\u6761
+    openNProgress: false,
+  },
+
+  // \u662F\u5426\u5F00\u542FKeepAlive\u7F13\u5B58  \u5F00\u53D1\u65F6\u5019\u6700\u597D\u5173\u95ED,\u4E0D\u7136\u6BCF\u6B21\u90FD\u9700\u8981\u6E05\u9664\u7F13\u5B58
+  openKeepAlive: true,
+  // \u81EA\u52A8\u9501\u5C4F\u65F6\u95F4\uFF0C\u4E3A0\u4E0D\u9501\u5C4F\u3002 \u5355\u4F4D\u5206\u949F \u9ED8\u8BA41\u4E2A\u5C0F\u65F6
+  lockTime: 0,
+  // \u663E\u793A\u9762\u5305\u5C51
+  showBreadCrumb: true,
+  // \u663E\u793A\u9762\u5305\u5C51\u56FE\u6807
+  showBreadCrumbIcon: false,
+  // \u662F\u5426\u4F7F\u7528\u5168\u5C40\u9519\u8BEF\u6355\u83B7
+  useErrorHandle: false,
+  // \u662F\u5426\u5F00\u542F\u56DE\u5230\u9876\u90E8
+  useOpenBackTop: true,
+  //  \u662F\u5426\u53EF\u4EE5\u5D4C\u5165iframe\u9875\u9762
+  canEmbedIFramePage: true,
+  // \u5207\u6362\u754C\u9762\u7684\u65F6\u5019\u662F\u5426\u5220\u9664\u672A\u5173\u95ED\u7684message\u53CAnotify
+  closeMessageOnSwitch: true,
+  // \u5207\u6362\u754C\u9762\u7684\u65F6\u5019\u662F\u5426\u53D6\u6D88\u5DF2\u7ECF\u53D1\u9001\u4F46\u662F\u672A\u54CD\u5E94\u7684http\u8BF7\u6C42\u3002
+  // \u5982\u679C\u5F00\u542F,\u60F3\u5BF9\u5355\u72EC\u63A5\u53E3\u8986\u76D6\u3002\u53EF\u4EE5\u5728\u5355\u72EC\u63A5\u53E3\u8BBE\u7F6E
+  removeAllHttpPending: true,
+};
+

\u7F13\u5B58\u914D\u7F6E

\u7528\u4E8E\u914D\u7F6E\u7F13\u5B58\u5185\u5BB9\u52A0\u5BC6\u4FE1\u606F\uFF0C\u5BF9\u7F13\u5B58\u5230\u6D4F\u89C8\u5668\u7684\u4FE1\u606F\u8FDB\u884C AES \u52A0\u5BC6

\u5728 /@/settings/encryptionSetting.ts \u5185\u53EF\u4EE5\u914D\u7F6E localStorage \u53CA sessionStorage \u7F13\u5B58\u4FE1\u606F

\u524D\u63D0: \u4F7F\u7528\u9879\u76EE\u81EA\u5E26\u7684\u7F13\u5B58\u5DE5\u5177\u7C7B /@/utils/cache \u6765\u8FDB\u884C\u7F13\u5B58\u64CD\u4F5C

import { isDevMode } from '/@/utils/env';
+
+// \u7F13\u5B58\u9ED8\u8BA4\u8FC7\u671F\u65F6\u95F4
+export const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7;
+
+// \u5F00\u542F\u7F13\u5B58\u52A0\u5BC6\u540E\uFF0C\u52A0\u5BC6\u5BC6\u94A5\u3002\u91C7\u7528aes\u52A0\u5BC6
+export const cacheCipher = {
+  key: '_11111000001111@',
+  iv: '@11111000001111_',
+};
+
+// \u662F\u5426\u52A0\u5BC6\u7F13\u5B58\uFF0C\u9ED8\u8BA4\u751F\u4EA7\u73AF\u5883\u52A0\u5BC6
+export const enableStorageEncryption = !isDevMode();
+

\u591A\u8BED\u8A00\u914D\u7F6E

\u7528\u4E8E\u914D\u7F6E\u591A\u8BED\u8A00\u4FE1\u606F

\u5728 src/settings/localeSetting.ts \u5185\u914D\u7F6E

export const LOCALE: { [key: string]: LocaleType } = {
+  ZH_CN: 'zh_CN',
+  EN_US: 'en',
+};
+
+export const localeSetting: LocaleSetting = {
+  // \u662F\u5426\u663E\u793A\u8BED\u8A00\u9009\u62E9\u5668
+  showPicker: true,
+  // \u5F53\u524D\u8BED\u8A00
+  locale: LOCALE.ZH_CN,
+  // \u9ED8\u8BA4\u8BED\u8A00
+  fallback: LOCALE.ZH_CN,
+  // \u5141\u8BB8\u7684\u8BED\u8A00
+  availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US],
+};
+
+// \u8BED\u8A00\u5217\u8868
+export const localeList: DropMenu[] = [
+  {
+    text: '\u7B80\u4F53\u4E2D\u6587',
+    event: LOCALE.ZH_CN,
+  },
+  {
+    text: 'English',
+    event: LOCALE.EN_US,
+  },
+];
+

\u4E3B\u9898\u8272\u914D\u7F6E

\u9ED8\u8BA4\u5168\u5C40\u4E3B\u9898\u8272\u914D\u7F6E\u4F4D\u4E8E build/config/glob/themeConfig.ts \u5185

\u53EA\u9700\u8981\u4FEE\u6539 primaryColor \u4E3A\u60A8\u9700\u8981\u7684\u914D\u8272\uFF0C\u7136\u540E\u91CD\u65B0\u6267\u884C yarn serve \u5373\u53EF

/**
+ * less global variable
+ */
+export const primaryColor = '#0960bd';
+

\u6837\u5F0F\u914D\u7F6E

css \u524D\u7F00\u8BBE\u7F6E

\u7528\u4E8E\u4FEE\u6539\u9879\u76EE\u5185\u7EC4\u4EF6 class \u7684\u7EDF\u4E00\u524D\u7F00

export const prefixCls = 'vben';
+
@namespace: vben;
+

\u524D\u7F00\u4F7F\u7528

\u5728 css \u5185

<style lang="less" scoped>
+  /* namespace\u5DF2\u7ECF\u5168\u5C40\u6CE8\u5165\uFF0C\u4E0D\u9700\u8981\u989D\u5916\u518D\u5F15\u5165 */
+  @prefix-cls: ~'@{namespace}-app-logo';
+
+  .@{prefix-cls} {
+    width: 100%;
+  }
+</style>
+

\u5728 vue/ts \u5185

import { useDesign } from '/@/hooks/web/useDesign';
+
+const { prefixCls } = useDesign('app-logo');
+
+// prefixCls => vben-app-logo
+

\u989C\u8272\u914D\u7F6E

\u7528\u4E8E\u9884\u8BBE\u4E00\u4E9B\u989C\u8272\u6570\u7EC4

\u5728 src/settings/designSetting.ts \u5185\u914D\u7F6E

//  app\u4E3B\u9898\u8272\u9884\u8BBE
+export const APP_PRESET_COLOR_LIST: string[] = [
+  '#0960bd',
+  '#0084f4',
+  '#009688',
+  '#536dfe',
+  '#ff5c93',
+  '#ee4f12',
+  '#0096c7',
+  '#9c27b0',
+  '#ff9800',
+];
+
+// \u9876\u90E8\u80CC\u666F\u8272\u9884\u8BBE
+export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
+  '#ffffff',
+  '#009688',
+  '#5172DC',
+  '#1E9FFF',
+  '#018ffb',
+  '#409eff',
+  '#4e73df',
+  '#e74c3c',
+  '#24292e',
+  '#394664',
+  '#001529',
+  '#383f45',
+];
+
+// \u5DE6\u4FA7\u83DC\u5355\u80CC\u666F\u8272\u9884\u8BBE
+export const SIDE_BAR_BG_COLOR_LIST: string[] = [
+  '#001529',
+  '#273352',
+  '#ffffff',
+  '#191b24',
+  '#191a23',
+  '#304156',
+  '#001628',
+  '#28333E',
+  '#344058',
+  '#383f45',
+];
+

\u7EC4\u4EF6\u9ED8\u8BA4\u53C2\u6570\u914D\u7F6E

\u5728 src/settings/componentSetting.ts \u5185\u914D\u7F6E

// \u7528\u4E8E\u914D\u7F6E\u67D0\u4E9B\u7EC4\u4EF6\u7684\u5E38\u89C4\u914D\u7F6E\uFF0C\u800C\u65E0\u9700\u4FEE\u6539\u7EC4\u4EF6
+import type { SorterResult } from '../components/Table';
+
+export default {
+  // \u8868\u683C\u914D\u7F6E
+  table: {
+    // \u8868\u683C\u63A5\u53E3\u8BF7\u6C42\u901A\u7528\u914D\u7F6E\uFF0C\u53EF\u5728\u7EC4\u4EF6prop\u8986\u76D6
+    // \u652F\u6301 xxx.xxx.xxx\u683C\u5F0F
+    fetchSetting: {
+      // \u4F20\u7ED9\u540E\u53F0\u7684\u5F53\u524D\u9875\u5B57\u6BB5
+      pageField: 'page',
+      // \u4F20\u7ED9\u540E\u53F0\u7684\u6BCF\u9875\u663E\u793A\u591A\u5C11\u6761\u7684\u5B57\u6BB5
+      sizeField: 'pageSize',
+      // \u63A5\u53E3\u8FD4\u56DE\u8868\u683C\u6570\u636E\u7684\u5B57\u6BB5
+      listField: 'items',
+      // \u63A5\u53E3\u8FD4\u56DE\u8868\u683C\u603B\u6570\u7684\u5B57\u6BB5
+      totalField: 'total',
+    },
+    // \u53EF\u9009\u7684\u5206\u9875\u9009\u9879
+    pageSizeOptions: ['10', '50', '80', '100'],
+    //\u9ED8\u8BA4\u6BCF\u9875\u663E\u793A\u591A\u5C11\u6761
+    defaultPageSize: 10,
+    // \u9ED8\u8BA4\u6392\u5E8F\u65B9\u6CD5
+    defaultSortFn: (sortInfo: SorterResult) => {
+      const { field, order } = sortInfo;
+      return {
+        // \u6392\u5E8F\u5B57\u6BB5
+        field,
+        // \u6392\u5E8F\u65B9\u5F0F asc/desc
+        order,
+      };
+    },
+    // \u81EA\u5B9A\u4E49\u8FC7\u6EE4\u65B9\u6CD5
+    defaultFilterFn: (data: Partial<Recordable<string[]>>) => {
+      return data;
+    },
+  },
+  // \u6EDA\u52A8\u7EC4\u4EF6\u914D\u7F6E
+  scrollbar: {
+    // \u662F\u5426\u4F7F\u7528\u539F\u751F\u6EDA\u52A8\u6837\u5F0F
+    // \u5F00\u542F\u540E\uFF0C\u83DC\u5355\uFF0C\u5F39\u7A97\uFF0C\u62BD\u5C49\u4F1A\u4F7F\u7528\u539F\u751F\u6EDA\u52A8\u6761\u7EC4\u4EF6
+    native: false,
+  },
+};
+
`,68),e=[o];function c(l,r,k,i,u,m){return a(),s("div",null,e)}var h=n(t,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/guide_settings.md.87a2cccb.lean.js b/assets/guide_settings.md.87a2cccb.lean.js new file mode 100644 index 00000000..28279910 --- /dev/null +++ b/assets/guide_settings.md.87a2cccb.lean.js @@ -0,0 +1,370 @@ +import{_ as n,f as s,e as a,N as p}from"./plugin-vue_export-helper.147b70e9.js";const g='{"title":"\u9879\u76EE\u914D\u7F6E\u9879","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u73AF\u5883\u53D8\u91CF\u914D\u7F6E","slug":"\u73AF\u5883\u53D8\u91CF\u914D\u7F6E"},{"level":3,"title":"\u914D\u7F6E\u9879\u8BF4\u660E","slug":"\u914D\u7F6E\u9879\u8BF4\u660E"},{"level":3,"title":".env","slug":"env"},{"level":3,"title":".env.development","slug":"env-development"},{"level":3,"title":".env.production","slug":"env-production"},{"level":2,"title":"\u751F\u4EA7\u73AF\u5883\u52A8\u6001\u914D\u7F6E","slug":"\u751F\u4EA7\u73AF\u5883\u52A8\u6001\u914D\u7F6E"},{"level":3,"title":"\u8BF4\u660E","slug":"\u8BF4\u660E"},{"level":3,"title":"\u4F5C\u7528","slug":"\u4F5C\u7528"},{"level":3,"title":"\u5982\u4F55\u83B7\u53D6\u5168\u5C40\u53D8\u91CF","slug":"\u5982\u4F55\u83B7\u53D6\u5168\u5C40\u53D8\u91CF"},{"level":3,"title":"\u5982\u4F55\u65B0\u589E(\u65B0\u589E\u4E00\u4E2A\u53EF\u52A8\u6001\u4FEE\u6539\u7684\u914D\u7F6E\u9879)","slug":"\u5982\u4F55\u65B0\u589E-\u65B0\u589E\u4E00\u4E2A\u53EF\u52A8\u6001\u4FEE\u6539\u7684\u914D\u7F6E\u9879"},{"level":2,"title":"\u9879\u76EE\u914D\u7F6E","slug":"\u9879\u76EE\u914D\u7F6E"},{"level":3,"title":"\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84","slug":"\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84"},{"level":3,"title":"\u8BF4\u660E","slug":"\u8BF4\u660E-1"},{"level":2,"title":"\u7F13\u5B58\u914D\u7F6E","slug":"\u7F13\u5B58\u914D\u7F6E"},{"level":2,"title":"\u591A\u8BED\u8A00\u914D\u7F6E","slug":"\u591A\u8BED\u8A00\u914D\u7F6E"},{"level":2,"title":"\u4E3B\u9898\u8272\u914D\u7F6E","slug":"\u4E3B\u9898\u8272\u914D\u7F6E"},{"level":2,"title":"\u6837\u5F0F\u914D\u7F6E","slug":"\u6837\u5F0F\u914D\u7F6E"},{"level":3,"title":"css \u524D\u7F00\u8BBE\u7F6E","slug":"css-\u524D\u7F00\u8BBE\u7F6E"},{"level":3,"title":"\u524D\u7F00\u4F7F\u7528","slug":"\u524D\u7F00\u4F7F\u7528"},{"level":2,"title":"\u989C\u8272\u914D\u7F6E","slug":"\u989C\u8272\u914D\u7F6E"},{"level":2,"title":"\u7EC4\u4EF6\u9ED8\u8BA4\u53C2\u6570\u914D\u7F6E","slug":"\u7EC4\u4EF6\u9ED8\u8BA4\u53C2\u6570\u914D\u7F6E"}],"relativePath":"guide/settings.md","lastUpdated":1694442156385}',t={},o=p(`__VP_STATIC_START__

\u9879\u76EE\u914D\u7F6E\u9879

\u7528\u4E8E\u4FEE\u6539\u9879\u76EE\u7684\u914D\u8272\u3001\u5E03\u5C40\u3001\u7F13\u5B58\u3001\u591A\u8BED\u8A00\u3001\u7EC4\u4EF6\u9ED8\u8BA4\u914D\u7F6E

\u73AF\u5883\u53D8\u91CF\u914D\u7F6E

\u9879\u76EE\u7684\u73AF\u5883\u53D8\u91CF\u914D\u7F6E\u4F4D\u4E8E\u9879\u76EE\u6839\u76EE\u5F55\u4E0B\u7684 .env\u3001.env.development\u3001.env.production

\u5177\u4F53\u53EF\u4EE5\u53C2\u8003 Vite \u6587\u6863

.env                # \u5728\u6240\u6709\u7684\u73AF\u5883\u4E2D\u88AB\u8F7D\u5165
+.env.local          # \u5728\u6240\u6709\u7684\u73AF\u5883\u4E2D\u88AB\u8F7D\u5165\uFF0C\u4F46\u4F1A\u88AB git \u5FFD\u7565
+.env.[mode]         # \u53EA\u5728\u6307\u5B9A\u7684\u6A21\u5F0F\u4E2D\u88AB\u8F7D\u5165
+.env.[mode].local   # \u53EA\u5728\u6307\u5B9A\u7684\u6A21\u5F0F\u4E2D\u88AB\u8F7D\u5165\uFF0C\u4F46\u4F1A\u88AB git \u5FFD\u7565
+
+

\u6E29\u99A8\u63D0\u9192

  • \u53EA\u6709\u4EE5 VITE_ \u5F00\u5934\u7684\u53D8\u91CF\u4F1A\u88AB\u5D4C\u5165\u5230\u5BA2\u6237\u7AEF\u4FA7\u7684\u5305\u4E2D\uFF0C\u4F60\u53EF\u4EE5\u9879\u76EE\u4EE3\u7801\u4E2D\u8FD9\u6837\u8BBF\u95EE\u5B83\u4EEC\uFF1A
console.log(import.meta.env.VITE_PROT);
+
  • \u4EE5 VITE_GLOB_* \u5F00\u5934\u7684\u7684\u53D8\u91CF\uFF0C\u5728\u6253\u5305\u7684\u65F6\u5019\uFF0C\u4F1A\u88AB\u52A0\u5165_app.config.js\u914D\u7F6E\u6587\u4EF6\u5F53\u4E2D.

\u914D\u7F6E\u9879\u8BF4\u660E

.env

\u6240\u6709\u73AF\u5883\u9002\u7528

# \u7AEF\u53E3\u53F7
+VITE_PORT=3100
+# \u7F51\u7AD9\u6807\u9898
+VITE_GLOB_APP_TITLE=vben admin
+# \u7B80\u79F0\uFF0C\u7528\u4E8E\u914D\u7F6E\u6587\u4EF6\u540D\u5B57 \u4E0D\u8981\u51FA\u73B0\u7A7A\u683C\u3001\u6570\u5B57\u5F00\u5934\u7B49\u7279\u6B8A\u5B57\u7B26
+VITE_GLOB_APP_SHORT_NAME=vben_admin
+

.env.development

\u5F00\u53D1\u73AF\u5883\u9002\u7528

# \u662F\u5426\u5F00\u542Fmock\u6570\u636E\uFF0C\u5173\u95ED\u65F6\u9700\u8981\u81EA\u884C\u5BF9\u63A5\u540E\u53F0\u63A5\u53E3
+VITE_USE_MOCK=true
+# \u8D44\u6E90\u516C\u5171\u8DEF\u5F84,\u9700\u8981\u4EE5 /\u5F00\u5934\u548C\u7ED3\u5C3E
+VITE_PUBLIC_PATH=/
+# \u662F\u5426\u5220\u9664Console.log
+VITE_DROP_CONSOLE=false
+# \u672C\u5730\u5F00\u53D1\u4EE3\u7406\uFF0C\u53EF\u4EE5\u89E3\u51B3\u8DE8\u57DF\u53CA\u591A\u5730\u5740\u4EE3\u7406
+# \u5982\u679C\u63A5\u53E3\u5730\u5740\u5339\u914D\u5230\uFF0C\u5219\u4F1A\u8F6C\u53D1\u5230http://localhost:3000\uFF0C\u9632\u6B62\u672C\u5730\u51FA\u73B0\u8DE8\u57DF\u95EE\u9898
+# \u53EF\u4EE5\u6709\u591A\u4E2A\uFF0C\u6CE8\u610F\u591A\u4E2A\u4E0D\u80FD\u6362\u884C\uFF0C\u5426\u5219\u4EE3\u7406\u5C06\u4F1A\u5931\u6548
+VITE_PROXY=[["/api","http://localhost:3000"],["api1","http://localhost:3001"],["/upload","http://localhost:3001/upload"]]
+# \u63A5\u53E3\u5730\u5740
+# \u5982\u679C\u6CA1\u6709\u8DE8\u57DF\u95EE\u9898\uFF0C\u76F4\u63A5\u5728\u8FD9\u91CC\u914D\u7F6E\u5373\u53EF
+VITE_GLOB_API_URL=/api
+# \u6587\u4EF6\u4E0A\u4F20\u63A5\u53E3  \u53EF\u9009
+VITE_GLOB_UPLOAD_URL=/upload
+# \u63A5\u53E3\u5730\u5740\u524D\u7F00\uFF0C\u6709\u4E9B\u7CFB\u7EDF\u6240\u6709\u63A5\u53E3\u5730\u5740\u90FD\u6709\u524D\u7F00\uFF0C\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EDF\u4E00\u52A0\uFF0C\u65B9\u4FBF\u5207\u6362
+VITE_GLOB_API_URL_PREFIX=
+

\u6CE8\u610F

\u8FD9\u91CC\u914D\u7F6E\u7684 VITE_PROXY \u4EE5\u53CA VITE_GLOB_API_URL, /api \u9700\u8981\u662F\u552F\u4E00\u7684\uFF0C\u4E0D\u8981\u548C\u63A5\u53E3\u6709\u7684\u540D\u5B57\u51B2\u7A81

\u5982\u679C\u4F60\u7684\u63A5\u53E3\u662F http://localhost:3000/api \u4E4B\u7C7B\u7684\uFF0C\u8BF7\u8003\u8651\u5C06 VITE_GLOB_API_URL=/xxxx \u6362\u6210\u522B\u7684\u540D\u5B57

.env.production

\u751F\u4EA7\u73AF\u5883\u9002\u7528

# \u662F\u5426\u5F00\u542Fmock
+VITE_USE_MOCK=true
+# \u63A5\u53E3\u5730\u5740 \u53EF\u4EE5\u7531nginx\u505A\u8F6C\u53D1\u6216\u8005\u76F4\u63A5\u5199\u5B9E\u9645\u5730\u5740
+VITE_GLOB_API_URL=/api
+# \u6587\u4EF6\u4E0A\u4F20\u5730\u5740 \u53EF\u4EE5\u7531nginx\u505A\u8F6C\u53D1\u6216\u8005\u76F4\u63A5\u5199\u5B9E\u9645\u5730\u5740
+VITE_GLOB_UPLOAD_URL=/upload
+# \u63A5\u53E3\u5730\u5740\u524D\u7F00\uFF0C\u6709\u4E9B\u7CFB\u7EDF\u6240\u6709\u63A5\u53E3\u5730\u5740\u90FD\u6709\u524D\u7F00\uFF0C\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EDF\u4E00\u52A0\uFF0C\u65B9\u4FBF\u5207\u6362
+VITE_GLOB_API_URL_PREFIX=
+# \u662F\u5426\u5220\u9664Console.log
+VITE_DROP_CONSOLE=true
+# \u8D44\u6E90\u516C\u5171\u8DEF\u5F84,\u9700\u8981\u4EE5 / \u5F00\u5934\u548C\u7ED3\u5C3E
+VITE_PUBLIC_PATH=/
+# \u6253\u5305\u662F\u5426\u8F93\u51FAgz\uFF5Cbr\u6587\u4EF6
+# \u53EF\u9009: gzip | brotli | none
+# \u4E5F\u53EF\u4EE5\u6709\u591A\u4E2A, \u4F8B\u5982 \u2018gzip\u2019|'brotli',\u8FD9\u6837\u4F1A\u540C\u65F6\u751F\u6210 .gz\u548C.br\u6587\u4EF6
+VITE_BUILD_COMPRESS = 'gzip'
+# \u6253\u5305\u662F\u5426\u538B\u7F29\u56FE\u7247
+VITE_USE_IMAGEMIN = false
+# \u6253\u5305\u662F\u5426\u5F00\u542Fpwa\u529F\u80FD
+VITE_USE_PWA = false
+# \u662F\u5426\u517C\u5BB9\u65E7\u7248\u6D4F\u89C8\u5668\u3002\u5F00\u542F\u540E\u6253\u5305\u65F6\u95F4\u4F1A\u6162\u4E00\u500D\u5DE6\u53F3\u3002\u4F1A\u591A\u6253\u51FA\u65E7\u6D4F\u89C8\u5668\u517C\u5BB9\u5305,\u4E14\u4F1A\u6839\u636E\u6D4F\u89C8\u5668\u517C\u5BB9\u6027\u81EA\u52A8\u4F7F\u7528\u76F8\u5E94\u7684\u7248\u672C
+VITE_LEGACY = false
+

\u751F\u4EA7\u73AF\u5883\u52A8\u6001\u914D\u7F6E

\u8BF4\u660E

\u5F53\u6267\u884Cyarn build\u6784\u5EFA\u9879\u76EE\u4E4B\u540E\uFF0C\u4F1A\u81EA\u52A8\u751F\u6210 _app.config.js \u6587\u4EF6\u5E76\u63D2\u5165 index.html\u3002

\u6CE8\u610F: \u5F00\u53D1\u73AF\u5883\u4E0D\u4F1A\u751F\u6210

// _app.config.js
+// \u53D8\u91CF\u540D\u547D\u540D\u89C4\u5219  __PRODUCTION__xxx_CONF__   xxx\uFF1A\u4E3A.env\u914D\u7F6E\u7684VITE_GLOB_APP_SHORT_NAME
+window.__PRODUCTION__VUE_VBEN_ADMIN__CONF__ = {
+  VITE_GLOB_APP_TITLE: 'vben admin',
+  VITE_GLOB_APP_SHORT_NAME: 'vue_vben_admin',
+  VITE_GLOB_API_URL: '/app',
+  VITE_GLOB_API_URL_PREFIX: '/',
+  VITE_GLOB_UPLOAD_URL: '/upload',
+};
+

\u4F5C\u7528

_app.config.js \u7528\u4E8E\u9879\u76EE\u5728\u6253\u5305\u540E\uFF0C\u9700\u8981\u52A8\u6001\u4FEE\u6539\u914D\u7F6E\u7684\u9700\u6C42\uFF0C\u5982\u63A5\u53E3\u5730\u5740\u3002\u4E0D\u7528\u91CD\u65B0\u8FDB\u884C\u6253\u5305\uFF0C\u53EF\u5728\u6253\u5305\u540E\u4FEE\u6539 /dist/_app.config.js \u5185\u7684\u53D8\u91CF\uFF0C\u5237\u65B0\u5373\u53EF\u66F4\u65B0\u4EE3\u7801\u5185\u7684\u5C40\u90E8\u53D8\u91CF\u3002

\u5982\u4F55\u83B7\u53D6\u5168\u5C40\u53D8\u91CF

\u60F3\u8981\u83B7\u53D6 _app.config.js \u5185\u7684\u53D8\u91CF\uFF0C\u53EF\u4EE5\u4F7F\u7528 src/hooks/setting/index.ts \u63D0\u4F9B\u7684\u51FD\u6570\u6765\u8FDB\u884C\u83B7\u53D6

\u5982\u4F55\u65B0\u589E(\u65B0\u589E\u4E00\u4E2A\u53EF\u52A8\u6001\u4FEE\u6539\u7684\u914D\u7F6E\u9879)

  1. \u9996\u5148\u5728 .env \u6216\u8005\u5BF9\u5E94\u7684\u5F00\u53D1\u73AF\u5883\u914D\u7F6E\u6587\u4EF6\u5185\uFF0C\u65B0\u589E\u9700\u8981\u53EF\u52A8\u6001\u914D\u7F6E\u7684\u53D8\u91CF\uFF0C\u9700\u8981\u4EE5 VITE_GLOB_\u5F00\u5934

  2. VITE_GLOB_ \u5F00\u5934\u7684\u53D8\u91CF\u4F1A\u81EA\u52A8\u52A0\u5165\u73AF\u5883\u53D8\u91CF\uFF0C\u901A\u8FC7\u5728 types/config.d.ts \u5185\u4FEE\u6539 GlobEnvConfig \u548C GlobConfig \u4E24\u4E2A\u73AF\u5883\u53D8\u91CF\u7684\u503C\u6765\u5B9A\u4E49\u65B0\u6DFB\u52A0\u7684\u7C7B\u578B

  3. useGlobSetting \u51FD\u6570\u4E2D\u6DFB\u52A0\u521A\u65B0\u589E\u7684\u8FD4\u56DE\u503C\u5373\u53EF

const {
+  VITE_GLOB_APP_TITLE,
+  VITE_GLOB_API_URL,
+  VITE_GLOB_APP_SHORT_NAME,
+  VITE_GLOB_API_URL_PREFIX,
+  VITE_GLOB_UPLOAD_URL,
+} = ENV;
+
+export const useGlobSetting = (): SettingWrap => {
+  // Take global configuration
+  const glob: Readonly<GlobConfig> = {
+    title: VITE_GLOB_APP_TITLE,
+    apiUrl: VITE_GLOB_API_URL,
+    shortName: VITE_GLOB_APP_SHORT_NAME,
+    urlPrefix: VITE_GLOB_API_URL_PREFIX,
+    uploadUrl: VITE_GLOB_UPLOAD_URL
+  };
+  return glob as Readonly<GlobConfig>;
+};
+
+

\u9879\u76EE\u914D\u7F6E

WARNING

\u9879\u76EE\u914D\u7F6E\u6587\u4EF6\u7528\u4E8E\u914D\u7F6E\u9879\u76EE\u5185\u5C55\u793A\u7684\u5185\u5BB9\u3001\u5E03\u5C40\u3001\u6587\u672C\u7B49\u6548\u679C\uFF0C\u5B58\u4E8ElocalStorage\u4E2D\u3002\u5982\u679C\u66F4\u6539\u4E86\u9879\u76EE\u914D\u7F6E\uFF0C\u9700\u8981\u624B\u52A8\u6E05\u7A7A localStorage \u7F13\u5B58\uFF0C\u5237\u65B0\u91CD\u65B0\u767B\u5F55\u540E\u65B9\u53EF\u751F\u6548\u3002

\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84

src/settings/projectSetting.ts

\u8BF4\u660E

// ! \u6539\u52A8\u540E\u9700\u8981\u6E05\u7A7A\u6D4F\u89C8\u5668\u7F13\u5B58
+const setting: ProjectConfig = {
+  // \u662F\u5426\u663E\u793ASettingButton
+  showSettingButton: true,
+
+  // \u662F\u5426\u663E\u793A\u4E3B\u9898\u5207\u6362\u6309\u94AE
+  showDarkModeToggle: true,
+
+  // \u8BBE\u7F6E\u6309\u94AE\u4F4D\u7F6E \u53EF\u9009\u9879
+  // SettingButtonPositionEnum.AUTO: \u81EA\u52A8\u9009\u62E9
+  // SettingButtonPositionEnum.HEADER: \u4F4D\u4E8E\u5934\u90E8
+  // SettingButtonPositionEnum.FIXED: \u56FA\u5B9A\u5728\u53F3\u4FA7
+  settingButtonPosition: SettingButtonPositionEnum.AUTO,
+
+  // \u6743\u9650\u6A21\u5F0F,\u9ED8\u8BA4\u524D\u7AEF\u89D2\u8272\u6743\u9650\u6A21\u5F0F
+  // ROUTE_MAPPING: \u524D\u7AEF\u6A21\u5F0F\uFF08\u83DC\u5355\u7531\u8DEF\u7531\u751F\u6210\uFF0C\u9ED8\u8BA4\uFF09
+  // ROLE\uFF1A\u524D\u7AEF\u6A21\u5F0F\uFF08\u83DC\u5355\u8DEF\u7531\u5206\u5F00\uFF09
+  permissionMode: PermissionModeEnum.ROUTE_MAPPING,
+  // \u6743\u9650\u7F13\u5B58\u5B58\u653E\u4F4D\u7F6E\u3002\u9ED8\u8BA4\u5B58\u653E\u4E8ElocalStorage
+  permissionCacheType: CacheTypeEnum.LOCAL,
+  // \u4F1A\u8BDD\u8D85\u65F6\u5904\u7406\u65B9\u6848
+  // SessionTimeoutProcessingEnum.ROUTE_JUMP: \u8DEF\u7531\u8DF3\u8F6C\u5230\u767B\u5F55\u9875
+  // SessionTimeoutProcessingEnum.PAGE_COVERAGE: \u751F\u6210\u767B\u5F55\u5F39\u7A97\uFF0C\u8986\u76D6\u5F53\u524D\u9875\u9762
+  sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
+  // \u9879\u76EE\u4E3B\u9898\u8272
+  themeColor: primaryColor,
+  // \u7F51\u7AD9\u7070\u8272\u6A21\u5F0F\uFF0C\u7528\u4E8E\u53EF\u80FD\u60BC\u5FF5\u7684\u65E5\u671F\u5F00\u542F
+  grayMode: false,
+  // \u8272\u5F31\u6A21\u5F0F
+  colorWeak: false,
+  // \u662F\u5426\u53D6\u6D88\u83DC\u5355,\u9876\u90E8,\u591A\u6807\u7B7E\u9875\u663E\u793A, \u7528\u4E8E\u53EF\u80FD\u5185\u5D4C\u5728\u522B\u7684\u7CFB\u7EDF\u5185
+  fullContent: false,
+  // \u4E3B\u9898\u5185\u5BB9\u5BBD\u5EA6
+  contentMode: ContentEnum.FULL,
+  // \u662F\u5426\u663E\u793Alogo
+  showLogo: true,
+  // \u662F\u5426\u663E\u793A\u5E95\u90E8\u4FE1\u606F copyright
+  showFooter: true,
+  // \u5934\u90E8\u914D\u7F6E
+  headerSetting: {
+    // \u80CC\u666F\u8272
+    bgColor: '#ffffff',
+    // \u56FA\u5B9A\u5934\u90E8
+    fixed: true,
+    // \u662F\u5426\u663E\u793A\u9876\u90E8
+    show: true,
+    // \u4E3B\u9898
+    theme: MenuThemeEnum.LIGHT,
+    // \u5F00\u542F\u9501\u5C4F\u529F\u80FD
+    useLockPage: true,
+    // \u663E\u793A\u5168\u5C4F\u6309\u94AE
+    showFullScreen: true,
+    // \u663E\u793A\u6587\u6863\u6309\u94AE
+    showDoc: true,
+    // \u663E\u793A\u6D88\u606F\u4E2D\u5FC3\u6309\u94AE
+    showNotice: true,
+    // \u663E\u793A\u83DC\u5355\u641C\u7D22\u6309\u94AE
+    showSearch: true,
+  },
+  // \u83DC\u5355\u914D\u7F6E
+  menuSetting: {
+    // \u80CC\u666F\u8272
+    bgColor: '#273352',
+    // \u662F\u5426\u56FA\u5B9A\u4F4F\u83DC\u5355
+    fixed: true,
+    // \u83DC\u5355\u6298\u53E0
+    collapsed: false,
+    // \u6298\u53E0\u83DC\u5355\u65F6\u5019\u662F\u5426\u663E\u793A\u83DC\u5355\u540D
+    collapsedShowTitle: false,
+    // \u662F\u5426\u53EF\u62D6\u62FD
+    canDrag: true,
+    // \u662F\u5426\u663E\u793A
+    show: true,
+    // \u83DC\u5355\u5BBD\u5EA6
+    menuWidth: 180,
+    // \u83DC\u5355\u6A21\u5F0F
+    mode: MenuModeEnum.INLINE,
+    // \u83DC\u5355\u7C7B\u578B
+    type: MenuTypeEnum.SIDEBAR,
+    // \u83DC\u5355\u4E3B\u9898
+    theme: MenuThemeEnum.DARK,
+    // \u5206\u5272\u83DC\u5355
+    split: false,
+    // \u9876\u90E8\u83DC\u5355\u5E03\u5C40
+    topMenuAlign: 'start',
+    // \u6298\u53E0\u89E6\u53D1\u5668\u7684\u4F4D\u7F6E
+    trigger: TriggerEnum.HEADER,
+    // \u624B\u98CE\u7434\u6A21\u5F0F\uFF0C\u53EA\u5C55\u793A\u4E00\u4E2A\u83DC\u5355
+    accordion: true,
+    // \u5728\u8DEF\u7531\u5207\u6362\u7684\u65F6\u5019\u5173\u95ED\u5DE6\u4FA7\u6DF7\u5408\u83DC\u5355\u5C55\u5F00\u83DC\u5355
+    closeMixSidebarOnChange: false,
+    // \u5DE6\u4FA7\u6DF7\u5408\u83DC\u5355\u6A21\u5757\u5207\u6362\u89E6\u53D1\u65B9\u5F0F
+    mixSideTrigger: MixSidebarTriggerEnum.CLICK,
+    // \u662F\u5426\u56FA\u5B9A\u5DE6\u4FA7\u6DF7\u5408\u83DC\u5355
+    mixSideFixed: false,
+  },
+  // \u591A\u6807\u7B7E
+  multiTabsSetting: {
+    // \u5237\u65B0\u540E\u662F\u5426\u4FDD\u7559\u5DF2\u7ECF\u6253\u5F00\u7684\u6807\u7B7E\u9875
+    cache: false,
+    // \u5F00\u542F
+    show: true,
+    // \u5F00\u542F\u5FEB\u901F\u64CD\u4F5C
+    showQuick: true,
+    // \u662F\u5426\u53EF\u4EE5\u62D6\u62FD
+    canDrag: true,
+    // \u662F\u5426\u663E\u793A\u5237\u65B0\u6309\u94AE
+    showRedo: true,
+    // \u662F\u5426\u663E\u793A\u6298\u53E0\u6309\u94AE
+    showFold: true,
+  },
+
+  // \u52A8\u753B\u914D\u7F6E
+  transitionSetting: {
+    //  \u662F\u5426\u5F00\u542F\u5207\u6362\u52A8\u753B
+    enable: true,
+    // \u52A8\u753B\u540D
+    basicTransition: RouterTransitionEnum.FADE_SIDE,
+    // \u662F\u5426\u6253\u5F00\u9875\u9762\u5207\u6362loading
+    openPageLoading: true,
+    // \u662F\u5426\u6253\u5F00\u9875\u9762\u5207\u6362\u9876\u90E8\u8FDB\u5EA6\u6761
+    openNProgress: false,
+  },
+
+  // \u662F\u5426\u5F00\u542FKeepAlive\u7F13\u5B58  \u5F00\u53D1\u65F6\u5019\u6700\u597D\u5173\u95ED,\u4E0D\u7136\u6BCF\u6B21\u90FD\u9700\u8981\u6E05\u9664\u7F13\u5B58
+  openKeepAlive: true,
+  // \u81EA\u52A8\u9501\u5C4F\u65F6\u95F4\uFF0C\u4E3A0\u4E0D\u9501\u5C4F\u3002 \u5355\u4F4D\u5206\u949F \u9ED8\u8BA41\u4E2A\u5C0F\u65F6
+  lockTime: 0,
+  // \u663E\u793A\u9762\u5305\u5C51
+  showBreadCrumb: true,
+  // \u663E\u793A\u9762\u5305\u5C51\u56FE\u6807
+  showBreadCrumbIcon: false,
+  // \u662F\u5426\u4F7F\u7528\u5168\u5C40\u9519\u8BEF\u6355\u83B7
+  useErrorHandle: false,
+  // \u662F\u5426\u5F00\u542F\u56DE\u5230\u9876\u90E8
+  useOpenBackTop: true,
+  //  \u662F\u5426\u53EF\u4EE5\u5D4C\u5165iframe\u9875\u9762
+  canEmbedIFramePage: true,
+  // \u5207\u6362\u754C\u9762\u7684\u65F6\u5019\u662F\u5426\u5220\u9664\u672A\u5173\u95ED\u7684message\u53CAnotify
+  closeMessageOnSwitch: true,
+  // \u5207\u6362\u754C\u9762\u7684\u65F6\u5019\u662F\u5426\u53D6\u6D88\u5DF2\u7ECF\u53D1\u9001\u4F46\u662F\u672A\u54CD\u5E94\u7684http\u8BF7\u6C42\u3002
+  // \u5982\u679C\u5F00\u542F,\u60F3\u5BF9\u5355\u72EC\u63A5\u53E3\u8986\u76D6\u3002\u53EF\u4EE5\u5728\u5355\u72EC\u63A5\u53E3\u8BBE\u7F6E
+  removeAllHttpPending: true,
+};
+

\u7F13\u5B58\u914D\u7F6E

\u7528\u4E8E\u914D\u7F6E\u7F13\u5B58\u5185\u5BB9\u52A0\u5BC6\u4FE1\u606F\uFF0C\u5BF9\u7F13\u5B58\u5230\u6D4F\u89C8\u5668\u7684\u4FE1\u606F\u8FDB\u884C AES \u52A0\u5BC6

\u5728 /@/settings/encryptionSetting.ts \u5185\u53EF\u4EE5\u914D\u7F6E localStorage \u53CA sessionStorage \u7F13\u5B58\u4FE1\u606F

\u524D\u63D0: \u4F7F\u7528\u9879\u76EE\u81EA\u5E26\u7684\u7F13\u5B58\u5DE5\u5177\u7C7B /@/utils/cache \u6765\u8FDB\u884C\u7F13\u5B58\u64CD\u4F5C

import { isDevMode } from '/@/utils/env';
+
+// \u7F13\u5B58\u9ED8\u8BA4\u8FC7\u671F\u65F6\u95F4
+export const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7;
+
+// \u5F00\u542F\u7F13\u5B58\u52A0\u5BC6\u540E\uFF0C\u52A0\u5BC6\u5BC6\u94A5\u3002\u91C7\u7528aes\u52A0\u5BC6
+export const cacheCipher = {
+  key: '_11111000001111@',
+  iv: '@11111000001111_',
+};
+
+// \u662F\u5426\u52A0\u5BC6\u7F13\u5B58\uFF0C\u9ED8\u8BA4\u751F\u4EA7\u73AF\u5883\u52A0\u5BC6
+export const enableStorageEncryption = !isDevMode();
+

\u591A\u8BED\u8A00\u914D\u7F6E

\u7528\u4E8E\u914D\u7F6E\u591A\u8BED\u8A00\u4FE1\u606F

\u5728 src/settings/localeSetting.ts \u5185\u914D\u7F6E

export const LOCALE: { [key: string]: LocaleType } = {
+  ZH_CN: 'zh_CN',
+  EN_US: 'en',
+};
+
+export const localeSetting: LocaleSetting = {
+  // \u662F\u5426\u663E\u793A\u8BED\u8A00\u9009\u62E9\u5668
+  showPicker: true,
+  // \u5F53\u524D\u8BED\u8A00
+  locale: LOCALE.ZH_CN,
+  // \u9ED8\u8BA4\u8BED\u8A00
+  fallback: LOCALE.ZH_CN,
+  // \u5141\u8BB8\u7684\u8BED\u8A00
+  availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US],
+};
+
+// \u8BED\u8A00\u5217\u8868
+export const localeList: DropMenu[] = [
+  {
+    text: '\u7B80\u4F53\u4E2D\u6587',
+    event: LOCALE.ZH_CN,
+  },
+  {
+    text: 'English',
+    event: LOCALE.EN_US,
+  },
+];
+

\u4E3B\u9898\u8272\u914D\u7F6E

\u9ED8\u8BA4\u5168\u5C40\u4E3B\u9898\u8272\u914D\u7F6E\u4F4D\u4E8E build/config/glob/themeConfig.ts \u5185

\u53EA\u9700\u8981\u4FEE\u6539 primaryColor \u4E3A\u60A8\u9700\u8981\u7684\u914D\u8272\uFF0C\u7136\u540E\u91CD\u65B0\u6267\u884C yarn serve \u5373\u53EF

/**
+ * less global variable
+ */
+export const primaryColor = '#0960bd';
+

\u6837\u5F0F\u914D\u7F6E

css \u524D\u7F00\u8BBE\u7F6E

\u7528\u4E8E\u4FEE\u6539\u9879\u76EE\u5185\u7EC4\u4EF6 class \u7684\u7EDF\u4E00\u524D\u7F00

export const prefixCls = 'vben';
+
@namespace: vben;
+

\u524D\u7F00\u4F7F\u7528

\u5728 css \u5185

<style lang="less" scoped>
+  /* namespace\u5DF2\u7ECF\u5168\u5C40\u6CE8\u5165\uFF0C\u4E0D\u9700\u8981\u989D\u5916\u518D\u5F15\u5165 */
+  @prefix-cls: ~'@{namespace}-app-logo';
+
+  .@{prefix-cls} {
+    width: 100%;
+  }
+</style>
+

\u5728 vue/ts \u5185

import { useDesign } from '/@/hooks/web/useDesign';
+
+const { prefixCls } = useDesign('app-logo');
+
+// prefixCls => vben-app-logo
+

\u989C\u8272\u914D\u7F6E

\u7528\u4E8E\u9884\u8BBE\u4E00\u4E9B\u989C\u8272\u6570\u7EC4

\u5728 src/settings/designSetting.ts \u5185\u914D\u7F6E

//  app\u4E3B\u9898\u8272\u9884\u8BBE
+export const APP_PRESET_COLOR_LIST: string[] = [
+  '#0960bd',
+  '#0084f4',
+  '#009688',
+  '#536dfe',
+  '#ff5c93',
+  '#ee4f12',
+  '#0096c7',
+  '#9c27b0',
+  '#ff9800',
+];
+
+// \u9876\u90E8\u80CC\u666F\u8272\u9884\u8BBE
+export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
+  '#ffffff',
+  '#009688',
+  '#5172DC',
+  '#1E9FFF',
+  '#018ffb',
+  '#409eff',
+  '#4e73df',
+  '#e74c3c',
+  '#24292e',
+  '#394664',
+  '#001529',
+  '#383f45',
+];
+
+// \u5DE6\u4FA7\u83DC\u5355\u80CC\u666F\u8272\u9884\u8BBE
+export const SIDE_BAR_BG_COLOR_LIST: string[] = [
+  '#001529',
+  '#273352',
+  '#ffffff',
+  '#191b24',
+  '#191a23',
+  '#304156',
+  '#001628',
+  '#28333E',
+  '#344058',
+  '#383f45',
+];
+

\u7EC4\u4EF6\u9ED8\u8BA4\u53C2\u6570\u914D\u7F6E

\u5728 src/settings/componentSetting.ts \u5185\u914D\u7F6E

// \u7528\u4E8E\u914D\u7F6E\u67D0\u4E9B\u7EC4\u4EF6\u7684\u5E38\u89C4\u914D\u7F6E\uFF0C\u800C\u65E0\u9700\u4FEE\u6539\u7EC4\u4EF6
+import type { SorterResult } from '../components/Table';
+
+export default {
+  // \u8868\u683C\u914D\u7F6E
+  table: {
+    // \u8868\u683C\u63A5\u53E3\u8BF7\u6C42\u901A\u7528\u914D\u7F6E\uFF0C\u53EF\u5728\u7EC4\u4EF6prop\u8986\u76D6
+    // \u652F\u6301 xxx.xxx.xxx\u683C\u5F0F
+    fetchSetting: {
+      // \u4F20\u7ED9\u540E\u53F0\u7684\u5F53\u524D\u9875\u5B57\u6BB5
+      pageField: 'page',
+      // \u4F20\u7ED9\u540E\u53F0\u7684\u6BCF\u9875\u663E\u793A\u591A\u5C11\u6761\u7684\u5B57\u6BB5
+      sizeField: 'pageSize',
+      // \u63A5\u53E3\u8FD4\u56DE\u8868\u683C\u6570\u636E\u7684\u5B57\u6BB5
+      listField: 'items',
+      // \u63A5\u53E3\u8FD4\u56DE\u8868\u683C\u603B\u6570\u7684\u5B57\u6BB5
+      totalField: 'total',
+    },
+    // \u53EF\u9009\u7684\u5206\u9875\u9009\u9879
+    pageSizeOptions: ['10', '50', '80', '100'],
+    //\u9ED8\u8BA4\u6BCF\u9875\u663E\u793A\u591A\u5C11\u6761
+    defaultPageSize: 10,
+    // \u9ED8\u8BA4\u6392\u5E8F\u65B9\u6CD5
+    defaultSortFn: (sortInfo: SorterResult) => {
+      const { field, order } = sortInfo;
+      return {
+        // \u6392\u5E8F\u5B57\u6BB5
+        field,
+        // \u6392\u5E8F\u65B9\u5F0F asc/desc
+        order,
+      };
+    },
+    // \u81EA\u5B9A\u4E49\u8FC7\u6EE4\u65B9\u6CD5
+    defaultFilterFn: (data: Partial<Recordable<string[]>>) => {
+      return data;
+    },
+  },
+  // \u6EDA\u52A8\u7EC4\u4EF6\u914D\u7F6E
+  scrollbar: {
+    // \u662F\u5426\u4F7F\u7528\u539F\u751F\u6EDA\u52A8\u6837\u5F0F
+    // \u5F00\u542F\u540E\uFF0C\u83DC\u5355\uFF0C\u5F39\u7A97\uFF0C\u62BD\u5C49\u4F1A\u4F7F\u7528\u539F\u751F\u6EDA\u52A8\u6761\u7EC4\u4EF6
+    native: false,
+  },
+};
+
__VP_STATIC_END__`,68),e=[o];function c(l,r,k,i,u,m){return a(),s("div",null,e)}var h=n(t,[["render",c]]);export{g as __pageData,h as default}; diff --git a/assets/index.md.9831e422.js b/assets/index.md.9831e422.js new file mode 100644 index 00000000..968c848d --- /dev/null +++ b/assets/index.md.9831e422.js @@ -0,0 +1 @@ +import{_ as t,f as e,e as i}from"./plugin-vue_export-helper.147b70e9.js";const _='{"title":"Home","description":"","frontmatter":{"home":true,"heroImage":"/logo.png","actionText":"\u5FEB\u901F\u5F00\u59CB \u2192","actionLink":"/guide/introduction","altActionText":"\u5728\u7EBF\u9884\u89C8","altActionLink":"https://vben.vvbin.cn/","features":[{"title":"\u{1F4A1} \u6700\u65B0\u6280\u672F\u6808","details":"\u57FA\u4E8EVue3\u3001Vite\u3001TypeScript\u7B49\u6700\u65B0\u6280\u672F\u6808\u5F00\u53D1"},{"title":"\u26A1\uFE0F \u8F7B\u91CF\u5FEB\u901F\u7684\u70ED\u91CD\u8F7D","details":"\u65E0\u8BBA\u5E94\u7528\u7A0B\u5E8F\u5927\u5C0F\u5982\u4F55\uFF0C\u90FD\u59CB\u7EC8\u6781\u5FEB\u7684\u6A21\u5757\u70ED\u91CD\u8F7D\uFF08HMR\uFF09"},{"title":"\u{1F6E0}\uFE0F \u4E30\u5BCC\u7684\u793A\u4F8B","details":"\u5E38\u89C1\u7684Web\u7AEF\u63D2\u4EF6\u793A\u4F8B\u5B9E\u73B0"},{"title":"\u{1F4E6} \u7EC4\u4EF6\u5C01\u88C5","details":"\u5BF9\u65E5\u5E38\u4F7F\u7528\u9891\u7387\u8F83\u9AD8\u7684\u7EC4\u4EF6\u4E8C\u6B21\u5C01\u88C5,\u6EE1\u8DB3\u57FA\u7840\u5DE5\u4F5C\u9700\u6C42"},{"title":"\u{1F529} \u4E3B\u9898\u914D\u7F6E","details":"\u4E30\u5BCC\u7684\u4E3B\u9898\u914D\u7F6E\u53CA\u9ED1\u6697\u4E3B\u9898\u9002\u914D"},{"title":"\u{1F511} \u6743\u9650\u7BA1\u7406","details":"\u5B8C\u5584\u7684\u524D\u540E\u7AEF\u6743\u9650\u7BA1\u7406\u65B9\u6848"}],"footer":"MIT Licensed | Copyright \xA9 2021-present Vben"},"relativePath":"index.md","lastUpdated":1694442156385}',a={};function n(o,r,s,l,c,d){return i(),e("div")}var f=t(a,[["render",n]]);export{_ as __pageData,f as default}; diff --git a/assets/index.md.9831e422.lean.js b/assets/index.md.9831e422.lean.js new file mode 100644 index 00000000..968c848d --- /dev/null +++ b/assets/index.md.9831e422.lean.js @@ -0,0 +1 @@ +import{_ as t,f as e,e as i}from"./plugin-vue_export-helper.147b70e9.js";const _='{"title":"Home","description":"","frontmatter":{"home":true,"heroImage":"/logo.png","actionText":"\u5FEB\u901F\u5F00\u59CB \u2192","actionLink":"/guide/introduction","altActionText":"\u5728\u7EBF\u9884\u89C8","altActionLink":"https://vben.vvbin.cn/","features":[{"title":"\u{1F4A1} \u6700\u65B0\u6280\u672F\u6808","details":"\u57FA\u4E8EVue3\u3001Vite\u3001TypeScript\u7B49\u6700\u65B0\u6280\u672F\u6808\u5F00\u53D1"},{"title":"\u26A1\uFE0F \u8F7B\u91CF\u5FEB\u901F\u7684\u70ED\u91CD\u8F7D","details":"\u65E0\u8BBA\u5E94\u7528\u7A0B\u5E8F\u5927\u5C0F\u5982\u4F55\uFF0C\u90FD\u59CB\u7EC8\u6781\u5FEB\u7684\u6A21\u5757\u70ED\u91CD\u8F7D\uFF08HMR\uFF09"},{"title":"\u{1F6E0}\uFE0F \u4E30\u5BCC\u7684\u793A\u4F8B","details":"\u5E38\u89C1\u7684Web\u7AEF\u63D2\u4EF6\u793A\u4F8B\u5B9E\u73B0"},{"title":"\u{1F4E6} \u7EC4\u4EF6\u5C01\u88C5","details":"\u5BF9\u65E5\u5E38\u4F7F\u7528\u9891\u7387\u8F83\u9AD8\u7684\u7EC4\u4EF6\u4E8C\u6B21\u5C01\u88C5,\u6EE1\u8DB3\u57FA\u7840\u5DE5\u4F5C\u9700\u6C42"},{"title":"\u{1F529} \u4E3B\u9898\u914D\u7F6E","details":"\u4E30\u5BCC\u7684\u4E3B\u9898\u914D\u7F6E\u53CA\u9ED1\u6697\u4E3B\u9898\u9002\u914D"},{"title":"\u{1F511} \u6743\u9650\u7BA1\u7406","details":"\u5B8C\u5584\u7684\u524D\u540E\u7AEF\u6743\u9650\u7BA1\u7406\u65B9\u6848"}],"footer":"MIT Licensed | Copyright \xA9 2021-present Vben"},"relativePath":"index.md","lastUpdated":1694442156385}',a={};function n(o,r,s,l,c,d){return i(),e("div")}var f=t(a,[["render",n]]);export{_ as __pageData,f as default}; diff --git a/assets/other_donate.md.d0e4b09b.js b/assets/other_donate.md.d0e4b09b.js new file mode 100644 index 00000000..75690db2 --- /dev/null +++ b/assets/other_donate.md.d0e4b09b.js @@ -0,0 +1 @@ +import{_ as t,f as a,e as o,g as e,k as n}from"./plugin-vue_export-helper.147b70e9.js";const b='{"title":"\u8D5E\u52A9","description":"","frontmatter":{},"relativePath":"other/donate.md","lastUpdated":1694442156385}',s={},r=e("h1",{id:"\u8D5E\u52A9"},[e("a",{class:"header-anchor",href:"#\u8D5E\u52A9","aria-hidden":"true"},"#"),n(" \u8D5E\u52A9")],-1),c=e("p",null,"\u5982\u679C\u4F60\u89C9\u5F97\u8FD9\u4E2A\u9879\u76EE\u5BF9\u4F60\u6709\u5E2E\u52A9\uFF0C\u4F60\u53EF\u4EE5\u5E2E\u4F5C\u8005\u4E70\u4E00\u676F\u5496\u5561\u8868\u793A\u652F\u6301!",-1),d=e("p",null,[e("img",{src:"https://anncwb.github.io/anncwb/images/sponsor.png",alt:"donate"})],-1),i=e("p",null,[e("a",{style:{display:"block",width:"100px",height:"50px","line-height":"50px",color:"#fff","text-align":"center",background:"#408aed","border-radius":"4px"},href:"https://www.paypal.com/paypalme/cvvben"},"Paypal Me")],-1),p=[r,c,d,i];function l(h,_,f,u,g,m){return o(),a("div",null,p)}var w=t(s,[["render",l]]);export{b as __pageData,w as default}; diff --git a/assets/other_donate.md.d0e4b09b.lean.js b/assets/other_donate.md.d0e4b09b.lean.js new file mode 100644 index 00000000..75690db2 --- /dev/null +++ b/assets/other_donate.md.d0e4b09b.lean.js @@ -0,0 +1 @@ +import{_ as t,f as a,e as o,g as e,k as n}from"./plugin-vue_export-helper.147b70e9.js";const b='{"title":"\u8D5E\u52A9","description":"","frontmatter":{},"relativePath":"other/donate.md","lastUpdated":1694442156385}',s={},r=e("h1",{id:"\u8D5E\u52A9"},[e("a",{class:"header-anchor",href:"#\u8D5E\u52A9","aria-hidden":"true"},"#"),n(" \u8D5E\u52A9")],-1),c=e("p",null,"\u5982\u679C\u4F60\u89C9\u5F97\u8FD9\u4E2A\u9879\u76EE\u5BF9\u4F60\u6709\u5E2E\u52A9\uFF0C\u4F60\u53EF\u4EE5\u5E2E\u4F5C\u8005\u4E70\u4E00\u676F\u5496\u5561\u8868\u793A\u652F\u6301!",-1),d=e("p",null,[e("img",{src:"https://anncwb.github.io/anncwb/images/sponsor.png",alt:"donate"})],-1),i=e("p",null,[e("a",{style:{display:"block",width:"100px",height:"50px","line-height":"50px",color:"#fff","text-align":"center",background:"#408aed","border-radius":"4px"},href:"https://www.paypal.com/paypalme/cvvben"},"Paypal Me")],-1),p=[r,c,d,i];function l(h,_,f,u,g,m){return o(),a("div",null,p)}var w=t(s,[["render",l]]);export{b as __pageData,w as default}; diff --git a/assets/other_doubt.md.a4551c31.js b/assets/other_doubt.md.a4551c31.js new file mode 100644 index 00000000..23b8df68 --- /dev/null +++ b/assets/other_doubt.md.a4551c31.js @@ -0,0 +1,23 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u5E38\u89C1\u7591\u70B9\u8BF4\u660E","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u9879\u76EE\u522B\u540D","slug":"\u9879\u76EE\u522B\u540D"},{"level":2,"title":"\u4E3A\u4EC0\u4E48\u5728\u672C\u5730\u6CA1\u6709\u6309\u9700\u5F15\u5165\u7EC4\u4EF6\u5E93\u6837\u5F0F\uFF0C\u5728\u751F\u4EA7\u624D\u5F15\u5165","slug":"\u4E3A\u4EC0\u4E48\u5728\u672C\u5730\u6CA1\u6709\u6309\u9700\u5F15\u5165\u7EC4\u4EF6\u5E93\u6837\u5F0F\uFF0C\u5728\u751F\u4EA7\u624D\u5F15\u5165"},{"level":2,"title":"\u4E3A\u4EC0\u4E48\u5355\u72EC\u628A moment \u653E\u5230 dataUtil \u5185","slug":"\u4E3A\u4EC0\u4E48\u5355\u72EC\u628A-moment-\u653E\u5230-datautil-\u5185"}],"relativePath":"other/doubt.md","lastUpdated":1694442156385}',p={},o=t(`

\u5E38\u89C1\u7591\u70B9\u8BF4\u660E

\u8BE5\u5206\u7C7B\u4E3B\u8981\u8BF4\u660E\u4E00\u4E9B\u5730\u65B9\u4E3A\u4EC0\u4E48\u8FD9\u6837\u505A\uFF0C\u4EE5\u53CA\u539F\u56E0\u662F\u4EC0\u4E48

\u9879\u76EE\u522B\u540D

/@/ \u662F vite \u5185\u914D\u7F6E\u7684\u522B\u540D

/@/settings \u7B49\u540C\u4E8E src/settings

\u4E3A\u4EC0\u4E48\u662F/@/

\u56E0\u4E3A\u9879\u76EE\u662F\u4ECE vite1.0 \u8FC7\u6E21\u8FC7\u6765\u7684\uFF0Cvite1.0 \u53EA\u80FD\u4EE5 / \u5F00\u5934\uFF0C\u6240\u4EE5\u6709\u4E00\u90E8\u5206\u4ECE webpack \u7528\u6237\u8F6C\u8FC7\u6765\u7684\u53EF\u80FD\u4E0D\u4E60\u60EF\u3002

\u4E3A\u4EC0\u4E48\u5728\u672C\u5730\u6CA1\u6709\u6309\u9700\u5F15\u5165\u7EC4\u4EF6\u5E93\u6837\u5F0F\uFF0C\u5728\u751F\u4EA7\u624D\u5F15\u5165

\u5728 main.ts \u5185\u53EF\u4EE5\u770B\u5230\uFF0C\u672C\u5730\u5F00\u53D1\u4F1A\u5168\u91CF\u5F15\u5165 antd.less\uFF0Cvite-plugin-style-import \u5728\u672C\u5730\u662F\u6CA1\u6709\u4F5C\u7528\u7684\u3002

\u8FD9\u6837\u505A\u7684\u539F\u56E0\u4E3B\u8981\u662F\u52A0\u5FEB\u672C\u5730\u5F00\u53D1\u5237\u65B0\u901F\u5EA6\u3002\u5982\u679C\u5728\u672C\u5730\u5F00\u53D1\u4E2D\u4E5F\u6309\u9700\u6309\u9700\u5F15\u5165\uFF0C\u5219\u5728\u6D4F\u89C8\u5668\u63A7\u5236\u53F0\u5185\u53EF\u4EE5\u770B\u5230\uFF0C\u5E73\u5747\u4E00\u4E2A\u9875\u9762\u5927\u6982\u589E\u52A0\u4E86 100 \u6B21 http \u8BF7\u6C42\u3002\u5982\u679C\u5168\u91CF\u5F15\u5165\uFF0C\u53EA\u589E\u52A0\u4E86\u4E00\u4E2A\u8BF7\u6C42\uFF0C\u6240\u4EE5\u4E3A\u4E86\u51CF\u5C11\u8BF7\u6C42\u6570\u91CF\uFF0C\u624D\u8FD9\u6837\u79CD\u3002

// src/main.ts
+if (import.meta.env.DEV) {
+  import('ant-design-vue/dist/antd.less');
+}
+
+// build/vite/plugin/styleImport
+import styleImport from 'vite-plugin-style-import';
+export function configStyleImportPlugin(isBuild: boolean) {
+  if (!isBuild) return [];
+  const styleImportPlugin = styleImport({
+    libs: [
+      {
+        libraryName: 'ant-design-vue',
+        esModule: true,
+        resolveStyle: (name) => {
+          return \`ant-design-vue/es/\${name}/style/index\`;
+        },
+      },
+    ],
+  });
+  return styleImportPlugin;
+}
+

\u4E3A\u4EC0\u4E48\u5355\u72EC\u628A moment \u653E\u5230 dataUtil \u5185

\u5728 src/utils/dataUtil \u5185\uFF0C\u4F7F\u7528\u7684\u662F moment\uFF0C\u5176\u6B21\u5728\u9875\u9762\u4E2D\u5BF9\u65F6\u95F4\u7684\u64CD\u4F5C\u4E5F\u662F\u4F7F\u7528 dateUtil\uFF0C\u800C\u4E0D\u662F\u76F4\u63A5 import moment from 'moment'\u3002

\u8FD9\u6837\u505A\u4E3B\u8981\u662F\u65B9\u4FBF\u540E\u7EED\u5207\u6362\u5230 dayjs\uFF0C\u56E0\u4E3A api \u4E00\u6837\uFF0C\u6240\u4EE5\u5728\u540E\u7EED\u5207\u6362\u4E2D\uFF0C\u53EA\u9700\u66F4\u6539 dataUtil \u5185\u7684 import \u5373\u53EF\uFF0C\u800C\u4E0D\u7528\u5168\u90E8\u66F4\u6539\u3002

`,13),e=[o];function c(l,i,u,r,k,d){return a(),s("div",null,e)}var g=n(p,[["render",c]]);export{h as __pageData,g as default}; diff --git a/assets/other_doubt.md.a4551c31.lean.js b/assets/other_doubt.md.a4551c31.lean.js new file mode 100644 index 00000000..e4f3d30b --- /dev/null +++ b/assets/other_doubt.md.a4551c31.lean.js @@ -0,0 +1,23 @@ +import{_ as n,f as s,e as a,N as t}from"./plugin-vue_export-helper.147b70e9.js";const h='{"title":"\u5E38\u89C1\u7591\u70B9\u8BF4\u660E","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u9879\u76EE\u522B\u540D","slug":"\u9879\u76EE\u522B\u540D"},{"level":2,"title":"\u4E3A\u4EC0\u4E48\u5728\u672C\u5730\u6CA1\u6709\u6309\u9700\u5F15\u5165\u7EC4\u4EF6\u5E93\u6837\u5F0F\uFF0C\u5728\u751F\u4EA7\u624D\u5F15\u5165","slug":"\u4E3A\u4EC0\u4E48\u5728\u672C\u5730\u6CA1\u6709\u6309\u9700\u5F15\u5165\u7EC4\u4EF6\u5E93\u6837\u5F0F\uFF0C\u5728\u751F\u4EA7\u624D\u5F15\u5165"},{"level":2,"title":"\u4E3A\u4EC0\u4E48\u5355\u72EC\u628A moment \u653E\u5230 dataUtil \u5185","slug":"\u4E3A\u4EC0\u4E48\u5355\u72EC\u628A-moment-\u653E\u5230-datautil-\u5185"}],"relativePath":"other/doubt.md","lastUpdated":1694442156385}',p={},o=t(`__VP_STATIC_START__

\u5E38\u89C1\u7591\u70B9\u8BF4\u660E

\u8BE5\u5206\u7C7B\u4E3B\u8981\u8BF4\u660E\u4E00\u4E9B\u5730\u65B9\u4E3A\u4EC0\u4E48\u8FD9\u6837\u505A\uFF0C\u4EE5\u53CA\u539F\u56E0\u662F\u4EC0\u4E48

\u9879\u76EE\u522B\u540D

/@/ \u662F vite \u5185\u914D\u7F6E\u7684\u522B\u540D

/@/settings \u7B49\u540C\u4E8E src/settings

\u4E3A\u4EC0\u4E48\u662F/@/

\u56E0\u4E3A\u9879\u76EE\u662F\u4ECE vite1.0 \u8FC7\u6E21\u8FC7\u6765\u7684\uFF0Cvite1.0 \u53EA\u80FD\u4EE5 / \u5F00\u5934\uFF0C\u6240\u4EE5\u6709\u4E00\u90E8\u5206\u4ECE webpack \u7528\u6237\u8F6C\u8FC7\u6765\u7684\u53EF\u80FD\u4E0D\u4E60\u60EF\u3002

\u4E3A\u4EC0\u4E48\u5728\u672C\u5730\u6CA1\u6709\u6309\u9700\u5F15\u5165\u7EC4\u4EF6\u5E93\u6837\u5F0F\uFF0C\u5728\u751F\u4EA7\u624D\u5F15\u5165

\u5728 main.ts \u5185\u53EF\u4EE5\u770B\u5230\uFF0C\u672C\u5730\u5F00\u53D1\u4F1A\u5168\u91CF\u5F15\u5165 antd.less\uFF0Cvite-plugin-style-import \u5728\u672C\u5730\u662F\u6CA1\u6709\u4F5C\u7528\u7684\u3002

\u8FD9\u6837\u505A\u7684\u539F\u56E0\u4E3B\u8981\u662F\u52A0\u5FEB\u672C\u5730\u5F00\u53D1\u5237\u65B0\u901F\u5EA6\u3002\u5982\u679C\u5728\u672C\u5730\u5F00\u53D1\u4E2D\u4E5F\u6309\u9700\u6309\u9700\u5F15\u5165\uFF0C\u5219\u5728\u6D4F\u89C8\u5668\u63A7\u5236\u53F0\u5185\u53EF\u4EE5\u770B\u5230\uFF0C\u5E73\u5747\u4E00\u4E2A\u9875\u9762\u5927\u6982\u589E\u52A0\u4E86 100 \u6B21 http \u8BF7\u6C42\u3002\u5982\u679C\u5168\u91CF\u5F15\u5165\uFF0C\u53EA\u589E\u52A0\u4E86\u4E00\u4E2A\u8BF7\u6C42\uFF0C\u6240\u4EE5\u4E3A\u4E86\u51CF\u5C11\u8BF7\u6C42\u6570\u91CF\uFF0C\u624D\u8FD9\u6837\u79CD\u3002

// src/main.ts
+if (import.meta.env.DEV) {
+  import('ant-design-vue/dist/antd.less');
+}
+
+// build/vite/plugin/styleImport
+import styleImport from 'vite-plugin-style-import';
+export function configStyleImportPlugin(isBuild: boolean) {
+  if (!isBuild) return [];
+  const styleImportPlugin = styleImport({
+    libs: [
+      {
+        libraryName: 'ant-design-vue',
+        esModule: true,
+        resolveStyle: (name) => {
+          return \`ant-design-vue/es/\${name}/style/index\`;
+        },
+      },
+    ],
+  });
+  return styleImportPlugin;
+}
+

\u4E3A\u4EC0\u4E48\u5355\u72EC\u628A moment \u653E\u5230 dataUtil \u5185

\u5728 src/utils/dataUtil \u5185\uFF0C\u4F7F\u7528\u7684\u662F moment\uFF0C\u5176\u6B21\u5728\u9875\u9762\u4E2D\u5BF9\u65F6\u95F4\u7684\u64CD\u4F5C\u4E5F\u662F\u4F7F\u7528 dateUtil\uFF0C\u800C\u4E0D\u662F\u76F4\u63A5 import moment from 'moment'\u3002

\u8FD9\u6837\u505A\u4E3B\u8981\u662F\u65B9\u4FBF\u540E\u7EED\u5207\u6362\u5230 dayjs\uFF0C\u56E0\u4E3A api \u4E00\u6837\uFF0C\u6240\u4EE5\u5728\u540E\u7EED\u5207\u6362\u4E2D\uFF0C\u53EA\u9700\u66F4\u6539 dataUtil \u5185\u7684 import \u5373\u53EF\uFF0C\u800C\u4E0D\u7528\u5168\u90E8\u66F4\u6539\u3002

__VP_STATIC_END__`,13),e=[o];function c(l,i,u,r,k,d){return a(),s("div",null,e)}var g=n(p,[["render",c]]);export{h as __pageData,g as default}; diff --git a/assets/other_faq.md.c3ca86c2.js b/assets/other_faq.md.c3ca86c2.js new file mode 100644 index 00000000..8e2d9e55 --- /dev/null +++ b/assets/other_faq.md.c3ca86c2.js @@ -0,0 +1,67 @@ +import{_ as a,f as n,e as s,N as e}from"./plugin-vue_export-helper.147b70e9.js";const k='{"title":"\u5E38\u89C1\u95EE\u9898","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u524D\u8A00","slug":"\u524D\u8A00"},{"level":2,"title":"\u5173\u4E8E\u7F13\u5B58\u66F4\u65B0\u95EE\u9898","slug":"\u5173\u4E8E\u7F13\u5B58\u66F4\u65B0\u95EE\u9898"},{"level":2,"title":"\u5173\u4E8E\u4FEE\u6539\u914D\u7F6E\u6587\u4EF6\u7684\u95EE\u9898","slug":"\u5173\u4E8E\u4FEE\u6539\u914D\u7F6E\u6587\u4EF6\u7684\u95EE\u9898"},{"level":2,"title":"esbuild \u6A21\u5F0F\u4E0B\u5F00\u542F LEGACY \u6253\u5305\u5931\u8D25","slug":"esbuild-\u6A21\u5F0F\u4E0B\u5F00\u542F-legacy-\u6253\u5305\u5931\u8D25"},{"level":2,"title":"ant-design-vue \u63A7\u5236\u53F0\u8B66\u544A","slug":"ant-design-vue-\u63A7\u5236\u53F0\u8B66\u544A"},{"level":2,"title":"\u6DFB\u52A0\u83DC\u5355\u540E\u6CA1\u663E\u793A","slug":"\u6DFB\u52A0\u83DC\u5355\u540E\u6CA1\u663E\u793A"},{"level":2,"title":"imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25","slug":"imagemin-\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25"},{"level":2,"title":"\u4F7F\u7528 yarn \u5B89\u88C5 imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25","slug":"\u4F7F\u7528-yarn-\u5B89\u88C5-imagemin-\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25"},{"level":2,"title":"\u5728 Linux \u5185\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25","slug":"\u5728-linux-\u5185\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25"},{"level":2,"title":"\u672C\u5730\u8FD0\u884C\u62A5\u9519","slug":"\u672C\u5730\u8FD0\u884C\u62A5\u9519"},{"level":2,"title":"tab \u9875\u5207\u6362\u540E\u9875\u9762\u7A7A\u767D","slug":"tab-\u9875\u5207\u6362\u540E\u9875\u9762\u7A7A\u767D"},{"level":2,"title":"\u7EC4\u4EF6\u547D\u540D\u95EE\u9898","slug":"\u7EC4\u4EF6\u547D\u540D\u95EE\u9898"},{"level":2,"title":"\u6211\u7684\u4EE3\u7801\u672C\u5730\u5F00\u53D1\u53EF\u4EE5\uFF0C\u6253\u5305\u5C31\u4E0D\u884C\u4E86","slug":"\u6211\u7684\u4EE3\u7801\u672C\u5730\u5F00\u53D1\u53EF\u4EE5\uFF0C\u6253\u5305\u5C31\u4E0D\u884C\u4E86"},{"level":2,"title":"safari \u95EE\u9898","slug":"safari-\u95EE\u9898"},{"level":2,"title":"\u6A21\u7248\u533A\u522B","slug":"\u6A21\u7248\u533A\u522B"},{"level":2,"title":"\u73AF\u5883\u95EE\u9898","slug":"\u73AF\u5883\u95EE\u9898"},{"level":2,"title":"\u4F9D\u8D56\u5B89\u88C5\u95EE\u9898","slug":"\u4F9D\u8D56\u5B89\u88C5\u95EE\u9898"},{"level":2,"title":"\u5982\u4F55\u4FDD\u8BC1\u6211\u7684\u4EE3\u7801\u80FD\u66F4\u65B0\u5230\u6700\u65B0\u4EE3\u7801","slug":"\u5982\u4F55\u4FDD\u8BC1\u6211\u7684\u4EE3\u7801\u80FD\u66F4\u65B0\u5230\u6700\u65B0\u4EE3\u7801"},{"level":2,"title":"\u6253\u5305\u6587\u4EF6\u8FC7\u5927","slug":"\u6253\u5305\u6587\u4EF6\u8FC7\u5927"},{"level":2,"title":"\u8FD0\u884C\u9519\u8BEF","slug":"\u8FD0\u884C\u9519\u8BEF"},{"level":2,"title":"\u4E3A\u4EC0\u4E48\u662F moment.js","slug":"\u4E3A\u4EC0\u4E48\u662F-moment-js"},{"level":2,"title":"\u63A7\u5236\u53F0\u8DEF\u7531\u8B66\u544A\u95EE\u9898","slug":"\u63A7\u5236\u53F0\u8DEF\u7531\u8B66\u544A\u95EE\u9898"},{"level":2,"title":"\u542F\u52A8\u62A5\u9519","slug":"\u542F\u52A8\u62A5\u9519"},{"level":2,"title":"\u9875\u9762\u62A5\u9519","slug":"\u9875\u9762\u62A5\u9519"},{"level":2,"title":"\u8DE8\u57DF\u95EE\u9898","slug":"\u8DE8\u57DF\u95EE\u9898"},{"level":2,"title":"\u63A5\u53E3\u8BF7\u6C42\u95EE\u9898","slug":"\u63A5\u53E3\u8BF7\u6C42\u95EE\u9898"},{"level":2,"title":"\u7EC4\u4EF6\u5E93\u95EE\u9898","slug":"\u7EC4\u4EF6\u5E93\u95EE\u9898"}],"relativePath":"other/faq.md","lastUpdated":1694442156385}',t={},p=e(`

\u5E38\u89C1\u95EE\u9898

TIP

\u5217\u4E3E\u4E86\u4E00\u4E9B\u5E38\u89C1\u7684\u95EE\u9898\u3002\u6709\u95EE\u9898\u53EF\u4EE5\u5148\u6765\u8FD9\u91CC\u5BFB\u627E\uFF0C\u5982\u679C\u6CA1\u6709\u53EF\u4EE5\u5728 issue \u63D0\u3002

\u524D\u8A00

\u9047\u5230\u95EE\u9898,\u53EF\u4EE5\u5148\u4ECE\u4EE5\u4E0B\u51E0\u4E2A\u65B9\u9762\u67E5\u627E

  1. \u5BF9\u5E94\u6A21\u5757\u7684 GitHub \u4ED3\u5E93 issue \u641C\u7D22
  2. \u4ECEgoogle\u641C\u7D22\u95EE\u9898
  3. \u4ECE\u767E\u5EA6\u641C\u7D22\u95EE\u9898
  4. \u5728\u4E0B\u9762\u5217\u8868\u627E\u4E0D\u5230\u95EE\u9898\u53EF\u4EE5\u5230 issue \u63D0\u95EE issues
  5. \u5982\u679C\u4E0D\u662F\u95EE\u9898\u7C7B\u578B\u7684\uFF0C\u9700\u8981\u8BA8\u8BBA\u7684\uFF0C\u8BF7\u5230 discussions \u8BA8\u8BBA

\u5173\u4E8E\u7F13\u5B58\u66F4\u65B0\u95EE\u9898

vben-admin \u7684\u9879\u76EE\u914D\u7F6E\u9ED8\u8BA4\u662F\u7F13\u5B58\u5728 localStorage \u5185\uFF0C\u6240\u4EE5\u7248\u672C\u66F4\u65B0\u540E\u53EF\u80FD\u6709\u4E9B\u914D\u7F6E\u6CA1\u6539\u53D8\u3002

\u89E3\u51B3\u65B9\u5F0F\u662F\u6BCF\u6B21\u66F4\u65B0\u4EE3\u7801\u7684\u65F6\u5019\u4FEE\u6539 package.json \u5185\u7684 version \u7248\u672C\u53F7. \u56E0\u4E3A localStorage \u7684 key \u662F\u6839\u636E\u7248\u672C\u53F7\u6765\u7684\u3002\u6240\u4EE5\u66F4\u65B0\u540E\u7248\u672C\u4E0D\u540C\u524D\u9762\u7684\u914D\u7F6E\u4F1A\u5931\u6548\u3002\u91CD\u65B0\u767B\u5F55\u5373\u53EF

VUE_VBEN_ADMIN__DEVELOPMENT__2.0.3__COMMON__LOCAL__KEY__ key \u7684\u7EC4\u6210\u662F [\u9879\u76EE\u540D]+[\u5F00\u53D1\u73AF\u5883]+[\u7248\u672C\u53F7]+[key]

\u5173\u4E8E\u4FEE\u6539\u914D\u7F6E\u6587\u4EF6\u7684\u95EE\u9898

\u5F53\u4FEE\u6539 .env \u7B49\u73AF\u5883\u6587\u4EF6\u53CA vite.config.ts \u6587\u4EF6\u65F6\uFF0Cvite \u4F1A\u81EA\u52A8\u91CD\u542F\u670D\u52A1\u3002

\u81EA\u52A8\u91CD\u542F\u6709\u51E0\u7387\u51FA\u73B0\u95EE\u9898\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u9879\u76EE\u5373\u53EF\u89E3\u51B3.

esbuild \u6A21\u5F0F\u4E0B\u5F00\u542F LEGACY \u6253\u5305\u5931\u8D25

\u5982\u679C\u5C06 \b build.minify \u8BBE\u7F6E\u4E3A 'esbuild'\uFF0C\u4E14\u4E0D\u80FD\u542F\u7528 LEGACY\uFF0C\u5426\u5219\u6253\u5305\u5C06\u4F1A\u62A5\u9519\uFF0C\u4E24\u8005\u9009\u5176\u4E00\u5373\u53EF\u6253\u5305\u3002

ant-design-vue \u63A7\u5236\u53F0\u8B66\u544A

\u5728\u63A7\u5236\u53F0\u770B\u5230\u4EE5\u4E0B\u8B66\u544A\u7684\u539F\u56E0\u662F ant-design-vue \u4F1A\u68C0\u6D4B\u662F\u5426\u4F7F\u7528\u4E86 babel-plugin-import \u6765\u5224\u65AD\u662F\u5426\u8FDB\u884C\u4E86\u7EC4\u4EF6\u5E93\u7684\u6309\u9700\u5F15\u5165\u3002

\u4F46\u662F\u9879\u76EE\u4F7F\u7528\u7684\u662F vite \u7684\u63D2\u4EF6 vite-plugin-style-import \u6765\u8FDB\u884C\u6309\u9700\u5F15\u5165\u3002\u5728 vite \u5185\u6CA1\u5FC5\u8981\u4F7F\u7528 babel \u5728\u8F6C\u6362\u4E00\u6B21\u4EE3\u7801\u4E86\u3002

\u6240\u4EE5\u60F3\u5173\u95ED\u8FD9\u4E2A\u8B66\u544A\uFF0C\u5F97\u7B49 ant-design-vue \u63D0\u4F9B\u53EF\u4EE5\u5173\u95ED\u8BE5\u8B66\u544A\u7684\u914D\u7F6E\u3002

You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size. Not support Vite !!!
+

\u6DFB\u52A0\u83DC\u5355\u540E\u6CA1\u663E\u793A

\u83DC\u5355\u5FC5\u987B\u548C\u8DEF\u7531\u5339\u914D\u624D\u4F1A\u663E\u793A\u5728\u754C\u9762\u4E0A\uFF0C\u6240\u4EE5\u5F97\u786E\u4FDD\u83DC\u5355\u548C\u5BF9\u5E94\u7684\u8DEF\u7531\u5B58\u5728\u5373\u53EF\u663E\u793A.

imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25

\u7531\u4E8E imagemin \u5728\u56FD\u5185\u5B89\u88C5\u56F0\u96BE\uFF0C\u63D0\u4F9B\u4EE5\u4E0B\u51E0\u4E2A\u89E3\u51B3\u65B9\u6848\uFF1A

  1. \u4F7F\u7528 yarn \u5728 package.json \u5185\u914D\u7F6E\uFF08\u63A8\u8350\uFF0C\u9879\u76EE\u5185\u5DF2\u96C6\u6210\uFF0C\u524D\u63D0\u662F\u5FC5\u987B\u4F7F\u7528 yarn\uFF09
"resolutions": {
+  "bin-wrapper": "npm:bin-wrapper-china"
+}
+
  1. \u4F7F\u7528 npm,\u5728\u7535\u8111 host \u6587\u4EF6\u52A0\u4E0A\u5982\u4E0B\u914D\u7F6E\u5373\u53EF
199.232.4.133 raw.githubusercontent.com
+

\u4F7F\u7528 yarn \u5B89\u88C5 imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25

\u5982\u679C\u4F7F\u7528 yarn \u8FD8\u662F\u4E0D\u80FD\u5B89\u88C5\u4F9D\u8D56\uFF0C\u53EF\u4EE5\u5C06\u56FE\u7247\u538B\u7F29\u529F\u80FD\u79FB\u9664\uFF0C\u79FB\u9664\u65B9\u6CD5\u5982\u4E0B\uFF1A

  • \u5728 package.json \u5185\u5220\u9664 vite-plugin-imagemin \u8FD9\u4E2A\u4F9D\u8D56\u3002\u8FD9\u4F1A\u5BFC\u81F4\u56FE\u7247\u6CA1\u6709\u538B\u7F29\uFF0C\u4F46\u662F\u53EF\u4EE5\u624B\u52A8\u5230\u5728\u7EBF\u7F51\u7AD9\u8FDB\u884C\u538B\u7F29\u3002\u8FD9\u91CC\u63A8\u8350tinypng
    1. \u6CE8\u91CA vite-plugin-imagemin \u63D2\u4EF6\u5F15\u7528
import { configImageminPlugin } from './imagemin';
+VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
+

\u5728 Linux \u5185\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25

\u5982\u679C\u6267\u884C yarn install \u4F1A\u51FA\u73B0\u4EE5\u4E0B\u9519\u8BEF\uFF1A

gifsicle pre-build test failed
+compiling from source
+

\u53EF\u80FD\u662F linux \u670D\u52A1\u5668\u9700\u8981\u914D\u7F6E\u4E0B\u73AF\u5883\uFF0Cimagemin \u8FD9\u4E2A\u4F1A\u5BFC\u81F4\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\u3002

\u8FD9\u91CC\u4EE5Centos\u4E3A\u4F8B

  • \u89E3\u51B3\u65B9\u5F0F 1:
  1. \u5C06\u4EE5\u4E0B\u5185\u5BB9\u6DFB\u52A0\u5230 yum \u6E90
[nasm]
+name=The Netwide Assembler
+baseurl=http://www.nasm.us/pub/nasm/stable/linux/
+enabled=1
+gpgcheck=0
+
+[nasm-testing]
+name=The Netwide Assembler (release candidate builds)
+baseurl=http://www.nasm.us/pub/nasm/testing/linux/
+enabled=0
+gpgcheck=0
+
+[nasm-snapshot]
+name=The Netwide Assembler (daily snapshot builds)
+baseurl=http://www.nasm.us/pub/nasm/snapshots/latest/linux/
+enabled=0
+gpgcheck=0
+

\u5728 /etc/yum.repos.d/ \u4E0B\u65B0\u5EFA Centos-Nasm.repo\uFF0C\u5C06\u4EE5\u4E0A\u5185\u5BB9\u590D\u5236\u5230\u8FD9\u4E2A\u6587\u4EF6\u5373\u53EF

  1. \u6267\u884C yum install libtool automake autoconf nasm
  2. \u91CD\u65B0\u6267\u884C yarn install \u5373\u53EF

\u672C\u5730\u8FD0\u884C\u62A5\u9519

\u7531\u4E8E vite \u5728\u672C\u5730\u6CA1\u6709\u8F6C\u6362\u4EE3\u7801\uFF0C\u4E14\u4EE3\u7801\u4E2D\u7528\u5230\u4E86\u53EF\u9009\u94FE\u7B49\u6BD4\u8F83\u65B0\u7684\u8BED\u6CD5\u3002\u6240\u4EE5\u672C\u5730\u5F00\u53D1\u9700\u8981\u4F7F\u7528\u7248\u672C\u8F83\u9AD8\u7684\u6D4F\u89C8\u5668(Chrome 85+)\u8FDB\u884C\u5F00\u53D1

tab \u9875\u5207\u6362\u540E\u9875\u9762\u7A7A\u767D

\u8FD9\u662F\u7531\u4E8E\u5F00\u542F\u4E86\u8DEF\u7531\u5207\u6362\u52A8\u753B,\u4E14\u5BF9\u5E94\u7684\u9875\u9762\u7EC4\u4EF6\u5B58\u5728\u591A\u4E2A\u6839\u8282\u70B9\u5BFC\u81F4\u7684\uFF0C\u5728\u9875\u9762\u6700\u5916\u5C42\u6DFB\u52A0<div></div>\u5373\u53EF

\u9519\u8BEF\u793A\u4F8B

<template>
+  <!-- \u6CE8\u91CA\u4E5F\u7B97\u4E00\u4E2A\u8282\u70B9 -->
+  <h1>text h1</h1>
+  <h2>text h2</h2>
+</template>
+

\u6B63\u786E\u793A\u4F8B

<template>
+  <div>
+    <h1>text h1</h1>
+    <h2>text h2</h2>
+  </div>
+</template>
+

\u63D0\u793A

  • \u5982\u679C\u60F3\u4F7F\u7528\u591A\u4E2A\u6839\u6807\u7B7E\uFF0C\u53EF\u4EE5\u7981\u7528\u8DEF\u7531\u5207\u6362\u52A8\u753B
  • template \u4E0B\u9762\u7684\u6839\u6CE8\u91CA\u8282\u70B9\u4E5F\u7B97\u4E00\u4E2A\u8282\u70B9

\u7EC4\u4EF6\u547D\u540D\u95EE\u9898

\u76EE\u524D\u5728 vite+vue3.0.5 \u7248\u672C\u4E2D\uFF0C\u5982\u679C\u7EC4\u4EF6\u547D\u540D\u643A\u5E26\u5173\u952E\u5B57\uFF0C\u5219\u53EF\u80FD\u4F1A\u5BFC\u81F4\u5185\u5B58\u6EA2\u51FA\u3002\u4F8B\u5982 ImportExcel excel \u5BFC\u5165\u7EC4\u4EF6\u3002

\u6211\u7684\u4EE3\u7801\u672C\u5730\u5F00\u53D1\u53EF\u4EE5\uFF0C\u6253\u5305\u5C31\u4E0D\u884C\u4E86

\u76EE\u524D\u53D1\u73B0\u8FD9\u4E2A\u539F\u56E0\u53EF\u80FD\u6709\u4EE5\u4E0B\uFF0C\u53EF\u4EE5\u4ECE\u4EE5\u4E0B\u539F\u56E0\u6765\u6392\u67E5\uFF0C\u5982\u679C\u8FD8\u6709\u522B\u7684\u53EF\u80FD\uFF0C\u53EF\u4EE5\u63D0\u4EA4 pr \u6765\u544A\u8BC9\u6211

  1. \u4F7F\u7528\u4E86 ctx \u8FD9\u4E2A\u53D8\u91CF\uFF0Cctx \u672C\u8EAB\u672A\u66B4\u9732\u51FA\u5728\u5B9E\u4F8B\u7C7B\u578B\u5185\uFF0C\u5C24\u5927\u4E5F\u662F\u8BF4\u4E86\u4E0D\u8981\u7528\u8FD9\u4E2A\u5C5E\u6027\u3002\u8FD9\u4E2A\u5C5E\u6027\u53EA\u662F\u7528\u4E8E\u5185\u90E8\u4F7F\u7528\u3002
import { getCurrentInstance } from 'vue';
+getCurrentInstance().ctx.xxxx;
+

safari \u95EE\u9898

\u76EE\u524D\u5728 safari \u4E0A\u9762\u672C\u5730\u5F00\u53D1\u8FD0\u884C\u6837\u5F0F\u4F1A\u6709\u95EE\u9898\uFF0C\u8FD8\u672A\u627E\u5230\u539F\u56E0\uFF0C\u6709\u77E5\u9053\u7684\u4E5F\u53EF\u4EE5\u544A\u8BC9\u6211\u3002

\u6A21\u7248\u533A\u522B

  • Vue-Vben-Admin - \u662F\u5305\u542B Demo \u793A\u4F8B\u7684,\u4E2A\u4EBA\u5EFA\u8BAE\u4E0D\u8981\u5728\u8FD9\u4E0A\u9762\u8FDB\u884C\u5F00\u53D1\u3002\u5F53\u7136\uFF0C\u4F60\u5982\u679C\u52A8\u624B\u80FD\u529B\u5F3A\u7684\u8BDD\u53EF\u4EE5\u76F4\u63A5\u6539\u3002
  • Vue-Vben-Admin-Thin-Next \u7CBE\u7B80\u4E86\u4EE3\u7801\u540E\u7684\u6A21\u7248\u9879\u76EE\u3002\u9002\u5408\u5728\u8FD9\u57FA\u7840\u4E0A\u8FDB\u884C\u4E8C\u6B21\u5F00\u53D1\u3002

\u73AF\u5883\u95EE\u9898

\u5982\u679C\u51FA\u73B0\u4F9D\u8D56\u5B89\u88C5\u62A5\u9519\uFF0C\u542F\u52A8\u62A5\u9519\u7B49\u3002\u5148\u68C0\u67E5\u7535\u8111\u73AF\u5883\u6709\u6CA1\u6709\u5B89\u88C5\u9F50\u5168\u3002

  • Node \u7248\u672C\u5FC5\u987B\u5927\u4E8E12.0.0\u4E0D\u652F\u6301 13\uFF0C \u63A8\u8350 14 \u7248\u672C\u3002
  • Git
  • Yarn \u6700\u65B0\u7248

\u4F9D\u8D56\u5B89\u88C5\u95EE\u9898

  • \u5982\u679C\u4F9D\u8D56\u5B89\u88C5\u4E0D\u4E86\u6216\u8005\u542F\u52A8\u62A5\u9519\u53EF\u4EE5\u5148\u5C1D\u8BD5 \u5220\u9664 yarn.lock \u548C node_modules\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C yarn install
  • \u5982\u679C\u4F9D\u8D56\u5B89\u88C5\u4E0D\u4E86\u6216\u8005\u62A5\u9519\uFF0C\u53EF\u4EE5\u5C1D\u8BD5\u5207\u6362\u624B\u673A\u70ED\u70B9\u6765\u8FDB\u884C\u4F9D\u8D56\u5B89\u88C5\u3002
  • \u5982\u679C\u8FD8\u662F\u4E0D\u884C\uFF0C\u53EF\u4EE5\u81EA\u884C\u914D\u7F6E\u56FD\u5185\u955C\u50CF\u5B89\u88C5\u3002
  • \u4E5F\u53EF\u4EE5\u5728\u9879\u76EE\u6839\u76EE\u5F55\u521B\u5EFA .npmrc \u6587\u4EF6\uFF0C\u5185\u5BB9\u5982\u4E0B
# .npmrc
+registry = https://registry.npm.taobao.org
+

\u7136\u540E\u91CD\u65B0\u6267\u884Cyarn run reinstall\u7B49\u5F85\u5B89\u88C5\u5B8C\u6210\u5373\u53EF

\u5982\u4F55\u4FDD\u8BC1\u6211\u7684\u4EE3\u7801\u80FD\u66F4\u65B0\u5230\u6700\u65B0\u4EE3\u7801

\u5982\u679C\u4F60\u4F7F\u7528\u4E86\u8BE5\u9879\u76EE\u8FDB\u884C\u9879\u76EE\u5F00\u53D1\u3002\u5F00\u53D1\u4E4B\u4E2D\u60F3\u540C\u6B65\u6700\u65B0\u7684\u4EE3\u7801\u3002\u4F60\u53EF\u4EE5\u8BBE\u7F6E\u591A\u4E2A\u6E90\u7684\u65B9\u5F0F

  1. \u514B\u9686\u4EE3\u7801
git clone https://github.com/vbenjs/vben-admin-thin-next.git
+
  1. \u6DFB\u52A0\u81EA\u5DF1\u7684\u516C\u53F8 git \u6E90\u5730\u5740
# up \u4E3A\u6E90\u540D\u79F0,\u53EF\u4EE5\u968F\u610F\u8BBE\u7F6E
+# gitUrl\u4E3A\u5F00\u6E90\u6700\u65B0\u4EE3\u7801
+git remote add up gitUrl;
+
  1. \u63D0\u4EA4\u4EE3\u7801\u5230\u81EA\u5DF1\u516C\u53F8 git
# \u63D0\u4EA4\u4EE3\u7801\u5230\u81EA\u5DF1\u516C\u53F8
+# main\u4E3A\u5206\u652F\u540D \u9700\u8981\u81EA\u884C\u6839\u636E\u60C5\u51B5\u4FEE\u6539
+git push up main
+
+# \u540C\u6B65\u516C\u53F8\u7684\u4EE3\u7801
+# main\u4E3A\u5206\u652F\u540D \u9700\u8981\u81EA\u884C\u6839\u636E\u60C5\u51B5\u4FEE\u6539
+git pull up main
+
  1. \u5982\u4F55\u540C\u6B65\u5F00\u6E90\u6700\u65B0\u4EE3\u7801
git pull origin main
+

TIP

\u540C\u6B65\u4EE3\u7801\u7684\u65F6\u5019\u4F1A\u51FA\u73B0\u51B2\u7A81\u3002\u53EA\u9700\u8981\u628A\u51B2\u7A81\u89E3\u51B3\u5373\u53EF

\u6253\u5305\u6587\u4EF6\u8FC7\u5927

  • \u9996\u5148\uFF0C\u5B8C\u6574\u7248\u7531\u4E8E\u5F15\u7528\u4E86\u6BD4\u8F83\u591A\u7684\u5E93\u6587\u4EF6\uFF0C\u6240\u4EE5\u6253\u5305\u4F1A\u6BD4\u8F83\u5927\u3002\u53EF\u4EE5\u4F7F\u7528\u7CBE\u7B80\u7248\u6765\u8FDB\u884C\u5F00\u53D1

  • \u5176\u6B21\u5EFA\u8BAE\u5F00\u542F gzip\uFF0C\u4F7F\u7528\u4E4B\u540E\u4F53\u79EF\u4F1A\u53EA\u6709\u539F\u5148 1/3 \u5DE6\u53F3\u3002

gzip \u53EF\u4EE5\u7531\u670D\u52A1\u5668\u76F4\u63A5\u5F00\u542F\u3002\u5982\u679C\u662F\u8FD9\u6837\uFF0C\u524D\u7AEF\u4E0D\u9700\u8981\u6784\u5EFA .gz \u683C\u5F0F\u7684\u6587\u4EF6

\u5982\u679C\u524D\u7AEF\u6784\u5EFA\u4E86 .gz \u6587\u4EF6\uFF0C\u4EE5 nginx \u4E3A\u4F8B\uFF0Cnginx \u9700\u8981\u5F00\u542F gzip_static: on \u8FD9\u4E2A\u9009\u9879\u3002

  • \u5F00\u542F gzip \u7684\u540C\u65F6\u8FD8\u53EF\u4EE5\u540C\u65F6\u5F00\u542F brotli\uFF0C\u6BD4 gzip \u66F4\u597D\u7684\u538B\u7F29\u3002\u4E24\u8005\u53EF\u4EE5\u5171\u5B58

\u6CE8\u610F

  • gzip_static: \u8FD9\u4E2A\u6A21\u5757\u9700\u8981 nginx \u53E6\u5916\u5B89\u88C5\uFF0C\u9ED8\u8BA4\u7684 nginx \u6CA1\u6709\u5B89\u88C5\u8FD9\u4E2A\u6A21\u5757\u3002

  • \u5F00\u542F brotli \u4E5F\u9700\u8981 nginx \u53E6\u5916\u5B89\u88C5\u6A21\u5757

\u8FD0\u884C\u9519\u8BEF

\u5982\u679C\u51FA\u73B0\u7C7B\u4F3C\u4EE5\u4E0B\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u9879\u76EE\u5168\u8DEF\u5F84\uFF08\u5305\u542B\u6240\u6709\u7236\u7EA7\u8DEF\u5F84\uFF09\u4E0D\u80FD\u51FA\u73B0\u4E2D\u6587\u3001\u65E5\u6587\u3001\u97E9\u6587\u3002\u5426\u5219\u5C06\u4F1A\u51FA\u73B0\u8DEF\u5F84\u8BBF\u95EE 404 \u5BFC\u81F4\u4EE5\u4E0B\u95EE\u9898

[vite] Failed to resolve module import "ant-design-vue/dist/antd.css-vben-adminode_modulesant-design-vuedistantd.css". (imported by /@/setup/ant-design-vue/index.ts)
+

\u4E3A\u4EC0\u4E48\u662F moment.js

\u5F88\u591A\u4EBA\u95EE\u4E3A\u4EC0\u4E48\u4E0D\u7528dayjs\u3002\u5728\u9879\u76EE\u4F9D\u8D56\u4E2D\u53EF\u4EE5\u770B\u5230\uFF0C\u5B83\u662F Ant-Design-Vue \u5185\u90E8\u81EA\u5E26\u7684\u3002

\u76EE\u524D\u8FD8\u6CA1\u6709\u57FA\u4E8E Vite \u7684 dayjs \u66FF\u6362 momentjs \u65B9\u6848\uFF0Cwebpack \u5DF2\u7ECF\u6709\u4E86\u3002\u7B49\u4EE5\u540E\u51FA\u73B0\u4E86\u5728\u8FDB\u884C\u66FF\u6362\u3002

\u63A7\u5236\u53F0\u8DEF\u7531\u8B66\u544A\u95EE\u9898

\u5982\u679C\u770B\u5230\u63A7\u5236\u53F0\u6709\u5982\u4E0B\u8B66\u544A\uFF0C\u4E14\u9875\u9762\u80FD\u6B63\u5E38\u6253\u5F00 \u53EF\u4EE5\u5FFD\u7565\u8BE5\u8B66\u544A\u3002

\u540E\u7EED vue-router \u53EF\u80FD\u4F1A\u63D0\u4F9B\u914D\u7F6E\u9879\u6765\u5173\u95ED\u8B66\u544A

2.6.1\u53CA\u4EE5\u4E0A\u7248\u672C\u5DF2\u79FB\u9664\u6B64\u8B66\u544A

[Vue Router warn]: No match found for location with path "xxxx"
+

\u542F\u52A8\u62A5\u9519

\u5F53\u51FA\u73B0\u4EE5\u4E0B\u9519\u8BEF\u4FE1\u606F\u65F6\uFF0C\u8BF7\u68C0\u67E5\u4F60\u7684 nodejs \u7248\u672C\u53F7\u662F\u5426\u7B26\u5408\u8981\u6C42

TypeError: str.matchAll is not a function
+at Object.extractor (vue-vben-admin-main\\node_modules@purge-icons\\core\\dist\\index.js:146:27)
+at Extract (vue-vben-admin-main\\node_modules@purge-icons\\core\\dist\\index.js:173:54)
+
+

\u9875\u9762\u62A5\u9519

\u5F53\u9875\u9762\u51FA\u73B0\u4EE5\u4E0B\u62A5\u9519\uFF0C\u662F\u56E0\u4E3A /xxx \u5BF9\u5E94\u7684\u8DEF\u7531\u7EC4\u4EF6\u5185\u90E8\u51FA\u73B0\u4E86\u9519\u8BEF\u3002

 Uncaught (in promise) Error: Couldn't resolve component "default" at "/xxx"
+
+

\u53EF\u4EE5\u5C1D\u8BD5\u4ECE\u4EE5\u4E0B\u51E0\u70B9\u6392\u67E5

  1. \u68C0\u67E5\u5BF9\u5E94\u7EC4\u4EF6\u5185\u90E8 import \u7684\u6240\u6709\u6587\u4EF6\u662F\u5426\u6B63\u786E
  2. \u68C0\u67E5\u5F15\u5165\u65B9\u5F0F\u662F\u5426\u9519\u8BEF\u3002
// \u6B63\u786E\u7684
+import { cloneDeep } from 'lodash-es';
+
+// \u62A5\u9519
+import _ from 'lodash-es';
+
  1. \u68C0\u67E5\u6837\u5F0F\u662F\u5426\u4F7F\u7528\u53D8\u91CF\u53CA\u6709\u6CA1\u6709\u5F15\u5165\u5BF9\u5E94\u7684\u53D8\u91CF\u6587\u4EF6
  2. \u68C0\u67E5\u4EE3\u7801\u660E\u663E\u7684\u8BED\u6CD5\u9519\u8BEF

\u8FD9\u6837\u5C31\u4E0D\u4F1A\u662F\u4F7F\u7528\u7684\u53D6\u503C\u5FD8\u8BB0 xxx.value \u6765\u8FDB\u884C\u6570\u636E\u83B7\u53D6

\u8DE8\u57DF\u95EE\u9898

\u53C2\u8003\u8DE8\u57DF\u95EE\u9898

\u63A5\u53E3\u8BF7\u6C42\u95EE\u9898

proxy \u4EE3\u7406\u4E0D\u6210\u529F\uFF0C\u6CA1\u6709\u4EE3\u7406\u5230\u5B9E\u9645\u5730\u5740\uFF1F

\u4EE3\u7406\u53EA\u662F\u670D\u52A1\u8BF7\u6C42\u4EE3\u7406\uFF0C\u8FD9\u4E2A\u5730\u5740\u662F\u4E0D\u4F1A\u53D8\u7684\u3002 \u539F\u7406\u53EF\u4EE5\u7B80\u5355\u7684\u7406\u89E3\u4E3A\uFF0C\u5728\u672C\u5730\u542F\u4E86\u4E00\u4E2A\u670D\u52A1\uFF0C\u4F60\u5148\u8BF7\u6C42\u4E86\u672C\u5730\u7684\u670D\u52A1\uFF0C\u672C\u5730\u7684\u670D\u52A1\u8F6C\u53D1\u4E86\u4F60\u7684\u8BF7\u6C42\u5230\u5B9E\u9645\u670D\u52A1\u5668\u3002\u6240\u4EE5\u4F60\u5728\u6D4F\u89C8\u5668\u4E0A\u770B\u5230\u7684\u8BF7\u6C42\u5730\u5740\u8FD8\u662F http://localhost:8000/xxx\u3002\u4EE5\u670D\u52A1\u7AEF\u662F\u5426\u6536\u5230\u8BF7\u6C42\u4E3A\u51C6\u3002

\u7EC4\u4EF6\u5E93\u95EE\u9898

\u8DDF\u7EC4\u4EF6\u5E93\u76F8\u5173\u7684\u95EE\u9898\u53EF\u4EE5\u67E5\u770B\u5E38\u89C1\u95EE\u9898

`,114),o=[p];function l(c,i,r,u,d,h){return s(),n("div",null,o)}var m=a(t,[["render",l]]);export{k as __pageData,m as default}; diff --git a/assets/other_faq.md.c3ca86c2.lean.js b/assets/other_faq.md.c3ca86c2.lean.js new file mode 100644 index 00000000..b8af4772 --- /dev/null +++ b/assets/other_faq.md.c3ca86c2.lean.js @@ -0,0 +1,67 @@ +import{_ as a,f as n,e as s,N as e}from"./plugin-vue_export-helper.147b70e9.js";const k='{"title":"\u5E38\u89C1\u95EE\u9898","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u524D\u8A00","slug":"\u524D\u8A00"},{"level":2,"title":"\u5173\u4E8E\u7F13\u5B58\u66F4\u65B0\u95EE\u9898","slug":"\u5173\u4E8E\u7F13\u5B58\u66F4\u65B0\u95EE\u9898"},{"level":2,"title":"\u5173\u4E8E\u4FEE\u6539\u914D\u7F6E\u6587\u4EF6\u7684\u95EE\u9898","slug":"\u5173\u4E8E\u4FEE\u6539\u914D\u7F6E\u6587\u4EF6\u7684\u95EE\u9898"},{"level":2,"title":"esbuild \u6A21\u5F0F\u4E0B\u5F00\u542F LEGACY \u6253\u5305\u5931\u8D25","slug":"esbuild-\u6A21\u5F0F\u4E0B\u5F00\u542F-legacy-\u6253\u5305\u5931\u8D25"},{"level":2,"title":"ant-design-vue \u63A7\u5236\u53F0\u8B66\u544A","slug":"ant-design-vue-\u63A7\u5236\u53F0\u8B66\u544A"},{"level":2,"title":"\u6DFB\u52A0\u83DC\u5355\u540E\u6CA1\u663E\u793A","slug":"\u6DFB\u52A0\u83DC\u5355\u540E\u6CA1\u663E\u793A"},{"level":2,"title":"imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25","slug":"imagemin-\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25"},{"level":2,"title":"\u4F7F\u7528 yarn \u5B89\u88C5 imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25","slug":"\u4F7F\u7528-yarn-\u5B89\u88C5-imagemin-\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25"},{"level":2,"title":"\u5728 Linux \u5185\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25","slug":"\u5728-linux-\u5185\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25"},{"level":2,"title":"\u672C\u5730\u8FD0\u884C\u62A5\u9519","slug":"\u672C\u5730\u8FD0\u884C\u62A5\u9519"},{"level":2,"title":"tab \u9875\u5207\u6362\u540E\u9875\u9762\u7A7A\u767D","slug":"tab-\u9875\u5207\u6362\u540E\u9875\u9762\u7A7A\u767D"},{"level":2,"title":"\u7EC4\u4EF6\u547D\u540D\u95EE\u9898","slug":"\u7EC4\u4EF6\u547D\u540D\u95EE\u9898"},{"level":2,"title":"\u6211\u7684\u4EE3\u7801\u672C\u5730\u5F00\u53D1\u53EF\u4EE5\uFF0C\u6253\u5305\u5C31\u4E0D\u884C\u4E86","slug":"\u6211\u7684\u4EE3\u7801\u672C\u5730\u5F00\u53D1\u53EF\u4EE5\uFF0C\u6253\u5305\u5C31\u4E0D\u884C\u4E86"},{"level":2,"title":"safari \u95EE\u9898","slug":"safari-\u95EE\u9898"},{"level":2,"title":"\u6A21\u7248\u533A\u522B","slug":"\u6A21\u7248\u533A\u522B"},{"level":2,"title":"\u73AF\u5883\u95EE\u9898","slug":"\u73AF\u5883\u95EE\u9898"},{"level":2,"title":"\u4F9D\u8D56\u5B89\u88C5\u95EE\u9898","slug":"\u4F9D\u8D56\u5B89\u88C5\u95EE\u9898"},{"level":2,"title":"\u5982\u4F55\u4FDD\u8BC1\u6211\u7684\u4EE3\u7801\u80FD\u66F4\u65B0\u5230\u6700\u65B0\u4EE3\u7801","slug":"\u5982\u4F55\u4FDD\u8BC1\u6211\u7684\u4EE3\u7801\u80FD\u66F4\u65B0\u5230\u6700\u65B0\u4EE3\u7801"},{"level":2,"title":"\u6253\u5305\u6587\u4EF6\u8FC7\u5927","slug":"\u6253\u5305\u6587\u4EF6\u8FC7\u5927"},{"level":2,"title":"\u8FD0\u884C\u9519\u8BEF","slug":"\u8FD0\u884C\u9519\u8BEF"},{"level":2,"title":"\u4E3A\u4EC0\u4E48\u662F moment.js","slug":"\u4E3A\u4EC0\u4E48\u662F-moment-js"},{"level":2,"title":"\u63A7\u5236\u53F0\u8DEF\u7531\u8B66\u544A\u95EE\u9898","slug":"\u63A7\u5236\u53F0\u8DEF\u7531\u8B66\u544A\u95EE\u9898"},{"level":2,"title":"\u542F\u52A8\u62A5\u9519","slug":"\u542F\u52A8\u62A5\u9519"},{"level":2,"title":"\u9875\u9762\u62A5\u9519","slug":"\u9875\u9762\u62A5\u9519"},{"level":2,"title":"\u8DE8\u57DF\u95EE\u9898","slug":"\u8DE8\u57DF\u95EE\u9898"},{"level":2,"title":"\u63A5\u53E3\u8BF7\u6C42\u95EE\u9898","slug":"\u63A5\u53E3\u8BF7\u6C42\u95EE\u9898"},{"level":2,"title":"\u7EC4\u4EF6\u5E93\u95EE\u9898","slug":"\u7EC4\u4EF6\u5E93\u95EE\u9898"}],"relativePath":"other/faq.md","lastUpdated":1694442156385}',t={},p=e(`__VP_STATIC_START__

\u5E38\u89C1\u95EE\u9898

TIP

\u5217\u4E3E\u4E86\u4E00\u4E9B\u5E38\u89C1\u7684\u95EE\u9898\u3002\u6709\u95EE\u9898\u53EF\u4EE5\u5148\u6765\u8FD9\u91CC\u5BFB\u627E\uFF0C\u5982\u679C\u6CA1\u6709\u53EF\u4EE5\u5728 issue \u63D0\u3002

\u524D\u8A00

\u9047\u5230\u95EE\u9898,\u53EF\u4EE5\u5148\u4ECE\u4EE5\u4E0B\u51E0\u4E2A\u65B9\u9762\u67E5\u627E

  1. \u5BF9\u5E94\u6A21\u5757\u7684 GitHub \u4ED3\u5E93 issue \u641C\u7D22
  2. \u4ECEgoogle\u641C\u7D22\u95EE\u9898
  3. \u4ECE\u767E\u5EA6\u641C\u7D22\u95EE\u9898
  4. \u5728\u4E0B\u9762\u5217\u8868\u627E\u4E0D\u5230\u95EE\u9898\u53EF\u4EE5\u5230 issue \u63D0\u95EE issues
  5. \u5982\u679C\u4E0D\u662F\u95EE\u9898\u7C7B\u578B\u7684\uFF0C\u9700\u8981\u8BA8\u8BBA\u7684\uFF0C\u8BF7\u5230 discussions \u8BA8\u8BBA

\u5173\u4E8E\u7F13\u5B58\u66F4\u65B0\u95EE\u9898

vben-admin \u7684\u9879\u76EE\u914D\u7F6E\u9ED8\u8BA4\u662F\u7F13\u5B58\u5728 localStorage \u5185\uFF0C\u6240\u4EE5\u7248\u672C\u66F4\u65B0\u540E\u53EF\u80FD\u6709\u4E9B\u914D\u7F6E\u6CA1\u6539\u53D8\u3002

\u89E3\u51B3\u65B9\u5F0F\u662F\u6BCF\u6B21\u66F4\u65B0\u4EE3\u7801\u7684\u65F6\u5019\u4FEE\u6539 package.json \u5185\u7684 version \u7248\u672C\u53F7. \u56E0\u4E3A localStorage \u7684 key \u662F\u6839\u636E\u7248\u672C\u53F7\u6765\u7684\u3002\u6240\u4EE5\u66F4\u65B0\u540E\u7248\u672C\u4E0D\u540C\u524D\u9762\u7684\u914D\u7F6E\u4F1A\u5931\u6548\u3002\u91CD\u65B0\u767B\u5F55\u5373\u53EF

VUE_VBEN_ADMIN__DEVELOPMENT__2.0.3__COMMON__LOCAL__KEY__ key \u7684\u7EC4\u6210\u662F [\u9879\u76EE\u540D]+[\u5F00\u53D1\u73AF\u5883]+[\u7248\u672C\u53F7]+[key]

\u5173\u4E8E\u4FEE\u6539\u914D\u7F6E\u6587\u4EF6\u7684\u95EE\u9898

\u5F53\u4FEE\u6539 .env \u7B49\u73AF\u5883\u6587\u4EF6\u53CA vite.config.ts \u6587\u4EF6\u65F6\uFF0Cvite \u4F1A\u81EA\u52A8\u91CD\u542F\u670D\u52A1\u3002

\u81EA\u52A8\u91CD\u542F\u6709\u51E0\u7387\u51FA\u73B0\u95EE\u9898\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u9879\u76EE\u5373\u53EF\u89E3\u51B3.

esbuild \u6A21\u5F0F\u4E0B\u5F00\u542F LEGACY \u6253\u5305\u5931\u8D25

\u5982\u679C\u5C06 \b build.minify \u8BBE\u7F6E\u4E3A 'esbuild'\uFF0C\u4E14\u4E0D\u80FD\u542F\u7528 LEGACY\uFF0C\u5426\u5219\u6253\u5305\u5C06\u4F1A\u62A5\u9519\uFF0C\u4E24\u8005\u9009\u5176\u4E00\u5373\u53EF\u6253\u5305\u3002

ant-design-vue \u63A7\u5236\u53F0\u8B66\u544A

\u5728\u63A7\u5236\u53F0\u770B\u5230\u4EE5\u4E0B\u8B66\u544A\u7684\u539F\u56E0\u662F ant-design-vue \u4F1A\u68C0\u6D4B\u662F\u5426\u4F7F\u7528\u4E86 babel-plugin-import \u6765\u5224\u65AD\u662F\u5426\u8FDB\u884C\u4E86\u7EC4\u4EF6\u5E93\u7684\u6309\u9700\u5F15\u5165\u3002

\u4F46\u662F\u9879\u76EE\u4F7F\u7528\u7684\u662F vite \u7684\u63D2\u4EF6 vite-plugin-style-import \u6765\u8FDB\u884C\u6309\u9700\u5F15\u5165\u3002\u5728 vite \u5185\u6CA1\u5FC5\u8981\u4F7F\u7528 babel \u5728\u8F6C\u6362\u4E00\u6B21\u4EE3\u7801\u4E86\u3002

\u6240\u4EE5\u60F3\u5173\u95ED\u8FD9\u4E2A\u8B66\u544A\uFF0C\u5F97\u7B49 ant-design-vue \u63D0\u4F9B\u53EF\u4EE5\u5173\u95ED\u8BE5\u8B66\u544A\u7684\u914D\u7F6E\u3002

You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size. Not support Vite !!!
+

\u6DFB\u52A0\u83DC\u5355\u540E\u6CA1\u663E\u793A

\u83DC\u5355\u5FC5\u987B\u548C\u8DEF\u7531\u5339\u914D\u624D\u4F1A\u663E\u793A\u5728\u754C\u9762\u4E0A\uFF0C\u6240\u4EE5\u5F97\u786E\u4FDD\u83DC\u5355\u548C\u5BF9\u5E94\u7684\u8DEF\u7531\u5B58\u5728\u5373\u53EF\u663E\u793A.

imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25

\u7531\u4E8E imagemin \u5728\u56FD\u5185\u5B89\u88C5\u56F0\u96BE\uFF0C\u63D0\u4F9B\u4EE5\u4E0B\u51E0\u4E2A\u89E3\u51B3\u65B9\u6848\uFF1A

  1. \u4F7F\u7528 yarn \u5728 package.json \u5185\u914D\u7F6E\uFF08\u63A8\u8350\uFF0C\u9879\u76EE\u5185\u5DF2\u96C6\u6210\uFF0C\u524D\u63D0\u662F\u5FC5\u987B\u4F7F\u7528 yarn\uFF09
"resolutions": {
+  "bin-wrapper": "npm:bin-wrapper-china"
+}
+
  1. \u4F7F\u7528 npm,\u5728\u7535\u8111 host \u6587\u4EF6\u52A0\u4E0A\u5982\u4E0B\u914D\u7F6E\u5373\u53EF
199.232.4.133 raw.githubusercontent.com
+

\u4F7F\u7528 yarn \u5B89\u88C5 imagemin \u4F9D\u8D56\u5B89\u88C5\u5931\u8D25

\u5982\u679C\u4F7F\u7528 yarn \u8FD8\u662F\u4E0D\u80FD\u5B89\u88C5\u4F9D\u8D56\uFF0C\u53EF\u4EE5\u5C06\u56FE\u7247\u538B\u7F29\u529F\u80FD\u79FB\u9664\uFF0C\u79FB\u9664\u65B9\u6CD5\u5982\u4E0B\uFF1A

  • \u5728 package.json \u5185\u5220\u9664 vite-plugin-imagemin \u8FD9\u4E2A\u4F9D\u8D56\u3002\u8FD9\u4F1A\u5BFC\u81F4\u56FE\u7247\u6CA1\u6709\u538B\u7F29\uFF0C\u4F46\u662F\u53EF\u4EE5\u624B\u52A8\u5230\u5728\u7EBF\u7F51\u7AD9\u8FDB\u884C\u538B\u7F29\u3002\u8FD9\u91CC\u63A8\u8350tinypng
    1. \u6CE8\u91CA vite-plugin-imagemin \u63D2\u4EF6\u5F15\u7528
import { configImageminPlugin } from './imagemin';
+VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
+

\u5728 Linux \u5185\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25

\u5982\u679C\u6267\u884C yarn install \u4F1A\u51FA\u73B0\u4EE5\u4E0B\u9519\u8BEF\uFF1A

gifsicle pre-build test failed
+compiling from source
+

\u53EF\u80FD\u662F linux \u670D\u52A1\u5668\u9700\u8981\u914D\u7F6E\u4E0B\u73AF\u5883\uFF0Cimagemin \u8FD9\u4E2A\u4F1A\u5BFC\u81F4\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\u3002

\u8FD9\u91CC\u4EE5Centos\u4E3A\u4F8B

  • \u89E3\u51B3\u65B9\u5F0F 1:
  1. \u5C06\u4EE5\u4E0B\u5185\u5BB9\u6DFB\u52A0\u5230 yum \u6E90
[nasm]
+name=The Netwide Assembler
+baseurl=http://www.nasm.us/pub/nasm/stable/linux/
+enabled=1
+gpgcheck=0
+
+[nasm-testing]
+name=The Netwide Assembler (release candidate builds)
+baseurl=http://www.nasm.us/pub/nasm/testing/linux/
+enabled=0
+gpgcheck=0
+
+[nasm-snapshot]
+name=The Netwide Assembler (daily snapshot builds)
+baseurl=http://www.nasm.us/pub/nasm/snapshots/latest/linux/
+enabled=0
+gpgcheck=0
+

\u5728 /etc/yum.repos.d/ \u4E0B\u65B0\u5EFA Centos-Nasm.repo\uFF0C\u5C06\u4EE5\u4E0A\u5185\u5BB9\u590D\u5236\u5230\u8FD9\u4E2A\u6587\u4EF6\u5373\u53EF

  1. \u6267\u884C yum install libtool automake autoconf nasm
  2. \u91CD\u65B0\u6267\u884C yarn install \u5373\u53EF

\u672C\u5730\u8FD0\u884C\u62A5\u9519

\u7531\u4E8E vite \u5728\u672C\u5730\u6CA1\u6709\u8F6C\u6362\u4EE3\u7801\uFF0C\u4E14\u4EE3\u7801\u4E2D\u7528\u5230\u4E86\u53EF\u9009\u94FE\u7B49\u6BD4\u8F83\u65B0\u7684\u8BED\u6CD5\u3002\u6240\u4EE5\u672C\u5730\u5F00\u53D1\u9700\u8981\u4F7F\u7528\u7248\u672C\u8F83\u9AD8\u7684\u6D4F\u89C8\u5668(Chrome 85+)\u8FDB\u884C\u5F00\u53D1

tab \u9875\u5207\u6362\u540E\u9875\u9762\u7A7A\u767D

\u8FD9\u662F\u7531\u4E8E\u5F00\u542F\u4E86\u8DEF\u7531\u5207\u6362\u52A8\u753B,\u4E14\u5BF9\u5E94\u7684\u9875\u9762\u7EC4\u4EF6\u5B58\u5728\u591A\u4E2A\u6839\u8282\u70B9\u5BFC\u81F4\u7684\uFF0C\u5728\u9875\u9762\u6700\u5916\u5C42\u6DFB\u52A0<div></div>\u5373\u53EF

\u9519\u8BEF\u793A\u4F8B

<template>
+  <!-- \u6CE8\u91CA\u4E5F\u7B97\u4E00\u4E2A\u8282\u70B9 -->
+  <h1>text h1</h1>
+  <h2>text h2</h2>
+</template>
+

\u6B63\u786E\u793A\u4F8B

<template>
+  <div>
+    <h1>text h1</h1>
+    <h2>text h2</h2>
+  </div>
+</template>
+

\u63D0\u793A

  • \u5982\u679C\u60F3\u4F7F\u7528\u591A\u4E2A\u6839\u6807\u7B7E\uFF0C\u53EF\u4EE5\u7981\u7528\u8DEF\u7531\u5207\u6362\u52A8\u753B
  • template \u4E0B\u9762\u7684\u6839\u6CE8\u91CA\u8282\u70B9\u4E5F\u7B97\u4E00\u4E2A\u8282\u70B9

\u7EC4\u4EF6\u547D\u540D\u95EE\u9898

\u76EE\u524D\u5728 vite+vue3.0.5 \u7248\u672C\u4E2D\uFF0C\u5982\u679C\u7EC4\u4EF6\u547D\u540D\u643A\u5E26\u5173\u952E\u5B57\uFF0C\u5219\u53EF\u80FD\u4F1A\u5BFC\u81F4\u5185\u5B58\u6EA2\u51FA\u3002\u4F8B\u5982 ImportExcel excel \u5BFC\u5165\u7EC4\u4EF6\u3002

\u6211\u7684\u4EE3\u7801\u672C\u5730\u5F00\u53D1\u53EF\u4EE5\uFF0C\u6253\u5305\u5C31\u4E0D\u884C\u4E86

\u76EE\u524D\u53D1\u73B0\u8FD9\u4E2A\u539F\u56E0\u53EF\u80FD\u6709\u4EE5\u4E0B\uFF0C\u53EF\u4EE5\u4ECE\u4EE5\u4E0B\u539F\u56E0\u6765\u6392\u67E5\uFF0C\u5982\u679C\u8FD8\u6709\u522B\u7684\u53EF\u80FD\uFF0C\u53EF\u4EE5\u63D0\u4EA4 pr \u6765\u544A\u8BC9\u6211

  1. \u4F7F\u7528\u4E86 ctx \u8FD9\u4E2A\u53D8\u91CF\uFF0Cctx \u672C\u8EAB\u672A\u66B4\u9732\u51FA\u5728\u5B9E\u4F8B\u7C7B\u578B\u5185\uFF0C\u5C24\u5927\u4E5F\u662F\u8BF4\u4E86\u4E0D\u8981\u7528\u8FD9\u4E2A\u5C5E\u6027\u3002\u8FD9\u4E2A\u5C5E\u6027\u53EA\u662F\u7528\u4E8E\u5185\u90E8\u4F7F\u7528\u3002
import { getCurrentInstance } from 'vue';
+getCurrentInstance().ctx.xxxx;
+

safari \u95EE\u9898

\u76EE\u524D\u5728 safari \u4E0A\u9762\u672C\u5730\u5F00\u53D1\u8FD0\u884C\u6837\u5F0F\u4F1A\u6709\u95EE\u9898\uFF0C\u8FD8\u672A\u627E\u5230\u539F\u56E0\uFF0C\u6709\u77E5\u9053\u7684\u4E5F\u53EF\u4EE5\u544A\u8BC9\u6211\u3002

\u6A21\u7248\u533A\u522B

  • Vue-Vben-Admin - \u662F\u5305\u542B Demo \u793A\u4F8B\u7684,\u4E2A\u4EBA\u5EFA\u8BAE\u4E0D\u8981\u5728\u8FD9\u4E0A\u9762\u8FDB\u884C\u5F00\u53D1\u3002\u5F53\u7136\uFF0C\u4F60\u5982\u679C\u52A8\u624B\u80FD\u529B\u5F3A\u7684\u8BDD\u53EF\u4EE5\u76F4\u63A5\u6539\u3002
  • Vue-Vben-Admin-Thin-Next \u7CBE\u7B80\u4E86\u4EE3\u7801\u540E\u7684\u6A21\u7248\u9879\u76EE\u3002\u9002\u5408\u5728\u8FD9\u57FA\u7840\u4E0A\u8FDB\u884C\u4E8C\u6B21\u5F00\u53D1\u3002

\u73AF\u5883\u95EE\u9898

\u5982\u679C\u51FA\u73B0\u4F9D\u8D56\u5B89\u88C5\u62A5\u9519\uFF0C\u542F\u52A8\u62A5\u9519\u7B49\u3002\u5148\u68C0\u67E5\u7535\u8111\u73AF\u5883\u6709\u6CA1\u6709\u5B89\u88C5\u9F50\u5168\u3002

  • Node \u7248\u672C\u5FC5\u987B\u5927\u4E8E12.0.0\u4E0D\u652F\u6301 13\uFF0C \u63A8\u8350 14 \u7248\u672C\u3002
  • Git
  • Yarn \u6700\u65B0\u7248

\u4F9D\u8D56\u5B89\u88C5\u95EE\u9898

  • \u5982\u679C\u4F9D\u8D56\u5B89\u88C5\u4E0D\u4E86\u6216\u8005\u542F\u52A8\u62A5\u9519\u53EF\u4EE5\u5148\u5C1D\u8BD5 \u5220\u9664 yarn.lock \u548C node_modules\uFF0C\u7136\u540E\u91CD\u65B0\u8FD0\u884C yarn install
  • \u5982\u679C\u4F9D\u8D56\u5B89\u88C5\u4E0D\u4E86\u6216\u8005\u62A5\u9519\uFF0C\u53EF\u4EE5\u5C1D\u8BD5\u5207\u6362\u624B\u673A\u70ED\u70B9\u6765\u8FDB\u884C\u4F9D\u8D56\u5B89\u88C5\u3002
  • \u5982\u679C\u8FD8\u662F\u4E0D\u884C\uFF0C\u53EF\u4EE5\u81EA\u884C\u914D\u7F6E\u56FD\u5185\u955C\u50CF\u5B89\u88C5\u3002
  • \u4E5F\u53EF\u4EE5\u5728\u9879\u76EE\u6839\u76EE\u5F55\u521B\u5EFA .npmrc \u6587\u4EF6\uFF0C\u5185\u5BB9\u5982\u4E0B
# .npmrc
+registry = https://registry.npm.taobao.org
+

\u7136\u540E\u91CD\u65B0\u6267\u884Cyarn run reinstall\u7B49\u5F85\u5B89\u88C5\u5B8C\u6210\u5373\u53EF

\u5982\u4F55\u4FDD\u8BC1\u6211\u7684\u4EE3\u7801\u80FD\u66F4\u65B0\u5230\u6700\u65B0\u4EE3\u7801

\u5982\u679C\u4F60\u4F7F\u7528\u4E86\u8BE5\u9879\u76EE\u8FDB\u884C\u9879\u76EE\u5F00\u53D1\u3002\u5F00\u53D1\u4E4B\u4E2D\u60F3\u540C\u6B65\u6700\u65B0\u7684\u4EE3\u7801\u3002\u4F60\u53EF\u4EE5\u8BBE\u7F6E\u591A\u4E2A\u6E90\u7684\u65B9\u5F0F

  1. \u514B\u9686\u4EE3\u7801
git clone https://github.com/vbenjs/vben-admin-thin-next.git
+
  1. \u6DFB\u52A0\u81EA\u5DF1\u7684\u516C\u53F8 git \u6E90\u5730\u5740
# up \u4E3A\u6E90\u540D\u79F0,\u53EF\u4EE5\u968F\u610F\u8BBE\u7F6E
+# gitUrl\u4E3A\u5F00\u6E90\u6700\u65B0\u4EE3\u7801
+git remote add up gitUrl;
+
  1. \u63D0\u4EA4\u4EE3\u7801\u5230\u81EA\u5DF1\u516C\u53F8 git
# \u63D0\u4EA4\u4EE3\u7801\u5230\u81EA\u5DF1\u516C\u53F8
+# main\u4E3A\u5206\u652F\u540D \u9700\u8981\u81EA\u884C\u6839\u636E\u60C5\u51B5\u4FEE\u6539
+git push up main
+
+# \u540C\u6B65\u516C\u53F8\u7684\u4EE3\u7801
+# main\u4E3A\u5206\u652F\u540D \u9700\u8981\u81EA\u884C\u6839\u636E\u60C5\u51B5\u4FEE\u6539
+git pull up main
+
  1. \u5982\u4F55\u540C\u6B65\u5F00\u6E90\u6700\u65B0\u4EE3\u7801
git pull origin main
+

TIP

\u540C\u6B65\u4EE3\u7801\u7684\u65F6\u5019\u4F1A\u51FA\u73B0\u51B2\u7A81\u3002\u53EA\u9700\u8981\u628A\u51B2\u7A81\u89E3\u51B3\u5373\u53EF

\u6253\u5305\u6587\u4EF6\u8FC7\u5927

  • \u9996\u5148\uFF0C\u5B8C\u6574\u7248\u7531\u4E8E\u5F15\u7528\u4E86\u6BD4\u8F83\u591A\u7684\u5E93\u6587\u4EF6\uFF0C\u6240\u4EE5\u6253\u5305\u4F1A\u6BD4\u8F83\u5927\u3002\u53EF\u4EE5\u4F7F\u7528\u7CBE\u7B80\u7248\u6765\u8FDB\u884C\u5F00\u53D1

  • \u5176\u6B21\u5EFA\u8BAE\u5F00\u542F gzip\uFF0C\u4F7F\u7528\u4E4B\u540E\u4F53\u79EF\u4F1A\u53EA\u6709\u539F\u5148 1/3 \u5DE6\u53F3\u3002

gzip \u53EF\u4EE5\u7531\u670D\u52A1\u5668\u76F4\u63A5\u5F00\u542F\u3002\u5982\u679C\u662F\u8FD9\u6837\uFF0C\u524D\u7AEF\u4E0D\u9700\u8981\u6784\u5EFA .gz \u683C\u5F0F\u7684\u6587\u4EF6

\u5982\u679C\u524D\u7AEF\u6784\u5EFA\u4E86 .gz \u6587\u4EF6\uFF0C\u4EE5 nginx \u4E3A\u4F8B\uFF0Cnginx \u9700\u8981\u5F00\u542F gzip_static: on \u8FD9\u4E2A\u9009\u9879\u3002

  • \u5F00\u542F gzip \u7684\u540C\u65F6\u8FD8\u53EF\u4EE5\u540C\u65F6\u5F00\u542F brotli\uFF0C\u6BD4 gzip \u66F4\u597D\u7684\u538B\u7F29\u3002\u4E24\u8005\u53EF\u4EE5\u5171\u5B58

\u6CE8\u610F

  • gzip_static: \u8FD9\u4E2A\u6A21\u5757\u9700\u8981 nginx \u53E6\u5916\u5B89\u88C5\uFF0C\u9ED8\u8BA4\u7684 nginx \u6CA1\u6709\u5B89\u88C5\u8FD9\u4E2A\u6A21\u5757\u3002

  • \u5F00\u542F brotli \u4E5F\u9700\u8981 nginx \u53E6\u5916\u5B89\u88C5\u6A21\u5757

\u8FD0\u884C\u9519\u8BEF

\u5982\u679C\u51FA\u73B0\u7C7B\u4F3C\u4EE5\u4E0B\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u9879\u76EE\u5168\u8DEF\u5F84\uFF08\u5305\u542B\u6240\u6709\u7236\u7EA7\u8DEF\u5F84\uFF09\u4E0D\u80FD\u51FA\u73B0\u4E2D\u6587\u3001\u65E5\u6587\u3001\u97E9\u6587\u3002\u5426\u5219\u5C06\u4F1A\u51FA\u73B0\u8DEF\u5F84\u8BBF\u95EE 404 \u5BFC\u81F4\u4EE5\u4E0B\u95EE\u9898

[vite] Failed to resolve module import "ant-design-vue/dist/antd.css-vben-adminode_modulesant-design-vuedistantd.css". (imported by /@/setup/ant-design-vue/index.ts)
+

\u4E3A\u4EC0\u4E48\u662F moment.js

\u5F88\u591A\u4EBA\u95EE\u4E3A\u4EC0\u4E48\u4E0D\u7528dayjs\u3002\u5728\u9879\u76EE\u4F9D\u8D56\u4E2D\u53EF\u4EE5\u770B\u5230\uFF0C\u5B83\u662F Ant-Design-Vue \u5185\u90E8\u81EA\u5E26\u7684\u3002

\u76EE\u524D\u8FD8\u6CA1\u6709\u57FA\u4E8E Vite \u7684 dayjs \u66FF\u6362 momentjs \u65B9\u6848\uFF0Cwebpack \u5DF2\u7ECF\u6709\u4E86\u3002\u7B49\u4EE5\u540E\u51FA\u73B0\u4E86\u5728\u8FDB\u884C\u66FF\u6362\u3002

\u63A7\u5236\u53F0\u8DEF\u7531\u8B66\u544A\u95EE\u9898

\u5982\u679C\u770B\u5230\u63A7\u5236\u53F0\u6709\u5982\u4E0B\u8B66\u544A\uFF0C\u4E14\u9875\u9762\u80FD\u6B63\u5E38\u6253\u5F00 \u53EF\u4EE5\u5FFD\u7565\u8BE5\u8B66\u544A\u3002

\u540E\u7EED vue-router \u53EF\u80FD\u4F1A\u63D0\u4F9B\u914D\u7F6E\u9879\u6765\u5173\u95ED\u8B66\u544A

2.6.1\u53CA\u4EE5\u4E0A\u7248\u672C\u5DF2\u79FB\u9664\u6B64\u8B66\u544A

[Vue Router warn]: No match found for location with path "xxxx"
+

\u542F\u52A8\u62A5\u9519

\u5F53\u51FA\u73B0\u4EE5\u4E0B\u9519\u8BEF\u4FE1\u606F\u65F6\uFF0C\u8BF7\u68C0\u67E5\u4F60\u7684 nodejs \u7248\u672C\u53F7\u662F\u5426\u7B26\u5408\u8981\u6C42

TypeError: str.matchAll is not a function
+at Object.extractor (vue-vben-admin-main\\node_modules@purge-icons\\core\\dist\\index.js:146:27)
+at Extract (vue-vben-admin-main\\node_modules@purge-icons\\core\\dist\\index.js:173:54)
+
+

\u9875\u9762\u62A5\u9519

\u5F53\u9875\u9762\u51FA\u73B0\u4EE5\u4E0B\u62A5\u9519\uFF0C\u662F\u56E0\u4E3A /xxx \u5BF9\u5E94\u7684\u8DEF\u7531\u7EC4\u4EF6\u5185\u90E8\u51FA\u73B0\u4E86\u9519\u8BEF\u3002

 Uncaught (in promise) Error: Couldn't resolve component "default" at "/xxx"
+
+

\u53EF\u4EE5\u5C1D\u8BD5\u4ECE\u4EE5\u4E0B\u51E0\u70B9\u6392\u67E5

  1. \u68C0\u67E5\u5BF9\u5E94\u7EC4\u4EF6\u5185\u90E8 import \u7684\u6240\u6709\u6587\u4EF6\u662F\u5426\u6B63\u786E
  2. \u68C0\u67E5\u5F15\u5165\u65B9\u5F0F\u662F\u5426\u9519\u8BEF\u3002
// \u6B63\u786E\u7684
+import { cloneDeep } from 'lodash-es';
+
+// \u62A5\u9519
+import _ from 'lodash-es';
+
  1. \u68C0\u67E5\u6837\u5F0F\u662F\u5426\u4F7F\u7528\u53D8\u91CF\u53CA\u6709\u6CA1\u6709\u5F15\u5165\u5BF9\u5E94\u7684\u53D8\u91CF\u6587\u4EF6
  2. \u68C0\u67E5\u4EE3\u7801\u660E\u663E\u7684\u8BED\u6CD5\u9519\u8BEF

\u8FD9\u6837\u5C31\u4E0D\u4F1A\u662F\u4F7F\u7528\u7684\u53D6\u503C\u5FD8\u8BB0 xxx.value \u6765\u8FDB\u884C\u6570\u636E\u83B7\u53D6

\u8DE8\u57DF\u95EE\u9898

\u53C2\u8003\u8DE8\u57DF\u95EE\u9898

\u63A5\u53E3\u8BF7\u6C42\u95EE\u9898

proxy \u4EE3\u7406\u4E0D\u6210\u529F\uFF0C\u6CA1\u6709\u4EE3\u7406\u5230\u5B9E\u9645\u5730\u5740\uFF1F

\u4EE3\u7406\u53EA\u662F\u670D\u52A1\u8BF7\u6C42\u4EE3\u7406\uFF0C\u8FD9\u4E2A\u5730\u5740\u662F\u4E0D\u4F1A\u53D8\u7684\u3002 \u539F\u7406\u53EF\u4EE5\u7B80\u5355\u7684\u7406\u89E3\u4E3A\uFF0C\u5728\u672C\u5730\u542F\u4E86\u4E00\u4E2A\u670D\u52A1\uFF0C\u4F60\u5148\u8BF7\u6C42\u4E86\u672C\u5730\u7684\u670D\u52A1\uFF0C\u672C\u5730\u7684\u670D\u52A1\u8F6C\u53D1\u4E86\u4F60\u7684\u8BF7\u6C42\u5230\u5B9E\u9645\u670D\u52A1\u5668\u3002\u6240\u4EE5\u4F60\u5728\u6D4F\u89C8\u5668\u4E0A\u770B\u5230\u7684\u8BF7\u6C42\u5730\u5740\u8FD8\u662F http://localhost:8000/xxx\u3002\u4EE5\u670D\u52A1\u7AEF\u662F\u5426\u6536\u5230\u8BF7\u6C42\u4E3A\u51C6\u3002

\u7EC4\u4EF6\u5E93\u95EE\u9898

\u8DDF\u7EC4\u4EF6\u5E93\u76F8\u5173\u7684\u95EE\u9898\u53EF\u4EE5\u67E5\u770B\u5E38\u89C1\u95EE\u9898

__VP_STATIC_END__`,114),o=[p];function l(c,i,r,u,d,h){return s(),n("div",null,o)}var m=a(t,[["render",l]]);export{k as __pageData,m as default}; diff --git a/assets/other_project.md.bb916282.js b/assets/other_project.md.bb916282.js new file mode 100644 index 00000000..8c1c8254 --- /dev/null +++ b/assets/other_project.md.bb916282.js @@ -0,0 +1 @@ +import{_ as e,f as t,e as r,N as o}from"./plugin-vue_export-helper.147b70e9.js";const u='{"title":"\u76F8\u5173\u9879\u76EE","description":"","frontmatter":{},"headers":[{"level":2,"title":"golang","slug":"golang"},{"level":2,"title":"php","slug":"php"},{"level":2,"title":"java","slug":"java"},{"level":2,"title":".net","slug":"net"}],"relativePath":"other/project.md","lastUpdated":1694442156385}',n={},a=o('

\u76F8\u5173\u9879\u76EE

\u5BF9\u63A5vben\u7684\u9879\u76EE\u5730\u5740\uFF0C\u975E\u5B98\u65B9\u9879\u76EE\uFF0Cvben\u7528\u6237\u5F00\u6E90\uFF0C\u5F00\u6E90\u534F\u8BAE\u8BF7\u81EA\u884C\u67E5\u770B

golang

  1. \u540E\u7AEF\uFF1Ahttps://github.com/vbenjs/gf-vben \u524D\u7AEF\uFF1Ahttps://github.com/vbenjs/gf-vben-admin

php

  1. \u540E\u7AEF\uFF1Ahttps://github.com/Joyboo/Joyboo-admin-easyswoole \u524D\u7AEF\uFF1Ahttps://github.com/Joyboo/Joyboo-vben-admin-thin
  2. \u540E\u7AEF: https://github.com/wcz0/laravel-vben \u524D\u7AEF: https://github.com/wcz0/laravel-vben-admin

java

  1. \u540E\u7AEFSpringCloud\uFF1Ahttps://github.com/zuihou/lamp-cloud \u540E\u7AEFSpringBoot\uFF1Ahttps://github.com/zuihou/lamp-boot \u524D\u7AEF\uFF1Ahttps://github.com/zuihou/lamp-web-plus
  2. \u540E\u7AEF\uFF1Ahttps://gitee.com/skysong/coffee-boot
  3. \u540E\u7AEF\uFF1Ahttps://gitee.com/battcn/wemirr-platform \u524D\u7AEF\uFF1Ahttps://gitee.com/battcn/wemirr-platform-ui
  4. \u540E\u7AEF\uFF1Ahttps://gitee.com/zsvg/vboot-java \u524D\u7AEF\uFF1Ahttps://gitee.com/zsvg/vboot-vben
  5. \u540E\u7AEFSpringBoot\uFF1Ahttps://github.com/uncarbon97/helio-boot \u540E\u7AEFSpringCloud\uFF1Ahttps://github.com/uncarbon97/helio-cloud \u524D\u7AEF\uFF1Ahttps://github.com/uncarbon97/helio-admin-vue-vben

.net

  1. \u5BF9\u63A5Osharp \u524D\u7AEF\uFF1Ahttps://github.com/zionLZH/osharp-vben-admin
  2. \u540E\u7AEF\uFF1Ahttps://gitee.com/zsvg/vboot-net \u524D\u7AEF\uFF1Ahttps://gitee.com/zsvg/vboot-vben
  3. Admin.NET \u6E90\u7801\u5730\u5740\uFF1Ahttps://gitee.com/zuohuaijun/Admin.NET
',10),h=[a];function l(s,g,i,p,b,c){return r(),t("div",null,h)}var f=e(n,[["render",l]]);export{u as __pageData,f as default}; diff --git a/assets/other_project.md.bb916282.lean.js b/assets/other_project.md.bb916282.lean.js new file mode 100644 index 00000000..9c07f96b --- /dev/null +++ b/assets/other_project.md.bb916282.lean.js @@ -0,0 +1 @@ +import{_ as e,f as t,e as r,N as o}from"./plugin-vue_export-helper.147b70e9.js";const u='{"title":"\u76F8\u5173\u9879\u76EE","description":"","frontmatter":{},"headers":[{"level":2,"title":"golang","slug":"golang"},{"level":2,"title":"php","slug":"php"},{"level":2,"title":"java","slug":"java"},{"level":2,"title":".net","slug":"net"}],"relativePath":"other/project.md","lastUpdated":1694442156385}',n={},a=o('',10),h=[a];function l(s,g,i,p,b,c){return r(),t("div",null,h)}var f=e(n,[["render",l]]);export{u as __pageData,f as default}; diff --git a/assets/other_server.md.5e6ad55f.js b/assets/other_server.md.5e6ad55f.js new file mode 100644 index 00000000..565065b4 --- /dev/null +++ b/assets/other_server.md.5e6ad55f.js @@ -0,0 +1,10 @@ +import{_ as e,f as a,e as s,N as n}from"./plugin-vue_export-helper.147b70e9.js";const u='{"title":"\u6D4B\u8BD5\u670D\u52A1\u5668","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"}],"relativePath":"other/server.md","lastUpdated":1694442156385}',t={},r=n(`

\u6D4B\u8BD5\u670D\u52A1\u5668

\u5728\u9879\u76EE /test/server \u5185\u6709\u7B80\u5355\u7684 Node.js \u6D4B\u8BD5\u540E\u53F0\u63A5\u53E3\u670D\u52A1\uFF0C\u7528 Koa2 \u5B9E\u73B0

\u4F7F\u7528


+cd ./test/server
+
+# \u5B89\u88C5\u4F9D\u8D56
+yarn
+
+# \u8FD0\u884C\u670D\u52A1
+yarn start
+
+

\u670D\u52A1\u8FD0\u884C\u6210\u529F\u4E4B\u540E\uFF0C\u5C31\u53EF\u4EE5\u8BBF\u95EE\u6D4B\u8BD5\u4E0A\u4F20\u63A5\u53E3\u53CA websocket \u63A5\u53E3\u670D\u52A1

`,5),o=[r];function c(d,p,_,i,l,h){return s(),a("div",null,o)}var m=e(t,[["render",c]]);export{u as __pageData,m as default}; diff --git a/assets/other_server.md.5e6ad55f.lean.js b/assets/other_server.md.5e6ad55f.lean.js new file mode 100644 index 00000000..2c78799d --- /dev/null +++ b/assets/other_server.md.5e6ad55f.lean.js @@ -0,0 +1,10 @@ +import{_ as e,f as a,e as s,N as n}from"./plugin-vue_export-helper.147b70e9.js";const u='{"title":"\u6D4B\u8BD5\u670D\u52A1\u5668","description":"","frontmatter":{},"headers":[{"level":2,"title":"\u4F7F\u7528","slug":"\u4F7F\u7528"}],"relativePath":"other/server.md","lastUpdated":1694442156385}',t={},r=n(`__VP_STATIC_START__

\u6D4B\u8BD5\u670D\u52A1\u5668

\u5728\u9879\u76EE /test/server \u5185\u6709\u7B80\u5355\u7684 Node.js \u6D4B\u8BD5\u540E\u53F0\u63A5\u53E3\u670D\u52A1\uFF0C\u7528 Koa2 \u5B9E\u73B0

\u4F7F\u7528


+cd ./test/server
+
+# \u5B89\u88C5\u4F9D\u8D56
+yarn
+
+# \u8FD0\u884C\u670D\u52A1
+yarn start
+
+

\u670D\u52A1\u8FD0\u884C\u6210\u529F\u4E4B\u540E\uFF0C\u5C31\u53EF\u4EE5\u8BBF\u95EE\u6D4B\u8BD5\u4E0A\u4F20\u63A5\u53E3\u53CA websocket \u63A5\u53E3\u670D\u52A1

__VP_STATIC_END__`,5),o=[r];function c(d,p,_,i,l,h){return s(),a("div",null,o)}var m=e(t,[["render",c]]);export{u as __pageData,m as default}; diff --git a/assets/plugin-vue_export-helper.147b70e9.js b/assets/plugin-vue_export-helper.147b70e9.js new file mode 100644 index 00000000..821017ff --- /dev/null +++ b/assets/plugin-vue_export-helper.147b70e9.js @@ -0,0 +1 @@ +function In(e,t){const n=Object.create(null),s=e.split(",");for(let r=0;r!!n[r.toLowerCase()]:r=>!!n[r]}const Rr="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",Sr=In(Rr);function Ps(e){return!!e||e===""}function vn(e){if(R(e)){const t={};for(let n=0;n{if(n){const s=n.split(Hr);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function Nn(e){let t="";if(ie(e))t=e;else if(R(e))for(let n=0;nie(e)?e:e==null?"":R(e)||se(e)&&(e.toString===Rs||!L(e.toString))?JSON.stringify(e,Is,2):String(e),Is=(e,t)=>t&&t.__v_isRef?Is(e,t.value):nt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r])=>(n[`${s} =>`]=r,n),{})}:vs(t)?{[`Set(${t.size})`]:[...t.values()]}:se(t)&&!R(t)&&!Ss(t)?String(t):t,z={},tt=[],Ee=()=>{},jr=()=>!1,Ur=/^on[^a-z]/,At=e=>Ur.test(e),Rn=e=>e.startsWith("onUpdate:"),oe=Object.assign,Sn=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},$r=Object.prototype.hasOwnProperty,$=(e,t)=>$r.call(e,t),R=Array.isArray,nt=e=>qt(e)==="[object Map]",vs=e=>qt(e)==="[object Set]",L=e=>typeof e=="function",ie=e=>typeof e=="string",Ln=e=>typeof e=="symbol",se=e=>e!==null&&typeof e=="object",Ns=e=>se(e)&&L(e.then)&&L(e.catch),Rs=Object.prototype.toString,qt=e=>Rs.call(e),Dr=e=>qt(e).slice(8,-1),Ss=e=>qt(e)==="[object Object]",Hn=e=>ie(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,pt=In(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Vt=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Kr=/-(\w)/g,Me=Vt(e=>e.replace(Kr,(t,n)=>n?n.toUpperCase():"")),kr=/\B([A-Z])/g,lt=Vt(e=>e.replace(kr,"-$1").toLowerCase()),Jt=Vt(e=>e.charAt(0).toUpperCase()+e.slice(1)),rn=Vt(e=>e?`on${Jt(e)}`:""),yt=(e,t)=>!Object.is(e,t),ln=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},Wr=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let ns;const qr=()=>ns||(ns=typeof globalThis!="undefined"?globalThis:typeof self!="undefined"?self:typeof window!="undefined"?window:typeof global!="undefined"?global:{});let Ae;class Vr{constructor(t=!1){this.active=!0,this.effects=[],this.cleanups=[],!t&&Ae&&(this.parent=Ae,this.index=(Ae.scopes||(Ae.scopes=[])).push(this)-1)}run(t){if(this.active){const n=Ae;try{return Ae=this,t()}finally{Ae=n}}}on(){Ae=this}off(){Ae=this.parent}stop(t){if(this.active){let n,s;for(n=0,s=this.effects.length;n{const t=new Set(e);return t.w=0,t.n=0,t},Ls=e=>(e.w&$e)>0,Hs=e=>(e.n&$e)>0,zr=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let s=0;s{(a==="length"||a>=s)&&f.push(u)});else switch(n!==void 0&&f.push(l.get(n)),t){case"add":R(e)?Hn(n)&&f.push(l.get("length")):(f.push(l.get(Ve)),nt(e)&&f.push(l.get(bn)));break;case"delete":R(e)||(f.push(l.get(Ve)),nt(e)&&f.push(l.get(bn)));break;case"set":nt(e)&&f.push(l.get(Ve));break}if(f.length===1)f[0]&&yn(f[0]);else{const u=[];for(const a of f)a&&u.push(...a);yn(Bn(u))}}function yn(e,t){for(const n of R(e)?e:[...e])(n!==we||n.allowRecurse)&&(n.scheduler?n.scheduler():n.run())}const Xr=In("__proto__,__v_isRef,__isVue"),Us=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(Ln)),Zr=Un(),Qr=Un(!1,!0),Gr=Un(!0),rs=ei();function ei(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const s=W(this);for(let i=0,l=this.length;i{e[t]=function(...n){ot();const s=W(this)[t].apply(this,n);return ft(),s}}),e}function Un(e=!1,t=!1){return function(s,r,i){if(r==="__v_isReactive")return!e;if(r==="__v_isReadonly")return e;if(r==="__v_isShallow")return t;if(r==="__v_raw"&&i===(e?t?mi:Ws:t?ks:Ks).get(s))return s;const l=R(s);if(!e&&l&&$(rs,r))return Reflect.get(rs,r,i);const f=Reflect.get(s,r,i);return(Ln(r)?Us.has(r):Xr(r))||(e||me(s,"get",r),t)?f:re(f)?!l||!Hn(r)?f.value:f:se(f)?e?qs(f):Kn(f):f}}const ti=$s(),ni=$s(!0);function $s(e=!1){return function(n,s,r,i){let l=n[s];if(xt(l)&&re(l)&&!re(r))return!1;if(!e&&!xt(r)&&(Vs(r)||(r=W(r),l=W(l)),!R(n)&&re(l)&&!re(r)))return l.value=r,!0;const f=R(n)&&Hn(s)?Number(s)e,zt=e=>Reflect.getPrototypeOf(e);function Pt(e,t,n=!1,s=!1){e=e.__v_raw;const r=W(e),i=W(t);t!==i&&!n&&me(r,"get",t),!n&&me(r,"get",i);const{has:l}=zt(r),f=s?$n:n?Wn:Ct;if(l.call(r,t))return f(e.get(t));if(l.call(r,i))return f(e.get(i));e!==r&&e.get(t)}function It(e,t=!1){const n=this.__v_raw,s=W(n),r=W(e);return e!==r&&!t&&me(s,"has",e),!t&&me(s,"has",r),e===r?n.has(e):n.has(e)||n.has(r)}function vt(e,t=!1){return e=e.__v_raw,!t&&me(W(e),"iterate",Ve),Reflect.get(e,"size",e)}function is(e){e=W(e);const t=W(this);return zt(t).has.call(t,e)||(t.add(e),ve(t,"add",e,e)),this}function ls(e,t){t=W(t);const n=W(this),{has:s,get:r}=zt(n);let i=s.call(n,e);i||(e=W(e),i=s.call(n,e));const l=r.call(n,e);return n.set(e,t),i?yt(t,l)&&ve(n,"set",e,t):ve(n,"add",e,t),this}function os(e){const t=W(this),{has:n,get:s}=zt(t);let r=n.call(t,e);r||(e=W(e),r=n.call(t,e)),s&&s.call(t,e);const i=t.delete(e);return r&&ve(t,"delete",e,void 0),i}function fs(){const e=W(this),t=e.size!==0,n=e.clear();return t&&ve(e,"clear",void 0,void 0),n}function Nt(e,t){return function(s,r){const i=this,l=i.__v_raw,f=W(l),u=t?$n:e?Wn:Ct;return!e&&me(f,"iterate",Ve),l.forEach((a,m)=>s.call(r,u(a),u(m),i))}}function Rt(e,t,n){return function(...s){const r=this.__v_raw,i=W(r),l=nt(i),f=e==="entries"||e===Symbol.iterator&&l,u=e==="keys"&&l,a=r[e](...s),m=n?$n:t?Wn:Ct;return!t&&me(i,"iterate",u?bn:Ve),{next(){const{value:E,done:w}=a.next();return w?{value:E,done:w}:{value:f?[m(E[0]),m(E[1])]:m(E),done:w}},[Symbol.iterator](){return this}}}}function Se(e){return function(...t){return e==="delete"?!1:this}}function fi(){const e={get(i){return Pt(this,i)},get size(){return vt(this)},has:It,add:is,set:ls,delete:os,clear:fs,forEach:Nt(!1,!1)},t={get(i){return Pt(this,i,!1,!0)},get size(){return vt(this)},has:It,add:is,set:ls,delete:os,clear:fs,forEach:Nt(!1,!0)},n={get(i){return Pt(this,i,!0)},get size(){return vt(this,!0)},has(i){return It.call(this,i,!0)},add:Se("add"),set:Se("set"),delete:Se("delete"),clear:Se("clear"),forEach:Nt(!0,!1)},s={get(i){return Pt(this,i,!0,!0)},get size(){return vt(this,!0)},has(i){return It.call(this,i,!0)},add:Se("add"),set:Se("set"),delete:Se("delete"),clear:Se("clear"),forEach:Nt(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(i=>{e[i]=Rt(i,!1,!1),n[i]=Rt(i,!0,!1),t[i]=Rt(i,!1,!0),s[i]=Rt(i,!0,!0)}),[e,n,t,s]}const[ci,ui,ai,di]=fi();function Dn(e,t){const n=t?e?di:ai:e?ui:ci;return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get($(n,r)&&r in s?n:s,r,i)}const hi={get:Dn(!1,!1)},pi={get:Dn(!1,!0)},gi={get:Dn(!0,!1)},Ks=new WeakMap,ks=new WeakMap,Ws=new WeakMap,mi=new WeakMap;function _i(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function bi(e){return e.__v_skip||!Object.isExtensible(e)?0:_i(Dr(e))}function Kn(e){return xt(e)?e:kn(e,!1,Ds,hi,Ks)}function yi(e){return kn(e,!1,oi,pi,ks)}function qs(e){return kn(e,!0,li,gi,Ws)}function kn(e,t,n,s,r){if(!se(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=r.get(e);if(i)return i;const l=bi(e);if(l===0)return e;const f=new Proxy(e,l===2?s:n);return r.set(e,f),f}function st(e){return xt(e)?st(e.__v_raw):!!(e&&e.__v_isReactive)}function xt(e){return!!(e&&e.__v_isReadonly)}function Vs(e){return!!(e&&e.__v_isShallow)}function Js(e){return st(e)||xt(e)}function W(e){const t=e&&e.__v_raw;return t?W(t):e}function zs(e){return Ht(e,"__v_skip",!0),e}const Ct=e=>se(e)?Kn(e):e,Wn=e=>se(e)?qs(e):e;function Ys(e){je&&we&&(e=W(e),js(e.dep||(e.dep=Bn())))}function Xs(e,t){e=W(e),e.dep&&yn(e.dep)}function re(e){return!!(e&&e.__v_isRef===!0)}function on(e){return xi(e,!1)}function xi(e,t){return re(e)?e:new Ci(e,t)}class Ci{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:W(t),this._value=n?t:Ct(t)}get value(){return Ys(this),this._value}set value(t){t=this.__v_isShallow?t:W(t),yt(t,this._rawValue)&&(this._rawValue=t,this._value=this.__v_isShallow?t:Ct(t),Xs(this))}}function wi(e){return re(e)?e.value:e}const Ei={get:(e,t,n)=>wi(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return re(r)&&!re(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function Zs(e){return st(e)?e:new Proxy(e,Ei)}function co(e){const t=R(e)?new Array(e.length):{};for(const n in e)t[n]=Ai(e,n);return t}class Ti{constructor(t,n,s){this._object=t,this._key=n,this._defaultValue=s,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}}function Ai(e,t,n){const s=e[t];return re(s)?s:new Ti(e,t,n)}class Fi{constructor(t,n,s,r){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this._dirty=!0,this.effect=new jn(t,()=>{this._dirty||(this._dirty=!0,Xs(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!r,this.__v_isReadonly=s}get value(){const t=W(this);return Ys(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function Mi(e,t,n=!1){let s,r;const i=L(e);return i?(s=e,r=Ee):(s=e.get,r=e.set),new Fi(s,r,i||!r,n)}function Ue(e,t,n,s){let r;try{r=s?e(...s):e()}catch(i){Ft(i,t,n)}return r}function ye(e,t,n,s){if(L(e)){const i=Ue(e,t,n,s);return i&&Ns(i)&&i.catch(l=>{Ft(l,t,n)}),i}const r=[];for(let i=0;i>>1;wt(pe[s])Ie&&pe.splice(t,1)}function er(e,t,n,s){R(e)?n.push(...e):(!t||!t.includes(e,e.allowRecurse?s+1:s))&&n.push(e),Gs()}function Ni(e){er(e,ht,gt,Ge)}function Ri(e){er(e,He,mt,et)}function Jn(e,t=null){if(gt.length){for(Cn=t,ht=[...new Set(gt)],gt.length=0,Ge=0;Gewt(n)-wt(s)),et=0;ete.id==null?1/0:e.id;function tr(e){xn=!1,Bt=!0,Jn(e),pe.sort((n,s)=>wt(n)-wt(s));const t=Ee;try{for(Ie=0;IeM.trim()):E&&(r=n.map(Wr))}let f,u=s[f=rn(t)]||s[f=rn(Me(t))];!u&&i&&(u=s[f=rn(lt(t))]),u&&ye(u,e,6,r);const a=s[f+"Once"];if(a){if(!e.emitted)e.emitted={};else if(e.emitted[f])return;e.emitted[f]=!0,ye(a,e,6,r)}}function nr(e,t,n=!1){const s=t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let l={},f=!1;if(!L(e)){const u=a=>{const m=nr(a,t,!0);m&&(f=!0,oe(l,m))};!n&&t.mixins.length&&t.mixins.forEach(u),e.extends&&u(e.extends),e.mixins&&e.mixins.forEach(u)}return!i&&!f?(s.set(e,null),null):(R(i)?i.forEach(u=>l[u]=null):oe(l,i),s.set(e,l),l)}function Yt(e,t){return!e||!At(t)?!1:(t=t.slice(2).replace(/Once$/,""),$(e,t[0].toLowerCase()+t.slice(1))||$(e,lt(t))||$(e,t))}let le=null,Xt=null;function Ut(e){const t=le;return le=e,Xt=e&&e.type.__scopeId||null,t}function uo(e){Xt=e}function ao(){Xt=null}function Li(e,t=le,n){if(!t||e._n)return e;const s=(...r)=>{s._d&&ys(-1);const i=Ut(t),l=e(...r);return Ut(i),s._d&&ys(1),l};return s._n=!0,s._c=!0,s._d=!0,s}function fn(e){const{type:t,vnode:n,proxy:s,withProxy:r,props:i,propsOptions:[l],slots:f,attrs:u,emit:a,render:m,renderCache:E,data:w,setupState:M,ctx:I,inheritAttrs:S}=e;let h,b;const v=Ut(e);try{if(n.shapeFlag&4){const B=r||s;h=Ce(m.call(B,B,E,i,M,w,I)),b=u}else{const B=t;h=Ce(B.length>1?B(i,{attrs:u,slots:f,emit:a}):B(i,null)),b=t.props?u:Hi(u)}}catch(B){bt.length=0,Ft(B,e,1),h=te(ge)}let j=h;if(b&&S!==!1){const B=Object.keys(b),{shapeFlag:k}=j;B.length&&k&7&&(l&&B.some(Rn)&&(b=Bi(b,l)),j=Ye(j,b))}return n.dirs&&(j.dirs=j.dirs?j.dirs.concat(n.dirs):n.dirs),n.transition&&(j.transition=n.transition),h=j,Ut(v),h}const Hi=e=>{let t;for(const n in e)(n==="class"||n==="style"||At(n))&&((t||(t={}))[n]=e[n]);return t},Bi=(e,t)=>{const n={};for(const s in e)(!Rn(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function ji(e,t,n){const{props:s,children:r,component:i}=e,{props:l,children:f,patchFlag:u}=t,a=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&u>=0){if(u&1024)return!0;if(u&16)return s?cs(s,l,a):!!l;if(u&8){const m=t.dynamicProps;for(let E=0;Ee.__isSuspense;function sr(e,t){t&&t.pendingBranch?R(e)?t.effects.push(...e):t.effects.push(e):Ri(e)}function Di(e,t){if(ne){let n=ne.provides;const s=ne.parent&&ne.parent.provides;s===n&&(n=ne.provides=Object.create(s)),n[e]=t}}function cn(e,t,n=!1){const s=ne||le;if(s){const r=s.parent==null?s.vnode.appContext&&s.vnode.appContext.provides:s.parent.provides;if(r&&e in r)return r[e];if(arguments.length>1)return n&&L(t)?t.call(s.proxy):t}}function ho(e,t){return zn(e,null,t)}const us={};function un(e,t,n){return zn(e,t,n)}function zn(e,t,{immediate:n,deep:s,flush:r,onTrack:i,onTrigger:l}=z){const f=ne;let u,a=!1,m=!1;if(re(e)?(u=()=>e.value,a=Vs(e)):st(e)?(u=()=>e,s=!0):R(e)?(m=!0,a=e.some(st),u=()=>e.map(b=>{if(re(b))return b.value;if(st(b))return qe(b);if(L(b))return Ue(b,f,2)})):L(e)?t?u=()=>Ue(e,f,2):u=()=>{if(!(f&&f.isUnmounted))return E&&E(),ye(e,f,3,[w])}:u=Ee,t&&s){const b=u;u=()=>qe(b())}let E,w=b=>{E=h.onStop=()=>{Ue(b,f,4)}};if(it)return w=Ee,t?n&&ye(t,f,3,[u(),m?[]:void 0,w]):u(),Ee;let M=m?[]:us;const I=()=>{if(!!h.active)if(t){const b=h.run();(s||a||(m?b.some((v,j)=>yt(v,M[j])):yt(b,M)))&&(E&&E(),ye(t,f,3,[b,M===us?void 0:M,w]),M=b)}else h.run()};I.allowRecurse=!!t;let S;r==="sync"?S=I:r==="post"?S=()=>ae(I,f&&f.suspense):S=()=>{!f||f.isMounted?Ni(I):I()};const h=new jn(u,S);return t?n?I():M=h.run():r==="post"?ae(h.run.bind(h),f&&f.suspense):h.run(),()=>{h.stop(),f&&f.scope&&Sn(f.scope.effects,h)}}function Ki(e,t,n){const s=this.proxy,r=ie(e)?e.includes(".")?rr(s,e):()=>s[e]:e.bind(s,s);let i;L(t)?i=t:(i=t.handler,n=t);const l=ne;rt(this);const f=zn(r,i.bind(s),n);return l?rt(l):ze(),f}function rr(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;r{qe(n,t)});else if(Ss(e))for(const n in e)qe(e[n],t);return e}function ki(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return fr(()=>{e.isMounted=!0}),cr(()=>{e.isUnmounting=!0}),e}const _e=[Function,Array],Wi={name:"BaseTransition",props:{mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:_e,onEnter:_e,onAfterEnter:_e,onEnterCancelled:_e,onBeforeLeave:_e,onLeave:_e,onAfterLeave:_e,onLeaveCancelled:_e,onBeforeAppear:_e,onAppear:_e,onAfterAppear:_e,onAppearCancelled:_e},setup(e,{slots:t}){const n=Il(),s=ki();let r;return()=>{const i=t.default&&lr(t.default(),!0);if(!i||!i.length)return;let l=i[0];if(i.length>1){for(const S of i)if(S.type!==ge){l=S;break}}const f=W(e),{mode:u}=f;if(s.isLeaving)return an(l);const a=as(l);if(!a)return an(l);const m=wn(a,f,s,n);En(a,m);const E=n.subTree,w=E&&as(E);let M=!1;const{getTransitionKey:I}=a.type;if(I){const S=I();r===void 0?r=S:S!==r&&(r=S,M=!0)}if(w&&w.type!==ge&&(!ke(a,w)||M)){const S=wn(w,f,s,n);if(En(w,S),u==="out-in")return s.isLeaving=!0,S.afterLeave=()=>{s.isLeaving=!1,n.update()},an(l);u==="in-out"&&a.type!==ge&&(S.delayLeave=(h,b,v)=>{const j=ir(s,w);j[String(w.key)]=w,h._leaveCb=()=>{b(),h._leaveCb=void 0,delete m.delayedLeave},m.delayedLeave=v})}return l}}},qi=Wi;function ir(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function wn(e,t,n,s){const{appear:r,mode:i,persisted:l=!1,onBeforeEnter:f,onEnter:u,onAfterEnter:a,onEnterCancelled:m,onBeforeLeave:E,onLeave:w,onAfterLeave:M,onLeaveCancelled:I,onBeforeAppear:S,onAppear:h,onAfterAppear:b,onAppearCancelled:v}=t,j=String(e.key),B=ir(n,e),k=(F,D)=>{F&&ye(F,s,9,D)},q={mode:i,persisted:l,beforeEnter(F){let D=f;if(!n.isMounted)if(r)D=S||f;else return;F._leaveCb&&F._leaveCb(!0);const U=B[j];U&&ke(e,U)&&U.el._leaveCb&&U.el._leaveCb(),k(D,[F])},enter(F){let D=u,U=a,V=m;if(!n.isMounted)if(r)D=h||u,U=b||a,V=v||m;else return;let Q=!1;const H=F._enterCb=G=>{Q||(Q=!0,G?k(V,[F]):k(U,[F]),q.delayedLeave&&q.delayedLeave(),F._enterCb=void 0)};D?(D(F,H),D.length<=1&&H()):H()},leave(F,D){const U=String(e.key);if(F._enterCb&&F._enterCb(!0),n.isUnmounting)return D();k(E,[F]);let V=!1;const Q=F._leaveCb=H=>{V||(V=!0,D(),H?k(I,[F]):k(M,[F]),F._leaveCb=void 0,B[U]===e&&delete B[U])};B[U]=e,w?(w(F,Q),w.length<=1&&Q()):Q()},clone(F){return wn(F,t,n,s)}};return q}function an(e){if(Mt(e))return e=Ye(e),e.children=null,e}function as(e){return Mt(e)?e.children?e.children[0]:void 0:e}function En(e,t){e.shapeFlag&6&&e.component?En(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function lr(e,t=!1,n){let s=[],r=0;for(let i=0;i1)for(let i=0;i!!e.type.__asyncLoader;function po(e){L(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:s,delay:r=200,timeout:i,suspensible:l=!0,onError:f}=e;let u=null,a,m=0;const E=()=>(m++,u=null,w()),w=()=>{let M;return u||(M=u=t().catch(I=>{if(I=I instanceof Error?I:new Error(String(I)),f)return new Promise((S,h)=>{f(I,()=>S(E()),()=>h(I),m+1)});throw I}).then(I=>M!==u&&u?u:(I&&(I.__esModule||I[Symbol.toStringTag]==="Module")&&(I=I.default),a=I,I)))};return Vi({name:"AsyncComponentWrapper",__asyncLoader:w,get __asyncResolved(){return a},setup(){const M=ne;if(a)return()=>dn(a,M);const I=v=>{u=null,Ft(v,M,13,!s)};if(l&&M.suspense||it)return w().then(v=>()=>dn(v,M)).catch(v=>(I(v),()=>s?te(s,{error:v}):null));const S=on(!1),h=on(),b=on(!!r);return r&&setTimeout(()=>{b.value=!1},r),i!=null&&setTimeout(()=>{if(!S.value&&!h.value){const v=new Error(`Async component timed out after ${i}ms.`);I(v),h.value=v}},i),w().then(()=>{S.value=!0,M.parent&&Mt(M.parent.vnode)&&Vn(M.parent.update)}).catch(v=>{I(v),h.value=v}),()=>{if(S.value&&a)return dn(a,M);if(h.value&&s)return te(s,{error:h.value});if(n&&!b.value)return te(n)}}})}function dn(e,{vnode:{ref:t,props:n,children:s}}){const r=te(e,n,s);return r.ref=t,r}const Mt=e=>e.type.__isKeepAlive;function Ji(e,t){or(e,"a",t)}function zi(e,t){or(e,"da",t)}function or(e,t,n=ne){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(Zt(t,s,n),n){let r=n.parent;for(;r&&r.parent;)Mt(r.parent.vnode)&&Yi(s,t,n,r),r=r.parent}}function Yi(e,t,n,s){const r=Zt(t,e,s,!0);ur(()=>{Sn(s[t],r)},n)}function Zt(e,t,n=ne,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...l)=>{if(n.isUnmounted)return;ot(),rt(n);const f=ye(t,n,e,l);return ze(),ft(),f});return s?r.unshift(i):r.push(i),i}}const Ne=e=>(t,n=ne)=>(!it||e==="sp")&&Zt(e,t,n),Xi=Ne("bm"),fr=Ne("m"),Zi=Ne("bu"),Qi=Ne("u"),cr=Ne("bum"),ur=Ne("um"),Gi=Ne("sp"),el=Ne("rtg"),tl=Ne("rtc");function nl(e,t=ne){Zt("ec",e,t)}let Tn=!0;function sl(e){const t=dr(e),n=e.proxy,s=e.ctx;Tn=!1,t.beforeCreate&&ds(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:l,watch:f,provide:u,inject:a,created:m,beforeMount:E,mounted:w,beforeUpdate:M,updated:I,activated:S,deactivated:h,beforeDestroy:b,beforeUnmount:v,destroyed:j,unmounted:B,render:k,renderTracked:q,renderTriggered:F,errorCaptured:D,serverPrefetch:U,expose:V,inheritAttrs:Q,components:H,directives:G,filters:ce}=t;if(a&&rl(a,s,null,e.appContext.config.unwrapInjectedRef),l)for(const ee in l){const Y=l[ee];L(Y)&&(s[ee]=Y.bind(n))}if(r){const ee=r.call(n,n);se(ee)&&(e.data=Kn(ee))}if(Tn=!0,i)for(const ee in i){const Y=i[ee],Oe=L(Y)?Y.bind(n,n):L(Y.get)?Y.get.bind(n,n):Ee,tn=!L(Y)&&L(Y.set)?Y.set.bind(n):Ee,ct=Bl({get:Oe,set:tn});Object.defineProperty(s,ee,{enumerable:!0,configurable:!0,get:()=>ct.value,set:Xe=>ct.value=Xe})}if(f)for(const ee in f)ar(f[ee],s,n,ee);if(u){const ee=L(u)?u.call(n):u;Reflect.ownKeys(ee).forEach(Y=>{Di(Y,ee[Y])})}m&&ds(m,e,"c");function ue(ee,Y){R(Y)?Y.forEach(Oe=>ee(Oe.bind(n))):Y&&ee(Y.bind(n))}if(ue(Xi,E),ue(fr,w),ue(Zi,M),ue(Qi,I),ue(Ji,S),ue(zi,h),ue(nl,D),ue(tl,q),ue(el,F),ue(cr,v),ue(ur,B),ue(Gi,U),R(V))if(V.length){const ee=e.exposed||(e.exposed={});V.forEach(Y=>{Object.defineProperty(ee,Y,{get:()=>n[Y],set:Oe=>n[Y]=Oe})})}else e.exposed||(e.exposed={});k&&e.render===Ee&&(e.render=k),Q!=null&&(e.inheritAttrs=Q),H&&(e.components=H),G&&(e.directives=G)}function rl(e,t,n=Ee,s=!1){R(e)&&(e=An(e));for(const r in e){const i=e[r];let l;se(i)?"default"in i?l=cn(i.from||r,i.default,!0):l=cn(i.from||r):l=cn(i),re(l)&&s?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>l.value,set:f=>l.value=f}):t[r]=l}}function ds(e,t,n){ye(R(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function ar(e,t,n,s){const r=s.includes(".")?rr(n,s):()=>n[s];if(ie(e)){const i=t[e];L(i)&&un(r,i)}else if(L(e))un(r,e.bind(n));else if(se(e))if(R(e))e.forEach(i=>ar(i,t,n,s));else{const i=L(e.handler)?e.handler.bind(n):t[e.handler];L(i)&&un(r,i,e)}}function dr(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:l}}=e.appContext,f=i.get(t);let u;return f?u=f:!r.length&&!n&&!s?u=t:(u={},r.length&&r.forEach(a=>$t(u,a,l,!0)),$t(u,t,l)),i.set(t,u),u}function $t(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&$t(e,i,n,!0),r&&r.forEach(l=>$t(e,l,n,!0));for(const l in t)if(!(s&&l==="expose")){const f=il[l]||n&&n[l];e[l]=f?f(e[l],t[l]):t[l]}return e}const il={data:hs,props:Ke,emits:Ke,methods:Ke,computed:Ke,beforeCreate:fe,created:fe,beforeMount:fe,mounted:fe,beforeUpdate:fe,updated:fe,beforeDestroy:fe,beforeUnmount:fe,destroyed:fe,unmounted:fe,activated:fe,deactivated:fe,errorCaptured:fe,serverPrefetch:fe,components:Ke,directives:Ke,watch:ol,provide:hs,inject:ll};function hs(e,t){return t?e?function(){return oe(L(e)?e.call(this,this):e,L(t)?t.call(this,this):t)}:t:e}function ll(e,t){return Ke(An(e),An(t))}function An(e){if(R(e)){const t={};for(let n=0;n0)&&!(l&16)){if(l&8){const m=e.vnode.dynamicProps;for(let E=0;E{u=!0;const[w,M]=pr(E,t,!0);oe(l,w),M&&f.push(...M)};!n&&t.mixins.length&&t.mixins.forEach(m),e.extends&&m(e.extends),e.mixins&&e.mixins.forEach(m)}if(!i&&!u)return s.set(e,tt),tt;if(R(i))for(let m=0;m-1,M[1]=S<0||I-1||$(M,"default"))&&f.push(E)}}}const a=[l,f];return s.set(e,a),a}function ps(e){return e[0]!=="$"}function gs(e){const t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:e===null?"null":""}function ms(e,t){return gs(e)===gs(t)}function _s(e,t){return R(t)?t.findIndex(n=>ms(n,e)):L(t)&&ms(t,e)?0:-1}const gr=e=>e[0]==="_"||e==="$stable",Yn=e=>R(e)?e.map(Ce):[Ce(e)],ul=(e,t,n)=>{const s=Li((...r)=>Yn(t(...r)),n);return s._c=!1,s},mr=(e,t,n)=>{const s=e._ctx;for(const r in e){if(gr(r))continue;const i=e[r];if(L(i))t[r]=ul(r,i,s);else if(i!=null){const l=Yn(i);t[r]=()=>l}}},_r=(e,t)=>{const n=Yn(t);e.slots.default=()=>n},al=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=W(t),Ht(t,"_",n)):mr(t,e.slots={})}else e.slots={},t&&_r(e,t);Ht(e.slots,Qt,1)},dl=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,l=z;if(s.shapeFlag&32){const f=t._;f?n&&f===1?i=!1:(oe(r,t),!n&&f===1&&delete r._):(i=!t.$stable,mr(t,r)),l=t}else t&&(_r(e,t),l={default:1});if(i)for(const f in r)!gr(f)&&!(f in l)&&delete r[f]};function go(e,t){const n=le;if(n===null)return e;const s=Gt(n)||n.proxy,r=e.dirs||(e.dirs=[]);for(let i=0;iDt(w,t&&(R(t)?t[M]:t),n,s,r));return}if(Et(s)&&!r)return;const i=s.shapeFlag&4?Gt(s.component)||s.component.proxy:s.el,l=r?null:i,{i:f,r:u}=e,a=t&&t.r,m=f.refs===z?f.refs={}:f.refs,E=f.setupState;if(a!=null&&a!==u&&(ie(a)?(m[a]=null,$(E,a)&&(E[a]=null)):re(a)&&(a.value=null)),L(u))Ue(u,f,12,[l,m]);else{const w=ie(u),M=re(u);if(w||M){const I=()=>{if(e.f){const S=w?m[u]:u.value;r?R(S)&&Sn(S,i):R(S)?S.includes(i)||S.push(i):w?(m[u]=[i],$(E,u)&&(E[u]=m[u])):(u.value=[i],e.k&&(m[e.k]=u.value))}else w?(m[u]=l,$(E,u)&&(E[u]=l)):re(u)&&(u.value=l,e.k&&(m[e.k]=l))};l?(I.id=-1,ae(I,n)):I()}}}let Le=!1;const St=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",hn=e=>e.nodeType===8;function gl(e){const{mt:t,p:n,o:{patchProp:s,nextSibling:r,parentNode:i,remove:l,insert:f,createComment:u}}=e,a=(h,b)=>{if(!b.hasChildNodes()){n(null,h,b),jt();return}Le=!1,m(b.firstChild,h,null,null,null),jt(),Le&&console.error("Hydration completed but contains mismatches.")},m=(h,b,v,j,B,k=!1)=>{const q=hn(h)&&h.data==="[",F=()=>I(h,b,v,j,B,q),{type:D,ref:U,shapeFlag:V}=b,Q=h.nodeType;b.el=h;let H=null;switch(D){case Tt:Q!==3?H=F():(h.data!==b.children&&(Le=!0,h.data=b.children),H=r(h));break;case ge:Q!==8||q?H=F():H=r(h);break;case _t:if(Q!==1)H=F();else{H=h;const G=!b.children.length;for(let ce=0;ce{k=k||!!b.dynamicChildren;const{type:q,props:F,patchFlag:D,shapeFlag:U,dirs:V}=b,Q=q==="input"&&V||q==="option";if(Q||D!==-1){if(V&&Fe(b,null,v,"created"),F)if(Q||!k||D&48)for(const G in F)(Q&&G.endsWith("value")||At(G)&&!pt(G))&&s(h,G,null,F[G],!1,void 0,v);else F.onClick&&s(h,"onClick",null,F.onClick,!1,void 0,v);let H;if((H=F&&F.onVnodeBeforeMount)&&be(H,v,b),V&&Fe(b,null,v,"beforeMount"),((H=F&&F.onVnodeMounted)||V)&&sr(()=>{H&&be(H,v,b),V&&Fe(b,null,v,"mounted")},j),U&16&&!(F&&(F.innerHTML||F.textContent))){let G=w(h.firstChild,b,h,v,j,B,k);for(;G;){Le=!0;const ce=G;G=G.nextSibling,l(ce)}}else U&8&&h.textContent!==b.children&&(Le=!0,h.textContent=b.children)}return h.nextSibling},w=(h,b,v,j,B,k,q)=>{q=q||!!b.dynamicChildren;const F=b.children,D=F.length;for(let U=0;U{const{slotScopeIds:q}=b;q&&(B=B?B.concat(q):q);const F=i(h),D=w(r(h),b,F,v,j,B,k);return D&&hn(D)&&D.data==="]"?r(b.anchor=D):(Le=!0,f(b.anchor=u("]"),F,D),D)},I=(h,b,v,j,B,k)=>{if(Le=!0,b.el=null,k){const D=S(h);for(;;){const U=r(h);if(U&&U!==D)l(U);else break}}const q=r(h),F=i(h);return l(h),n(null,b,F,q,v,j,St(F),B),q},S=h=>{let b=0;for(;h;)if(h=r(h),h&&hn(h)&&(h.data==="["&&b++,h.data==="]")){if(b===0)return r(h);b--}return h};return[a,m]}const ae=sr;function ml(e){return _l(e,gl)}function _l(e,t){const n=qr();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:l,createText:f,createComment:u,setText:a,setElementText:m,parentNode:E,nextSibling:w,setScopeId:M=Ee,cloneNode:I,insertStaticContent:S}=e,h=(o,c,d,g=null,p=null,x=null,T=!1,y=null,C=!!c.dynamicChildren)=>{if(o===c)return;o&&!ke(o,c)&&(g=Ot(o),Re(o,p,x,!0),o=null),c.patchFlag===-2&&(C=!1,c.dynamicChildren=null);const{type:_,ref:O,shapeFlag:A}=c;switch(_){case Tt:b(o,c,d,g);break;case ge:v(o,c,d,g);break;case _t:o==null&&j(c,d,g,T);break;case de:G(o,c,d,g,p,x,T,y,C);break;default:A&1?q(o,c,d,g,p,x,T,y,C):A&6?ce(o,c,d,g,p,x,T,y,C):(A&64||A&128)&&_.process(o,c,d,g,p,x,T,y,C,Ze)}O!=null&&p&&Dt(O,o&&o.ref,x,c||o,!c)},b=(o,c,d,g)=>{if(o==null)s(c.el=f(c.children),d,g);else{const p=c.el=o.el;c.children!==o.children&&a(p,c.children)}},v=(o,c,d,g)=>{o==null?s(c.el=u(c.children||""),d,g):c.el=o.el},j=(o,c,d,g)=>{[o.el,o.anchor]=S(o.children,c,d,g,o.el,o.anchor)},B=({el:o,anchor:c},d,g)=>{let p;for(;o&&o!==c;)p=w(o),s(o,d,g),o=p;s(c,d,g)},k=({el:o,anchor:c})=>{let d;for(;o&&o!==c;)d=w(o),r(o),o=d;r(c)},q=(o,c,d,g,p,x,T,y,C)=>{T=T||c.type==="svg",o==null?F(c,d,g,p,x,T,y,C):V(o,c,p,x,T,y,C)},F=(o,c,d,g,p,x,T,y)=>{let C,_;const{type:O,props:A,shapeFlag:P,transition:N,patchFlag:K,dirs:Z}=o;if(o.el&&I!==void 0&&K===-1)C=o.el=I(o.el);else{if(C=o.el=l(o.type,x,A&&A.is,A),P&8?m(C,o.children):P&16&&U(o.children,C,null,g,p,x&&O!=="foreignObject",T,y),Z&&Fe(o,null,g,"created"),A){for(const X in A)X!=="value"&&!pt(X)&&i(C,X,null,A[X],x,o.children,g,p,Pe);"value"in A&&i(C,"value",null,A.value),(_=A.onVnodeBeforeMount)&&be(_,g,o)}D(C,o,o.scopeId,T,g)}Z&&Fe(o,null,g,"beforeMount");const J=(!p||p&&!p.pendingBranch)&&N&&!N.persisted;J&&N.beforeEnter(C),s(C,c,d),((_=A&&A.onVnodeMounted)||J||Z)&&ae(()=>{_&&be(_,g,o),J&&N.enter(C),Z&&Fe(o,null,g,"mounted")},p)},D=(o,c,d,g,p)=>{if(d&&M(o,d),g)for(let x=0;x{for(let _=C;_{const y=c.el=o.el;let{patchFlag:C,dynamicChildren:_,dirs:O}=c;C|=o.patchFlag&16;const A=o.props||z,P=c.props||z;let N;d&&De(d,!1),(N=P.onVnodeBeforeUpdate)&&be(N,d,c,o),O&&Fe(c,o,d,"beforeUpdate"),d&&De(d,!0);const K=p&&c.type!=="foreignObject";if(_?Q(o.dynamicChildren,_,y,d,g,K,x):T||Oe(o,c,y,null,d,g,K,x,!1),C>0){if(C&16)H(y,c,A,P,d,g,p);else if(C&2&&A.class!==P.class&&i(y,"class",null,P.class,p),C&4&&i(y,"style",A.style,P.style,p),C&8){const Z=c.dynamicProps;for(let J=0;J{N&&be(N,d,c,o),O&&Fe(c,o,d,"updated")},g)},Q=(o,c,d,g,p,x,T)=>{for(let y=0;y{if(d!==g){for(const y in g){if(pt(y))continue;const C=g[y],_=d[y];C!==_&&y!=="value"&&i(o,y,_,C,T,c.children,p,x,Pe)}if(d!==z)for(const y in d)!pt(y)&&!(y in g)&&i(o,y,d[y],null,T,c.children,p,x,Pe);"value"in g&&i(o,"value",d.value,g.value)}},G=(o,c,d,g,p,x,T,y,C)=>{const _=c.el=o?o.el:f(""),O=c.anchor=o?o.anchor:f("");let{patchFlag:A,dynamicChildren:P,slotScopeIds:N}=c;N&&(y=y?y.concat(N):N),o==null?(s(_,d,g),s(O,d,g),U(c.children,d,O,p,x,T,y,C)):A>0&&A&64&&P&&o.dynamicChildren?(Q(o.dynamicChildren,P,d,p,x,T,y),(c.key!=null||p&&c===p.subTree)&&yr(o,c,!0)):Oe(o,c,d,O,p,x,T,y,C)},ce=(o,c,d,g,p,x,T,y,C)=>{c.slotScopeIds=y,o==null?c.shapeFlag&512?p.ctx.activate(c,d,g,T,C):en(c,d,g,p,x,T,C):ue(o,c,C)},en=(o,c,d,g,p,x,T)=>{const y=o.component=Pl(o,g,p);if(Mt(o)&&(y.ctx.renderer=Ze),vl(y),y.asyncDep){if(p&&p.registerDep(y,ee),!o.el){const C=y.subTree=te(ge);v(null,C,c,d)}return}ee(y,o,c,d,p,x,T)},ue=(o,c,d)=>{const g=c.component=o.component;if(ji(o,c,d))if(g.asyncDep&&!g.asyncResolved){Y(g,c,d);return}else g.next=c,vi(g.update),g.update();else c.component=o.component,c.el=o.el,g.vnode=c},ee=(o,c,d,g,p,x,T)=>{const y=()=>{if(o.isMounted){let{next:O,bu:A,u:P,parent:N,vnode:K}=o,Z=O,J;De(o,!1),O?(O.el=K.el,Y(o,O,T)):O=K,A&&ln(A),(J=O.props&&O.props.onVnodeBeforeUpdate)&&be(J,N,O,K),De(o,!0);const X=fn(o),xe=o.subTree;o.subTree=X,h(xe,X,E(xe.el),Ot(xe),o,p,x),O.el=X.el,Z===null&&Ui(o,X.el),P&&ae(P,p),(J=O.props&&O.props.onVnodeUpdated)&&ae(()=>be(J,N,O,K),p)}else{let O;const{el:A,props:P}=c,{bm:N,m:K,parent:Z}=o,J=Et(c);if(De(o,!1),N&&ln(N),!J&&(O=P&&P.onVnodeBeforeMount)&&be(O,Z,c),De(o,!0),A&&sn){const X=()=>{o.subTree=fn(o),sn(A,o.subTree,o,p,null)};J?c.type.__asyncLoader().then(()=>!o.isUnmounted&&X()):X()}else{const X=o.subTree=fn(o);h(null,X,d,g,o,p,x),c.el=X.el}if(K&&ae(K,p),!J&&(O=P&&P.onVnodeMounted)){const X=c;ae(()=>be(O,Z,X),p)}c.shapeFlag&256&&o.a&&ae(o.a,p),o.isMounted=!0,c=d=g=null}},C=o.effect=new jn(y,()=>Vn(o.update),o.scope),_=o.update=C.run.bind(C);_.id=o.uid,De(o,!0),_()},Y=(o,c,d)=>{c.component=o;const g=o.vnode.props;o.vnode=c,o.next=null,cl(o,c.props,g,d),dl(o,c.children,d),ot(),Jn(void 0,o.update),ft()},Oe=(o,c,d,g,p,x,T,y,C=!1)=>{const _=o&&o.children,O=o?o.shapeFlag:0,A=c.children,{patchFlag:P,shapeFlag:N}=c;if(P>0){if(P&128){ct(_,A,d,g,p,x,T,y,C);return}else if(P&256){tn(_,A,d,g,p,x,T,y,C);return}}N&8?(O&16&&Pe(_,p,x),A!==_&&m(d,A)):O&16?N&16?ct(_,A,d,g,p,x,T,y,C):Pe(_,p,x,!0):(O&8&&m(d,""),N&16&&U(A,d,g,p,x,T,y,C))},tn=(o,c,d,g,p,x,T,y,C)=>{o=o||tt,c=c||tt;const _=o.length,O=c.length,A=Math.min(_,O);let P;for(P=0;PO?Pe(o,p,x,!0,!1,A):U(c,d,g,p,x,T,y,C,A)},ct=(o,c,d,g,p,x,T,y,C)=>{let _=0;const O=c.length;let A=o.length-1,P=O-1;for(;_<=A&&_<=P;){const N=o[_],K=c[_]=C?Be(c[_]):Ce(c[_]);if(ke(N,K))h(N,K,d,null,p,x,T,y,C);else break;_++}for(;_<=A&&_<=P;){const N=o[A],K=c[P]=C?Be(c[P]):Ce(c[P]);if(ke(N,K))h(N,K,d,null,p,x,T,y,C);else break;A--,P--}if(_>A){if(_<=P){const N=P+1,K=NP)for(;_<=A;)Re(o[_],p,x,!0),_++;else{const N=_,K=_,Z=new Map;for(_=K;_<=P;_++){const he=c[_]=C?Be(c[_]):Ce(c[_]);he.key!=null&&Z.set(he.key,_)}let J,X=0;const xe=P-K+1;let Qe=!1,Gn=0;const ut=new Array(xe);for(_=0;_=xe){Re(he,p,x,!0);continue}let Te;if(he.key!=null)Te=Z.get(he.key);else for(J=K;J<=P;J++)if(ut[J-K]===0&&ke(he,c[J])){Te=J;break}Te===void 0?Re(he,p,x,!0):(ut[Te-K]=_+1,Te>=Gn?Gn=Te:Qe=!0,h(he,c[Te],d,null,p,x,T,y,C),X++)}const es=Qe?bl(ut):tt;for(J=es.length-1,_=xe-1;_>=0;_--){const he=K+_,Te=c[he],ts=he+1{const{el:x,type:T,transition:y,children:C,shapeFlag:_}=o;if(_&6){Xe(o.component.subTree,c,d,g);return}if(_&128){o.suspense.move(c,d,g);return}if(_&64){T.move(o,c,d,Ze);return}if(T===de){s(x,c,d);for(let A=0;Ay.enter(x),p);else{const{leave:A,delayLeave:P,afterLeave:N}=y,K=()=>s(x,c,d),Z=()=>{A(x,()=>{K(),N&&N()})};P?P(x,K,Z):Z()}else s(x,c,d)},Re=(o,c,d,g=!1,p=!1)=>{const{type:x,props:T,ref:y,children:C,dynamicChildren:_,shapeFlag:O,patchFlag:A,dirs:P}=o;if(y!=null&&Dt(y,null,d,o,!0),O&256){c.ctx.deactivate(o);return}const N=O&1&&P,K=!Et(o);let Z;if(K&&(Z=T&&T.onVnodeBeforeUnmount)&&be(Z,c,o),O&6)Nr(o.component,d,g);else{if(O&128){o.suspense.unmount(d,g);return}N&&Fe(o,null,c,"beforeUnmount"),O&64?o.type.remove(o,c,d,p,Ze,g):_&&(x!==de||A>0&&A&64)?Pe(_,c,d,!1,!0):(x===de&&A&384||!p&&O&16)&&Pe(C,c,d),g&&Zn(o)}(K&&(Z=T&&T.onVnodeUnmounted)||N)&&ae(()=>{Z&&be(Z,c,o),N&&Fe(o,null,c,"unmounted")},d)},Zn=o=>{const{type:c,el:d,anchor:g,transition:p}=o;if(c===de){vr(d,g);return}if(c===_t){k(o);return}const x=()=>{r(d),p&&!p.persisted&&p.afterLeave&&p.afterLeave()};if(o.shapeFlag&1&&p&&!p.persisted){const{leave:T,delayLeave:y}=p,C=()=>T(d,x);y?y(o.el,x,C):C()}else x()},vr=(o,c)=>{let d;for(;o!==c;)d=w(o),r(o),o=d;r(c)},Nr=(o,c,d)=>{const{bum:g,scope:p,update:x,subTree:T,um:y}=o;g&&ln(g),p.stop(),x&&(x.active=!1,Re(T,o,c,d)),y&&ae(y,c),ae(()=>{o.isUnmounted=!0},c),c&&c.pendingBranch&&!c.isUnmounted&&o.asyncDep&&!o.asyncResolved&&o.suspenseId===c.pendingId&&(c.deps--,c.deps===0&&c.resolve())},Pe=(o,c,d,g=!1,p=!1,x=0)=>{for(let T=x;To.shapeFlag&6?Ot(o.component.subTree):o.shapeFlag&128?o.suspense.next():w(o.anchor||o.el),Qn=(o,c,d)=>{o==null?c._vnode&&Re(c._vnode,null,null,!0):h(c._vnode||null,o,c,null,null,null,d),jt(),c._vnode=o},Ze={p:h,um:Re,m:Xe,r:Zn,mt:en,mc:U,pc:Oe,pbc:Q,n:Ot,o:e};let nn,sn;return t&&([nn,sn]=t(Ze)),{render:Qn,hydrate:nn,createApp:pl(Qn,nn)}}function De({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function yr(e,t,n=!1){const s=e.children,r=t.children;if(R(s)&&R(r))for(let i=0;i>1,e[n[f]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,l=n[i-1];i-- >0;)n[i]=l,l=t[l];return n}const yl=e=>e.__isTeleport,xr="components";function mo(e,t){return Cl(xr,e,!0,t)||e}const xl=Symbol();function Cl(e,t,n=!0,s=!1){const r=le||ne;if(r){const i=r.type;if(e===xr){const f=Ll(i);if(f&&(f===t||f===Me(t)||f===Jt(Me(t))))return i}const l=bs(r[e]||i[e],t)||bs(r.appContext[e],t);return!l&&s?i:l}}function bs(e,t){return e&&(e[t]||e[Me(t)]||e[Jt(Me(t))])}const de=Symbol(void 0),Tt=Symbol(void 0),ge=Symbol(void 0),_t=Symbol(void 0),bt=[];let Je=null;function Cr(e=!1){bt.push(Je=e?null:[])}function wl(){bt.pop(),Je=bt[bt.length-1]||null}let Kt=1;function ys(e){Kt+=e}function wr(e){return e.dynamicChildren=Kt>0?Je||tt:null,wl(),Kt>0&&Je&&Je.push(e),e}function _o(e,t,n,s,r,i){return wr(Ar(e,t,n,s,r,i,!0))}function Er(e,t,n,s,r){return wr(te(e,t,n,s,r,!0))}function kt(e){return e?e.__v_isVNode===!0:!1}function ke(e,t){return e.type===t.type&&e.key===t.key}const Qt="__vInternal",Tr=({key:e})=>e!=null?e:null,Lt=({ref:e,ref_key:t,ref_for:n})=>e!=null?ie(e)||re(e)||L(e)?{i:le,r:e,k:t,f:!!n}:e:null;function Ar(e,t=null,n=null,s=0,r=null,i=e===de?0:1,l=!1,f=!1){const u={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Tr(t),ref:t&&Lt(t),scopeId:Xt,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null};return f?(Xn(u,n),i&128&&e.normalize(u)):n&&(u.shapeFlag|=ie(n)?8:16),Kt>0&&!l&&Je&&(u.patchFlag>0||i&6)&&u.patchFlag!==32&&Je.push(u),u}const te=El;function El(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===xl)&&(e=ge),kt(e)){const f=Ye(e,t,!0);return n&&Xn(f,n),f}if(Hl(e)&&(e=e.__vccOpts),t){t=Tl(t);let{class:f,style:u}=t;f&&!ie(f)&&(t.class=Nn(f)),se(u)&&(Js(u)&&!R(u)&&(u=oe({},u)),t.style=vn(u))}const l=ie(e)?1:$i(e)?128:yl(e)?64:se(e)?4:L(e)?2:0;return Ar(e,t,n,s,r,l,i,!0)}function Tl(e){return e?Js(e)||Qt in e?oe({},e):e:null}function Ye(e,t,n=!1){const{props:s,ref:r,patchFlag:i,children:l}=e,f=t?Al(s||{},t):s;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:f,key:f&&Tr(f),ref:t&&t.ref?n&&r?R(r)?r.concat(Lt(t)):[r,Lt(t)]:Lt(t):r,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==de?i===-1?16:i|16:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Ye(e.ssContent),ssFallback:e.ssFallback&&Ye(e.ssFallback),el:e.el,anchor:e.anchor}}function Fr(e=" ",t=0){return te(Tt,null,e,t)}function bo(e,t){const n=te(_t,null,e);return n.staticCount=t,n}function yo(e="",t=!1){return t?(Cr(),Er(ge,null,e)):te(ge,null,e)}function Ce(e){return e==null||typeof e=="boolean"?te(ge):R(e)?te(de,null,e.slice()):typeof e=="object"?Be(e):te(Tt,null,String(e))}function Be(e){return e.el===null||e.memo?e:Ye(e)}function Xn(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(R(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),Xn(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!(Qt in t)?t._ctx=le:r===3&&le&&(le.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else L(t)?(t={default:t,_ctx:le},n=32):(t=String(t),s&64?(n=16,t=[Fr(t)]):n=8);e.children=t,e.shapeFlag|=n}function Al(...e){const t={};for(let n=0;nt(l,f,void 0,i&&i[f]));else{const l=Object.keys(e);r=new Array(l.length);for(let f=0,u=l.length;fkt(t)?!(t.type===ge||t.type===de&&!Mr(t.children)):!0)?e:null}const Mn=e=>e?Or(e)?Gt(e)||e.proxy:Mn(e.parent):null,Wt=oe(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Mn(e.parent),$root:e=>Mn(e.root),$emit:e=>e.emit,$options:e=>dr(e),$forceUpdate:e=>()=>Vn(e.update),$nextTick:e=>Pi.bind(e.proxy),$watch:e=>Ki.bind(e)}),Fl={get({_:e},t){const{ctx:n,setupState:s,data:r,props:i,accessCache:l,type:f,appContext:u}=e;let a;if(t[0]!=="$"){const M=l[t];if(M!==void 0)switch(M){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(s!==z&&$(s,t))return l[t]=1,s[t];if(r!==z&&$(r,t))return l[t]=2,r[t];if((a=e.propsOptions[0])&&$(a,t))return l[t]=3,i[t];if(n!==z&&$(n,t))return l[t]=4,n[t];Tn&&(l[t]=0)}}const m=Wt[t];let E,w;if(m)return t==="$attrs"&&me(e,"get",t),m(e);if((E=f.__cssModules)&&(E=E[t]))return E;if(n!==z&&$(n,t))return l[t]=4,n[t];if(w=u.config.globalProperties,$(w,t))return w[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return r!==z&&$(r,t)?(r[t]=n,!0):s!==z&&$(s,t)?(s[t]=n,!0):$(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,propsOptions:i}},l){let f;return!!n[l]||e!==z&&$(e,l)||t!==z&&$(t,l)||(f=i[0])&&$(f,l)||$(s,l)||$(Wt,l)||$(r.config.globalProperties,l)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:$(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}},Ml=br();let Ol=0;function Pl(e,t,n){const s=e.type,r=(t?t.appContext:e.appContext)||Ml,i={uid:Ol++,vnode:e,type:s,parent:t,appContext:r,root:null,next:null,subTree:null,effect:null,update:null,scope:new Vr(!0),render:null,proxy:null,exposed:null,exposeProxy:null,withProxy:null,provides:t?t.provides:Object.create(r.provides),accessCache:null,renderCache:[],components:null,directives:null,propsOptions:pr(s,r),emitsOptions:nr(s,r),emit:null,emitted:null,propsDefaults:z,inheritAttrs:s.inheritAttrs,ctx:z,data:z,props:z,attrs:z,slots:z,refs:z,setupState:z,setupContext:null,suspense:n,suspenseId:n?n.pendingId:0,asyncDep:null,asyncResolved:!1,isMounted:!1,isUnmounted:!1,isDeactivated:!1,bc:null,c:null,bm:null,m:null,bu:null,u:null,um:null,bum:null,da:null,a:null,rtg:null,rtc:null,ec:null,sp:null};return i.ctx={_:i},i.root=t?t.root:i,i.emit=Si.bind(null,i),e.ce&&e.ce(i),i}let ne=null;const Il=()=>ne||le,rt=e=>{ne=e,e.scope.on()},ze=()=>{ne&&ne.scope.off(),ne=null};function Or(e){return e.vnode.shapeFlag&4}let it=!1;function vl(e,t=!1){it=t;const{props:n,children:s}=e.vnode,r=Or(e);fl(e,n,r,t),al(e,s);const i=r?Nl(e,t):void 0;return it=!1,i}function Nl(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=zs(new Proxy(e.ctx,Fl));const{setup:s}=n;if(s){const r=e.setupContext=s.length>1?Sl(e):null;rt(e),ot();const i=Ue(s,e,0,[e.props,r]);if(ft(),ze(),Ns(i)){if(i.then(ze,ze),t)return i.then(l=>{xs(e,l,t)}).catch(l=>{Ft(l,e,0)});e.asyncDep=i}else xs(e,i,t)}else Pr(e,t)}function xs(e,t,n){L(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:se(t)&&(e.setupState=Zs(t)),Pr(e,n)}let Cs;function Pr(e,t,n){const s=e.type;if(!e.render){if(!t&&Cs&&!s.render){const r=s.template;if(r){const{isCustomElement:i,compilerOptions:l}=e.appContext.config,{delimiters:f,compilerOptions:u}=s,a=oe(oe({isCustomElement:i,delimiters:f},l),u);s.render=Cs(r,a)}}e.render=s.render||Ee}rt(e),ot(),sl(e),ft(),ze()}function Rl(e){return new Proxy(e.attrs,{get(t,n){return me(e,"get","$attrs"),t[n]}})}function Sl(e){const t=s=>{e.exposed=s||{}};let n;return{get attrs(){return n||(n=Rl(e))},slots:e.slots,emit:e.emit,expose:t}}function Gt(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Zs(zs(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Wt)return Wt[n](e)}}))}function Ll(e){return L(e)&&e.displayName||e.name}function Hl(e){return L(e)&&"__vccOpts"in e}const Bl=(e,t)=>Mi(e,t,it);function wo(e,t,n){const s=arguments.length;return s===2?se(t)&&!R(t)?kt(t)?te(e,null,[t]):te(e,t):te(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&kt(n)&&(n=[n]),te(e,t,n))}const jl="3.2.33",Ul="http://www.w3.org/2000/svg",We=typeof document!="undefined"?document:null,ws=We&&We.createElement("template"),$l={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t?We.createElementNS(Ul,e):We.createElement(e,n?{is:n}:void 0);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>We.createTextNode(e),createComment:e=>We.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>We.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},cloneNode(e){const t=e.cloneNode(!0);return"_value"in e&&(t._value=e._value),t},insertStaticContent(e,t,n,s,r,i){const l=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{ws.innerHTML=s?`${e}`:e;const f=ws.content;if(s){const u=f.firstChild;for(;u.firstChild;)f.appendChild(u.firstChild);f.removeChild(u)}t.insertBefore(f,n)}return[l?l.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}};function Dl(e,t,n){const s=e._vtc;s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}function Kl(e,t,n){const s=e.style,r=ie(n);if(n&&!r){for(const i in n)On(s,i,n[i]);if(t&&!ie(t))for(const i in t)n[i]==null&&On(s,i,"")}else{const i=s.display;r?t!==n&&(s.cssText=n):t&&e.removeAttribute("style"),"_vod"in e&&(s.display=i)}}const Es=/\s*!important$/;function On(e,t,n){if(R(n))n.forEach(s=>On(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=kl(e,t);Es.test(n)?e.setProperty(lt(s),n.replace(Es,""),"important"):e[s]=n}}const Ts=["Webkit","Moz","ms"],pn={};function kl(e,t){const n=pn[t];if(n)return n;let s=Me(t);if(s!=="filter"&&s in e)return pn[t]=s;s=Jt(s);for(let r=0;r{let e=Date.now,t=!1;if(typeof window!="undefined"){Date.now()>document.createEvent("Event").timeStamp&&(e=()=>performance.now());const n=navigator.userAgent.match(/firefox\/(\d+)/i);t=!!(n&&Number(n[1])<=53)}return[e,t]})();let Pn=0;const Jl=Promise.resolve(),zl=()=>{Pn=0},Yl=()=>Pn||(Jl.then(zl),Pn=Ir());function Xl(e,t,n,s){e.addEventListener(t,n,s)}function Zl(e,t,n,s){e.removeEventListener(t,n,s)}function Ql(e,t,n,s,r=null){const i=e._vei||(e._vei={}),l=i[t];if(s&&l)l.value=s;else{const[f,u]=Gl(t);if(s){const a=i[t]=eo(s,r);Xl(e,f,a,u)}else l&&(Zl(e,f,l,u),i[t]=void 0)}}const Fs=/(?:Once|Passive|Capture)$/;function Gl(e){let t;if(Fs.test(e)){t={};let n;for(;n=e.match(Fs);)e=e.slice(0,e.length-n[0].length),t[n[0].toLowerCase()]=!0}return[lt(e.slice(2)),t]}function eo(e,t){const n=s=>{const r=s.timeStamp||Ir();(Vl||r>=n.attached-1)&&ye(to(s,n.value),t,5,[s])};return n.value=e,n.attached=Yl(),n}function to(e,t){if(R(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Ms=/^on[a-z]/,no=(e,t,n,s,r=!1,i,l,f,u)=>{t==="class"?Dl(e,s,r):t==="style"?Kl(e,n,s):At(t)?Rn(t)||Ql(e,t,n,s,l):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):so(e,t,s,r))?ql(e,t,s,i,l,f,u):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Wl(e,t,s,r))};function so(e,t,n,s){return s?!!(t==="innerHTML"||t==="textContent"||t in e&&Ms.test(t)&&L(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||Ms.test(t)&&ie(n)?!1:t in e}const ro={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};qi.props;const Eo={beforeMount(e,{value:t},{transition:n}){e._vod=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):at(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:s}){!t!=!n&&(s?t?(s.beforeEnter(e),at(e,!0),s.enter(e)):s.leave(e,()=>{at(e,!1)}):at(e,t))},beforeUnmount(e,{value:t}){at(e,t)}};function at(e,t){e.style.display=t?e._vod:"none"}const io=oe({patchProp:no},$l);let gn,Os=!1;function lo(){return gn=Os?gn:ml(io),Os=!0,gn}const To=(...e)=>{const t=lo().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=oo(s);if(r)return n(r,!0,r instanceof SVGElement)},t};function oo(e){return ie(e)?document.querySelector(e):e}var Ao=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n};export{te as A,Il as B,ur as C,re as D,go as E,de as F,Eo as G,Co as H,Qi as I,mo as J,po as K,Li as L,To as M,bo as N,Ao as _,qs as a,on as b,Bl as c,Vi as d,Cr as e,_o as f,Ar as g,wo as h,cn as i,yo as j,Fr as k,co as l,zs as m,Pi as n,fr as o,Er as p,Al as q,Kn as r,uo as s,fo as t,wi as u,ao as v,ho as w,un as x,Nn as y,xo as z}; diff --git a/assets/style.cbedf401.css b/assets/style.cbedf401.css new file mode 100644 index 00000000..f269d6fd --- /dev/null +++ b/assets/style.cbedf401.css @@ -0,0 +1 @@ +:root{--c-white: #ffffff;--c-white-dark: #f8f8f8;--c-black: #000000;--c-divider-light: rgba(60, 60, 67, .12);--c-divider-dark: rgba(84, 84, 88, .48);--c-text-light-1: #2c3e50;--c-text-light-2: #476582;--c-text-light-3: #90a4b7;--c-brand: #3eaf7c;--c-brand-light: #4abf8a;--font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;--font-family-mono: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;--z-index-navbar: 10;--z-index-sidebar: 6;--shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16);--header-height: 3.6rem;--c-divider: var(--c-divider-light);--c-text: var(--c-text-light-1);--c-text-light: var(--c-text-light-2);--c-text-lighter: var(--c-text-light-3);--c-bg: var(--c-white);--c-bg-accent: var(--c-white-dark);--code-line-height: 24px;--code-font-family: var(--font-family-mono);--code-font-size: 14px;--code-inline-bg-color: rgba(27, 31, 35, .05);--code-bg-color: #282c34}h1,h2,h3,h4,h5,h6{margin:0;line-height:1.25}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:1.4;font-family:var(--font-family-base);font-size:16px;font-weight:400;color:var(--c-text);background-color:var(--c-bg);direction:ltr;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6,strong,b{font-weight:600}h1:hover .header-anchor,h1:focus .header-anchor,h2:hover .header-anchor,h2:focus .header-anchor,h3:hover .header-anchor,h3:focus .header-anchor,h4:hover .header-anchor,h4:focus .header-anchor,h5:hover .header-anchor,h5:focus .header-anchor,h6:hover .header-anchor,h6:focus .header-anchor{opacity:1}h1{margin-top:1.5rem;font-size:1.9rem}@media screen and (min-width: 420px){h1{font-size:2.2rem}}h2{margin-top:2.25rem;margin-bottom:1.25rem;border-bottom:1px solid var(--c-divider);padding-bottom:.3rem;line-height:1.25;font-size:1.65rem}h2+h3{margin-top:1.5rem}h3{margin-top:2rem;font-size:1.35rem}h4{font-size:1.15rem}p,ol,ul{margin:1rem 0;line-height:1.7}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}a{text-decoration:none;color:var(--c-brand)}a:hover{text-decoration:underline}a.header-anchor{float:left;margin-top:.125em;margin-left:-.87em;padding-right:.23em;font-size:.85em;opacity:0}a.header-anchor:hover,a.header-anchor:focus{text-decoration:none}figure{margin:0}img{max-width:100%}ul,ol{padding-left:1.25em}li>ul,li>ol{margin:0}table{display:block;border-collapse:collapse;margin:1rem 0;overflow-x:auto}tr{border-top:1px solid #dfe2e5}tr:nth-child(2n){background-color:#f6f8fa}th,td{border:1px solid #dfe2e5;padding:.6em 1em}blockquote{margin:1rem 0;border-left:.2rem solid #dfe2e5;padding:.25rem 0 .25rem 1rem;font-size:1rem;color:#999}blockquote>p{margin:0}form{margin:0}.theme.sidebar-open .sidebar-mask{display:block}.theme.no-navbar>h1,.theme.no-navbar>h2,.theme.no-navbar>h3,.theme.no-navbar>h4,.theme.no-navbar>h5,.theme.no-navbar>h6{margin-top:1.5rem;padding-top:0}.theme.no-navbar aside{top:0}@media screen and (min-width: 720px){.theme.no-sidebar aside{display:none}.theme.no-sidebar main{margin-left:0}}.sidebar-mask{position:fixed;z-index:2;display:none;width:100vw;height:100vh}code{margin:0;border-radius:3px;padding:.25rem .5rem;font-family:var(--code-font-family);font-size:.85em;color:var(--c-text-light);background-color:var(--code-inline-bg-color)}code .token.deleted{color:#ec5975}code .token.inserted{color:var(--c-brand)}div[class*=language-]{position:relative;margin:1rem -1.5rem;background-color:var(--code-bg-color);overflow-x:auto}li>div[class*=language-]{border-radius:6px 0 0 6px;margin:1rem -1.5rem 1rem -1.25rem}@media (min-width: 420px){div[class*=language-]{margin:1rem 0;border-radius:6px}li>div[class*=language-]{margin:1rem 0 1rem 0rem;border-radius:6px}}[class*=language-] pre,[class*=language-] code{text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}[class*=language-] pre{position:relative;z-index:1;margin:0;padding:1.25rem 1.5rem;background:transparent;overflow-x:auto}[class*=language-] code{padding:0;line-height:var(--code-line-height);font-size:var(--code-font-size);color:#eee}.highlight-lines{position:absolute;top:0;bottom:0;left:0;padding:1.25rem 0;width:100%;line-height:var(--code-line-height);font-family:var(--code-font-family);font-size:var(--code-font-size);user-select:none;overflow:hidden}.highlight-lines .highlighted{background-color:#000000a8}div[class*=language-].line-numbers-mode{padding-left:3.5rem}.line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid rgba(0,0,0,.5);padding:1.25rem 0;width:3.5rem;text-align:center;line-height:var(--code-line-height);font-family:var(--code-font-family);font-size:var(--code-font-size);color:#888}[class*=language-]:before{position:absolute;top:.6em;right:1em;z-index:2;font-size:.8rem;color:#888}[class~=language-html]:before,[class~=language-markup]:before{content:"html"}[class~=language-md]:before,[class~=language-markdown]:before{content:"md"}[class~=language-css]:before{content:"css"}[class~=language-sass]:before{content:"sass"}[class~=language-scss]:before{content:"scss"}[class~=language-less]:before{content:"less"}[class~=language-stylus]:before{content:"styl"}[class~=language-js]:before,[class~=language-javascript]:before{content:"js"}[class~=language-ts]:before,[class~=language-typescript]:before{content:"ts"}[class~=language-json]:before{content:"json"}[class~=language-rb]:before,[class~=language-ruby]:before{content:"rb"}[class~=language-py]:before,[class~=language-python]:before{content:"py"}[class~=language-sh]:before,[class~=language-bash]:before{content:"sh"}[class~=language-php]:before{content:"php"}[class~=language-go]:before{content:"go"}[class~=language-rust]:before{content:"rust"}[class~=language-java]:before{content:"java"}[class~=language-c]:before{content:"c"}[class~=language-yaml]:before{content:"yaml"}[class~=language-dockerfile]:before{content:"dockerfile"}.token.comment,.token.block-comment,.token.prolog,.token.doctype,.token.cdata{color:#999}.token.punctuation{color:#ccc}.token.tag,.token.attr-name,.token.namespace,.token.deleted{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.number,.token.function{color:#f08d49}.token.property,.token.class-name,.token.constant,.token.symbol{color:#f8c555}.token.selector,.token.important,.token.atrule,.token.keyword,.token.builtin{color:#cc99cd}.token.string,.token.char,.token.attr-value,.token.regex,.token.variable{color:#7ec699}.token.operator,.token.entity,.token.url{color:#67cdcc}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}.custom-block.tip,.custom-block.warning,.custom-block.danger{margin:1rem 0;border-left:.5rem solid;padding:.1rem 1.5rem;overflow-x:auto}.custom-block.tip{background-color:#f3f5f7;border-color:var(--c-brand)}.custom-block.warning{border-color:#e7c000;color:#6b5900;background-color:#ffe5644d}.custom-block.warning .custom-block-title{color:#b29400}.custom-block.warning a{color:var(--c-text)}.custom-block.danger{border-color:#c00;color:#4d0000;background-color:#ffe6e6}.custom-block.danger .custom-block-title{color:#900}.custom-block.danger a{color:var(--c-text)}.custom-block.details{position:relative;display:block;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:#eee}.custom-block.details h4{margin-top:0}.custom-block.details figure:last-child,.custom-block.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-block.details summary{outline:none;cursor:pointer}.custom-block-title{margin-bottom:-.4rem;font-weight:600}.sidebar-links{margin:0;padding:0;list-style:none}.sidebar-link-item{display:block;margin:0;border-left:.25rem solid transparent;color:var(--c-text)}a.sidebar-link-item:hover{text-decoration:none;color:var(--c-brand)}a.sidebar-link-item.active{color:var(--c-brand)}.sidebar>.sidebar-links{padding:.75rem 0 5rem}@media (min-width: 720px){.sidebar>.sidebar-links{padding:1.5rem 0}}.sidebar>.sidebar-links>.sidebar-link+.sidebar-link{padding-top:.5rem}@media (min-width: 720px){.sidebar>.sidebar-links>.sidebar-link+.sidebar-link{padding-top:1.25rem}}.sidebar>.sidebar-links>.sidebar-link>.sidebar-link-item{padding:.35rem 1.5rem .35rem 1.25rem;font-size:1.1rem;font-weight:700}.sidebar>.sidebar-links>.sidebar-link>a.sidebar-link-item.active{border-left-color:var(--c-brand);font-weight:600}.sidebar>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-link-item{display:block;padding:.35rem 1.5rem .35rem 2rem;line-height:1.4;font-size:1rem;font-weight:400}.sidebar>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>a.sidebar-link-item.active{border-left-color:var(--c-brand);font-weight:600}.sidebar>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-link-item{display:block;padding:.3rem 1.5rem .3rem 3rem;line-height:1.4;font-size:.9rem;font-weight:400}.sidebar>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-links>.sidebar-link>.sidebar-link-item{display:block;padding:.3rem 1.5rem .3rem 4rem;line-height:1.4;font-size:.9rem;font-weight:400}.debug[data-v-1be840de]{box-sizing:border-box;position:fixed;right:8px;bottom:8px;z-index:9999;border-radius:4px;width:74px;height:32px;color:#eee;overflow:hidden;cursor:pointer;background-color:#000000d9;transition:all .15s ease}.debug[data-v-1be840de]:hover{background-color:#000000bf}.debug.open[data-v-1be840de]{right:0;bottom:0;width:100%;height:100%;margin-top:0;border-radius:0;padding:0;overflow:scroll}@media (min-width: 512px){.debug.open[data-v-1be840de]{width:512px}}.debug.open[data-v-1be840de]:hover{background-color:#000000d9}.title[data-v-1be840de]{margin:0;padding:6px 16px;line-height:20px;font-size:13px}.block[data-v-1be840de]{margin:2px 0 0;border-top:1px solid rgba(255,255,255,.16);padding:8px 16px;font-family:Hack,monospace;font-size:13px}.block+.block[data-v-1be840de]{margin-top:8px}.nav-bar-title[data-v-3e3fd8b1]{font-size:1.3rem;font-weight:600;color:var(--c-text)}.nav-bar-title[data-v-3e3fd8b1]:hover{text-decoration:none}.logo[data-v-3e3fd8b1]{margin-right:.75rem;height:1.3rem;vertical-align:bottom}.icon.outbound{position:relative;top:-1px;display:inline-block;vertical-align:middle;color:var(--c-text-lighter)}.item[data-v-c272f228]{display:block;padding:0 1.5rem;line-height:36px;font-size:1rem;font-weight:600;color:var(--c-text);white-space:nowrap}.item[data-v-c272f228]:hover,.item.active[data-v-c272f228]{text-decoration:none;color:var(--c-brand)}.item.external[data-v-c272f228]:hover{border-bottom-color:transparent;color:var(--c-text)}@media (min-width: 720px){.item[data-v-c272f228]{border-bottom:2px solid transparent;padding:0;line-height:24px;font-size:.9rem;font-weight:500}.item[data-v-c272f228]:hover,.item.active[data-v-c272f228]{border-bottom-color:var(--c-brand);color:var(--c-text)}}.item[data-v-7b16fcd4]{display:block;padding:0 1.5rem 0 2.5rem;line-height:32px;font-size:.9rem;font-weight:500;color:var(--c-text);white-space:nowrap}@media (min-width: 720px){.item[data-v-7b16fcd4]{padding:0 24px 0 12px;line-height:32px;font-size:.85rem;font-weight:500;color:var(--c-text);white-space:nowrap}.item.active .arrow[data-v-7b16fcd4]{opacity:1}}.item[data-v-7b16fcd4]:hover,.item.active[data-v-7b16fcd4]{text-decoration:none;color:var(--c-brand)}.item.external[data-v-7b16fcd4]:hover{border-bottom-color:transparent;color:var(--c-text)}@media (min-width: 720px){.arrow[data-v-7b16fcd4]{display:inline-block;margin-right:8px;border-top:6px solid #ccc;border-right:4px solid transparent;border-bottom:0;border-left:4px solid transparent;vertical-align:middle;opacity:0;transform:translateY(-2px) rotate(-90deg)}}.nav-dropdown-link[data-v-312de885]{position:relative;height:36px;overflow:hidden;cursor:pointer}@media (min-width: 720px){.nav-dropdown-link[data-v-312de885]{height:auto;overflow:visible}.nav-dropdown-link:hover .dialog[data-v-312de885]{display:block}}.nav-dropdown-link.open[data-v-312de885]{height:auto}.button[data-v-312de885]{display:block;border:0;padding:0 1.5rem;width:100%;text-align:left;line-height:36px;font-family:var(--font-family-base);font-size:1rem;font-weight:600;color:var(--c-text);white-space:nowrap;background-color:transparent;cursor:pointer}.button[data-v-312de885]:focus{outline:0}@media (min-width: 720px){.button[data-v-312de885]{border-bottom:2px solid transparent;padding:0;line-height:24px;font-size:.9rem;font-weight:500}}.button-arrow[data-v-312de885]{display:inline-block;margin-top:-1px;margin-left:8px;border-top:6px solid #ccc;border-right:4px solid transparent;border-bottom:0;border-left:4px solid transparent;vertical-align:middle}.button-arrow.right[data-v-312de885]{transform:rotate(-90deg)}@media (min-width: 720px){.button-arrow.right[data-v-312de885]{transform:rotate(0)}}.dialog[data-v-312de885]{margin:0;padding:0;list-style:none}@media (min-width: 720px){.dialog[data-v-312de885]{display:none;position:absolute;top:26px;right:-8px;border-radius:6px;padding:12px 0;min-width:128px;background-color:var(--c-bg);box-shadow:var(--shadow-3)}}.nav-links[data-v-1e870408]{padding:.75rem 0;border-bottom:1px solid var(--c-divider)}@media (min-width: 720px){.nav-links[data-v-1e870408]{display:flex;padding:6px 0 0;align-items:center;border-bottom:0}.item+.item[data-v-1e870408]{padding-left:24px}}.sidebar-button{position:absolute;top:.6rem;left:1rem;display:none;padding:.6rem;cursor:pointer}.sidebar-button .icon{display:block;width:1.25rem;height:1.25rem}@media screen and (max-width: 719px){.sidebar-button{display:block}}.nav-bar[data-v-e81c9962]{position:fixed;top:0;right:0;left:0;z-index:var(--z-index-navbar);display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--c-divider);padding:.7rem 1.5rem .7rem 4rem;height:var(--header-height);background-color:var(--c-bg)}@media (min-width: 720px){.nav-bar[data-v-e81c9962]{padding:.7rem 1.5rem}}.flex-grow[data-v-e81c9962]{flex-grow:1}.nav[data-v-e81c9962]{display:none}@media (min-width: 720px){.nav[data-v-e81c9962]{display:flex}.navbar__dark-mode[data-v-e81c9962]{display:none}}.nav-icons[data-v-e81c9962]{display:flex;padding:2px 0 0;align-items:center;border-bottom:0;margin-left:12px}.nav-icons .item[data-v-e81c9962]{padding-left:12px}.sidebar[data-v-4668b452]{position:fixed;top:var(--header-height);bottom:0;left:0;z-index:var(--z-index-sidebar);border-right:1px solid var(--c-divider);width:16.4rem;background-color:var(--c-bg);overflow-y:auto;transform:translate(-100%);transition:transform .25s ease}@media (min-width: 720px){.sidebar[data-v-4668b452]{transform:translate(0)}}@media (min-width: 960px){.sidebar[data-v-4668b452]{width:20rem}}.sidebar.open[data-v-4668b452]{transform:translate(0)}.nav[data-v-4668b452]{display:block}@media (min-width: 720px){.nav[data-v-4668b452]{display:none}}.link[data-v-045573c2]{display:inline-block;font-size:1rem;font-weight:500;color:var(--c-text-light)}.link[data-v-045573c2]:hover{text-decoration:none;color:var(--c-brand)}.icon[data-v-045573c2]{margin-left:4px}.last-updated[data-v-03e55a27]{display:inline-block;margin:0;line-height:1.4;font-size:.9rem;color:var(--c-text-light)}@media (min-width: 960px){.last-updated[data-v-03e55a27]{font-size:1rem}}.prefix[data-v-03e55a27]{display:inline-block;font-weight:500}.datetime[data-v-03e55a27]{display:inline-block;margin-left:6px;font-weight:400}.page-footer[data-v-22e60b1a]{padding-top:1rem;padding-bottom:1rem;overflow:auto}@media (min-width: 960px){.page-footer[data-v-22e60b1a]{display:flex;justify-content:space-between;align-items:center}}.updated[data-v-22e60b1a]{padding-top:4px}@media (min-width: 960px){.updated[data-v-22e60b1a]{padding-top:0}}.next-and-prev-link[data-v-0facf926]{padding-top:1rem}.container[data-v-0facf926]{display:flex;justify-content:space-between;border-top:1px solid var(--c-divider);padding-top:1rem}.prev[data-v-0facf926],.next[data-v-0facf926]{display:flex;flex-shrink:0;width:50%}.prev[data-v-0facf926]{justify-content:flex-start;padding-right:12px}.next[data-v-0facf926]{justify-content:flex-end;padding-left:12px}.link[data-v-0facf926]{display:inline-flex;align-items:center;max-width:100%;font-size:1rem;font-weight:500}.text[data-v-0facf926]{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.icon[data-v-0facf926]{display:block;flex-shrink:0;width:16px;height:16px;fill:var(--c-text);transform:translateY(1px)}.icon-prev[data-v-0facf926]{margin-right:8px}.icon-next[data-v-0facf926]{margin-left:8px}.page[data-v-7abc59e6]{padding-top:var(--header-height)}@media (min-width: 720px){.page[data-v-7abc59e6]{margin-left:16.4rem}}@media (min-width: 960px){.page[data-v-7abc59e6]{margin-left:20rem}}.container[data-v-7abc59e6]{margin:0 auto;padding:0 1.5rem 4rem;padding:.025rem 0rem 2rem 0;width:calc(100% - var(--slug-width))}.content[data-v-7abc59e6]{padding-bottom:1.5rem}@media (max-width: 420px){.content[data-v-7abc59e6]{clear:both}}#ads-container{margin:0 auto}@media (min-width: 420px){#ads-container{position:relative;right:0;float:right;margin:-8px -8px 24px 24px;width:146px}}@media (max-width: 420px){#ads-container{height:105px;margin:1.75rem 0}}@media (min-width: 1400px){#ads-container{position:fixed;right:8px;bottom:8px}}.border{border-width:1px}.flex{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex}.inline-flex{display:-webkit-inline-box;display:-ms-inline-flexbox;display:-webkit-inline-flex;display:inline-flex}.table{display:table}.justify-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center}.h-full{height:100%}.text-color-base{font-size:1rem;line-height:1.5rem}.m-3{margin:.75rem}.m-4{margin:1rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mx-4{margin-left:1rem;margin-right:1rem}.mt-4{margin-top:1rem}.mr-4{margin-right:1rem}.mr-2{margin-right:.5rem}.mb-2{margin-bottom:.5rem}.ml-4{margin-left:1rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-10{padding:2.5rem}.px-10{padding-left:2.5rem;padding-right:2.5rem}.px-4{padding-left:1rem;padding-right:1rem}.tab{-moz-tab-size:4;-o-tab-size:4;tab-size:4}.absolute{position:absolute}.relative{position:relative}.w-full{width:100%}.transform{--tw-translate-x: 0;--tw-translate-y: 0;--tw-translate-z: 0;--tw-rotate: 0;--tw-rotate-x: 0;--tw-rotate-y: 0;--tw-rotate-z: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-scale-z: 1;-webkit-transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) translateZ(var(--tw-translate-z)) rotate(var(--tw-rotate)) rotateX(var(--tw-rotate-x)) rotateY(var(--tw-rotate-y)) rotateZ(var(--tw-rotate-z)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) scaleZ(var(--tw-scale-z));-ms-transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) translateZ(var(--tw-translate-z)) rotate(var(--tw-rotate)) rotateX(var(--tw-rotate-x)) rotateY(var(--tw-rotate-y)) rotateZ(var(--tw-rotate-z)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) scaleZ(var(--tw-scale-z));transform:translate(var(--tw-translate-x)) translateY(var(--tw-translate-y)) translateZ(var(--tw-translate-z)) rotate(var(--tw-rotate)) rotateX(var(--tw-rotate-x)) rotateY(var(--tw-rotate-y)) rotate(var(--tw-rotate-z)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) scaleZ(var(--tw-scale-z))}.transition{-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform,filter,backdrop-filter;-o-transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,-webkit-box-shadow,transform,-webkit-transform,filter,backdrop-filter;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);-o-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition-duration:.15s;-o-transition-duration:.15s;transition-duration:.15s}.duration{-webkit-transition-duration:.15s;-o-transition-duration:.15s;transition-duration:.15s}[duration~="8000"]{-webkit-transition-duration:8s;-o-transition-duration:8s;transition-duration:8s}:root{--c-brand: #4569d4;--c-brand-light: #4f73dd;--c-white-dark: #f8f8f8;--c-black: #111827;--c-black-light: #161f32;--c-black-lighter: #262a44;--c-text-dark-1: #d9e6eb;--c-text-dark-2: #c4dde6;--c-text-dark-3: #abc4cc;--c-brand-text: var(--c-white);--c-bg-accent: var(--c-white-dark);--code-bg-color: var(--c-white-dark);--code-inline-bg-color: var(--c-white-dark);--code-font-family: "dm", source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;--code-font-size: 16px;--slug-width: 10rem;--header-height: 3.6rem;--sidebar-width: 16.4rem}html:not(.light):root{--c-text: var(--c-text-dark-1);--c-text-light: var(--c-text-dark-2);--c-text-lighter: var(--c-text-dark-3);--c-divider: var(--c-divider-dark);--c-bg: var(--c-black);--c-bg-accent: var(--c-black-light);--code-bg-color: var(--c-black-light);--code-inline-bg-color: var(--c-black-light)}html:not(.light) .DocSearch{--docsearch-text-color: var(--c-white-dark);--docsearch-container-background: rgba(9, 10, 17, .8);--docsearch-modal-background: var(--c-black);--docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;--docsearch-searchbox-background: var(--c-black-lighter);--docsearch-searchbox-focus-background: var(--c-black-light);--docsearch-hit-color: var(--c-text-dark-1);--docsearch-hit-active-color: var(--c-brand-text);--docsearch-hit-shadow: none;--docsearch-hit-background: var(--c-black-light);--docsearch-key-gradient: linear-gradient(-26.5deg, #565872, #31355b);--docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 0 2px 2px 0 rgba(3, 4, 9, .3);--docsearch-footer-background: var(--c-black-light);--docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, .5), 0 -4px 8px 0 rgba(0, 0, 0, .2);--docsearch-logo-color: var(--c-white-dark);--docsearch-muted-color: var(--c-text-dark-1)}.home-hero .image{width:100px;height:100px}.nav-bar .logo{height:26px;margin-right:8px}.nav-bar .nav-bar-title{display:flex;align-items:center}.content img{border-radius:10px}.nav-dropdown-link-item .icon{display:none}.action.alt .icon.outbound{color:currentColor}.action .item.item.item{border-color:var(--c-brand);background-color:var(--c-brand)}.action.alt .item.item.item{background-color:transparent;color:var(--c-text);border-color:var(--c-brand);transition:background-color .15s ease-in-out,border-color .15s ease-in-out,color .15s ease-in-out}.action .item.item.item,.action .item.item.item:hover{color:var(--c-brand-text)}html.dark .action.alt .item.item.item{border-color:var(--c-text)}.action.alt .item.item.item:hover{background-color:var(--c-brand-light);border-color:var(--c-brand-light);color:var(--c-brand-text)}.nav-bar.nav-bar{background-color:var(--c-bg)}.custom-block.tip{border-color:var(--c-brand-light);background-color:var(--c-bg-accent)}.carbon-ads{padding:8px}.carbon-ads,.bsa-cpc{background-color:var(--c-bg-accent)!important}html:not(.light) .custom-block.warning{color:var(--c-text)}html:not(.light) .custom-block.warning a{color:var(--c-brand)}body,.nav-bar,.carbon-ads,.bsa-cpc,.custom-block.tip,code,div[class*=language-],.action.alt .item.item{transition:background-color .3s ease-in-out,color .3s ease-in-out}.sidebar.sidebar.sidebar,.DocSearch,.DocSearch-Search-Icon,.DocSearch-Form{transition:transform .25s ease,background-color .3s ease-in-out,color .3s ease-in-out}.DocSearch-Button-Key,.DocSearch-Footer,.DocSearch-Modal{transition:background-color .3s ease-in-out,color .3s ease-in-out,box-shadow .25s ease-in-out}code{font-size:.95em;padding:.175em .35em}input{border:1px solid #d9d9d9;padding:8px 6px;border-radius:4px;color:#000000a6;outline:none}input:focus{border-color:#40a9ff}button{padding:5px 16px;border-radius:2px;color:#000000a6;outline:none;border:1px solid #d9d9d9;cursor:pointer;background:#fff}button:hover{border-color:#40a9ff;color:#40a9ff}::-webkit-input-placeholder,:-moz-placeholder,::-moz-placeholder,:-ms-input-placeholder{color:var(--placeholder-color)}.nav-btn{display:flex;font-size:1.05rem;border:0;outline:none;background:none;color:var(--c-text);opacity:.8;cursor:pointer}.nav-btn:hover{opacity:1}.nav-btn svg{margin:auto}.slugs{position:fixed;top:var(--header-height);right:0;max-height:calc(100% - var(--header-height) - 10rem);width:var(--slug-width);padding:50px 24px 0 0;border-right:1px solid var(--border-color);background-color:#fff;z-index:3;overflow-y:auto}[class*=language-] code{color:inherit}code[class*=language-],pre[class*=language-]{color:#d6deeb;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,code[class*=language-] ::-moz-selection{text-shadow:none;background:rgba(29,59,83,.99)}pre[class*=language-]::selection,pre[class*=language-] ::selection,code[class*=language-]::selection,code[class*=language-] ::selection{text-shadow:none;background:rgba(29,59,83,.99)}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{color:#fff;background:#011627}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.comment,.token.prolog,.token.cdata{color:#637777}.token.punctuation{color:#c792ea}.namespace{color:#b2ccd6}.token.deleted{color:#ef5350}.token.symbol,.token.property{color:#80cbc4}.token.tag,.token.operator,.token.keyword{color:#7fdbca}.token.boolean{color:#ff5874}.token.number{color:#f78c6c}.token.constant,.token.function,.token.builtin,.token.char{color:#82aaff}.token.selector,.token.function,.token.doctype{color:#c792ea}.token.attr-name,.token.inserted,code .token.inserted,.token.string,.token.url,.token.entity,.language-css .token.string,.style .token.string{color:#addb67}.token.class-name,.token.atrule,.token.attr-value{color:#ffcb8b}.token.regex,.token.important,.token.variable{color:#d6deeb}.token.important,.token.bold{font-weight:700}html.dark tr:nth-child(2n){background-color:transparent!important}html.light code[class*=language-],html.light pre[class*=language-]{color:#403f53;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}html.light pre[class*=language-]::-moz-selection,html.light pre[class*=language-] ::-moz-selection,html.light code[class*=language-]::-moz-selection,html.light code[class*=language-] ::-moz-selection{text-shadow:none;background:#fbfbfb}html.light pre[class*=language-]::selection,html.light pre[class*=language-] ::selection,html.light code[class*=language-]::selection,html.light code[class*=language-] ::selection{text-shadow:none;background:#fbfbfb}@media print{html.light code[class*=language-],html.light pre[class*=language-]{text-shadow:none}}html.light pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}html.light :not(pre)>code[class*=language-],html.light pre[class*=language-]{color:#fff;background:#fbfbfb}html.light :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}html.light .token.comment,html.light .token.prolog,html.light .token.cdata{color:#989fb1}html.light .token.punctuation{color:#994cc3}html.light .namespace{color:#0c969b}html.light code .token.deleted{color:#ec5975}html.light .token.symbol,html.light .token.operator,html.light .token.keyword,html.light .token.property{color:#0c969b}html.light .token.tag{color:#994cc3}html.light .token.boolean{color:#bc5454}html.light .token.number{color:#aa0982}html.light .token.constant,html.light .token.builtin,html.light .token.string,html.light .token.url,html.light .token.entity,html.light .language-css .token.string,html.light .style .token.string,html.light .token.char{color:#4876d6}html.light .token.selector,html.light .token.function,html.light .token.doctype{color:#994cc3}html.light .token.attr-name,html.light .token.inserted{color:#4876d6}html.light .token.class-name,html.light .token.atrule,html.light .token.attr-value{color:#111}html.light .token.regex,html.light .token.important,html.light .token.variable{color:#c96765}html.light .token.important,html.light .token.bold{font-weight:700}.home-hero[data-v-e065f044]{margin:2.5rem 0 2.75rem;padding:0 1.5rem;text-align:center}@media (min-width: 420px){.home-hero[data-v-e065f044]{margin:3.5rem 0}}@media (min-width: 720px){.home-hero[data-v-e065f044]{margin:4rem 0 4.25rem}}.figure[data-v-e065f044]{padding:0 1.5rem}.image[data-v-e065f044]{display:block;margin:0 auto;width:auto;max-width:100%;max-height:280px}.title[data-v-e065f044]{margin-top:1.5rem;font-size:2rem}@media (min-width: 420px){.title[data-v-e065f044]{font-size:3rem}}@media (min-width: 720px){.title[data-v-e065f044]{margin-top:2rem}}.description[data-v-e065f044]{margin:0;margin-top:.25rem;line-height:1.3;font-size:1.2rem;color:var(--c-text-light)}@media (min-width: 420px){.description[data-v-e065f044]{line-height:1.2;font-size:1.6rem}}.action[data-v-e065f044]{margin-top:1.5rem;display:inline-block}.action.alt[data-v-e065f044]{margin-left:1.5rem}@media (min-width: 420px){.action[data-v-e065f044]{margin-top:2rem;display:inline-block}}.action[data-v-e065f044] .item{display:inline-block;border-radius:6px;padding:0 20px;line-height:44px;font-size:1rem;font-weight:500;color:var(--c-bg);background-color:var(--c-brand);border:2px solid var(--c-brand);transition:background-color .1s ease}.action.alt[data-v-e065f044] .item{background-color:var(--c-bg);color:var(--c-brand)}.action[data-v-e065f044] .item:hover{text-decoration:none;color:var(--c-bg);background-color:var(--c-brand-light)}@media (min-width: 420px){.action[data-v-e065f044] .item{padding:0 24px;line-height:52px;font-size:1.2rem;font-weight:500}}.home-features[data-v-9c9c2344]{margin:0 auto;padding:2.5rem 0 2.75rem;max-width:960px}.home-hero+.home-features[data-v-9c9c2344]{padding-top:0}@media (min-width: 420px){.home-features[data-v-9c9c2344]{padding:3.25rem 0 3.5rem}.home-hero+.home-features[data-v-9c9c2344]{padding-top:0}}@media (min-width: 720px){.home-features[data-v-9c9c2344]{padding-right:1.5rem;padding-left:1.5rem}}.wrapper[data-v-9c9c2344]{padding:0 1.5rem}.home-hero+.home-features .wrapper[data-v-9c9c2344]{border-top:1px solid var(--c-divider);padding-top:2.5rem}@media (min-width: 420px){.home-hero+.home-features .wrapper[data-v-9c9c2344]{padding-top:3.25rem}}@media (min-width: 720px){.wrapper[data-v-9c9c2344]{padding-right:0;padding-left:0}}.container[data-v-9c9c2344]{margin:0 auto;max-width:392px}@media (min-width: 720px){.container[data-v-9c9c2344]{max-width:960px}}.features[data-v-9c9c2344]{display:flex;flex-wrap:wrap;margin:-20px -24px}.feature[data-v-9c9c2344]{flex-shrink:0;padding:20px 24px;width:100%}@media (min-width: 720px){.feature[data-v-9c9c2344]{width:calc(100% / 3)}}.title[data-v-9c9c2344]{margin:0;border-bottom:0;line-height:1.4;font-size:1.25rem;font-weight:500}@media (min-width: 420px){.title[data-v-9c9c2344]{font-size:1.4rem}}.details[data-v-9c9c2344]{margin:0;line-height:1.6;font-size:1rem;color:var(--c-text-light)}.title+.details[data-v-9c9c2344]{padding-top:.25rem}.footer[data-v-44324124]{margin:0 auto;max-width:960px}@media (min-width: 720px){.footer[data-v-44324124]{padding:0 1.5rem}}.container[data-v-44324124]{padding:2rem 1.5rem 2.25rem}.home-hero+.footer .container[data-v-44324124],.home-features+.footer .container[data-v-44324124],.home-content+.footer .container[data-v-44324124]{border-top:1px solid var(--c-divider)}@media (min-width: 420px){.container[data-v-44324124]{padding:3rem 1.5rem 3.25rem}}.text[data-v-44324124]{margin:0;text-align:center;line-height:1.4;font-size:.9rem;color:var(--c-text-light)}.home[data-v-1fd43058]{padding-top:var(--header-height)}.home-content[data-v-1fd43058]{max-width:960px;margin:0 auto;padding:0 1.5rem}@media (max-width: 720px){.home-content[data-v-1fd43058]{max-width:392px;padding:0}} diff --git a/components/auth.html b/components/auth.html new file mode 100644 index 00000000..ff006546 --- /dev/null +++ b/components/auth.html @@ -0,0 +1,45 @@ + + + + + + Authority | Vben Admin + + + + + + + + + + + + + + + + +

Authority

用于项目权限的组件,一般用于按钮级等细粒度权限管理

Usage

<template>
+  <div>
+    <Authority :value="RoleEnum.ADMIN">
+      <a-button type="primary" block> 只有admin角色可见 </a-button>
+    </Authority>
+  </div>
+</template>
+<script>
+  import { Authority } from '/@/components/Authority';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { Authority },
+  });
+</script>
+

Props

属性类型默认值说明
valueRoleEnum,RoleEnum[],string,string[]-角色信息或者权限编码。会自动区分权限模式
+ + + + \ No newline at end of file diff --git a/components/basic.html b/components/basic.html new file mode 100644 index 00000000..72cce155 --- /dev/null +++ b/components/basic.html @@ -0,0 +1,69 @@ + + + + + + Basic 基础组件 | Vben Admin + + + + + + + + + + + + + + + + +

Basic 基础组件

一些比较基础的通用组件使用方式

BasicTitle

用于显示标题,可以显示帮助按钮及文本

Usage

<template>
+  <div>
+    <BasicTitle helpMessage="提示1">标题</BasicTitle>
+    <BasicTitle :helpMessage="['提示1', '提示2']">标题</BasicTitle>
+  </div>
+</template>
+<script>
+  import { BasicTitle } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicTitle },
+  });
+</script>
+

Props

属性类型默认值说明
helpMessagestring|string[]-标题右侧帮助按钮信息
spanbooleanfalse是否显示标题左侧蓝色色块
normalbooleanfalse将文字默认化,不加粗

Slots

名称说明
default标题文本

BasicArrow

带动画的箭头组件

Usage

<template>
+  <div>
+    <BasicArrow :expand="false" />
+  </div>
+</template>
+<script>
+  import { BasicArrow } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicArrow },
+  });
+</script>
+

Props

属性类型默认值说明
expandbooleanfalse箭头展开状态
topbooleanfalse箭头默认向上
bottombooleanfalse箭头默认向下
insetbooleanfalse取消 padding/margin,用于内嵌

BasicHelp

帮助按钮组件

Usage

<template>
+  <div>
+    <BasicHelp :text="['提示1', '提示2']" />
+    <BasicHelp text="提示" />
+  </div>
+</template>
+<script>
+  import { BasicHelp } from '/@/components/Basic/index';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { BasicHelp },
+  });
+</script>
+

Props

属性类型默认值可选值说明
fontSizestring14px-字体大小
colorstring#fff-颜色
textstring|string[]--文本列表
showIndexbooleantrue-是否显示序号,在 text 为 string[]情况下生效
maxWidthstring600px-最大宽度
placementstringright-显示方向,参考 Tooltip 组件

Slots

名称说明
default默认图标
+ + + + \ No newline at end of file diff --git a/components/click-out-side.html b/components/click-out-side.html new file mode 100644 index 00000000..890f6edd --- /dev/null +++ b/components/click-out-side.html @@ -0,0 +1,53 @@ + + + + + + ClickOutSide | Vben Admin + + + + + + + + + + + + + + + + +

ClickOutSide

用于监听包裹的元素点击外部触发事件

Usage

<template>
+  <div>
+    <ClickOutSide @clickOutside="() => (showRef = false)">
+      <div @click="() => (showRef = true)">
+        {{ showRef ? '鼠标点击那部(点击边框外可以恢复)' : '点击该区域状态(初始状态)' }}
+      </div>
+    </ClickOutSide>
+  </div>
+</template>
+<script>
+  import { defineComponent, ref } from 'vue';
+  import { ClickOutSide } from '/@/components/ClickOutSide/';
+  export default defineComponent({
+    components: { ClickOutSide },
+    setup() {
+      const showRef = ref(false);
+      return {
+        showRef,
+      };
+    },
+  });
+</script>
+

Events

事件回调参数说明
clickOutside()=>void点击包裹元素外部区域触发

Slots

名称说明
default被包裹的元素
+ + + + \ No newline at end of file diff --git a/components/code-editor.html b/components/code-editor.html new file mode 100644 index 00000000..07385cd5 --- /dev/null +++ b/components/code-editor.html @@ -0,0 +1,44 @@ + + + + + + CodeEditor | Vben Admin + + + + + + + + + + + + + + + + +

CodeEditor

代码编辑器

Usage

<template>
+  <CodeEditor v-model:value="value" :mode="modeValue" />
+</template>
+<script>
+  import { defineComponent, ref } from 'vue';
+  export default defineComponent({
+    components: { CodeEditor },
+    setup() {
+      const modeValue = ref('application/json');
+      return { value, modeValue };
+    },
+  });
+</script>
+

Props

属性类型默认值可选值说明
value(v-model:value)any--绑定值
modestringapplication/json'application/json','htmlmixed','javascript'代码类型
readonlyboolean--是否只读
+ + + + \ No newline at end of file diff --git a/components/collapse-container.html b/components/collapse-container.html new file mode 100644 index 00000000..ebc8782f --- /dev/null +++ b/components/collapse-container.html @@ -0,0 +1,46 @@ + + + + + + CollapseContainer | Vben Admin + + + + + + + + + + + + + + + + +

CollapseContainer

区域折叠卡片容器

Usage

<template>
+  <div>
+    <CollapseContainer> content </CollapseContainer>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CollapseContainer } from '/@/components/Container/index';
+
+  export default defineComponent({
+    components: {
+      CollapseContainer,
+    },
+  });
+</script>
+

Props

属性类型默认值可选值说明
titlestring--标题
canExpanbooleantrue-是否可以展开,为true显示折叠按钮
helpMessagestring[],string--标题右侧温馨提醒
triggerWindowResizebooleanfalse-展开收缩的时候是否触发 window.resize
loadingbooleanfalse-显示加载骨架屏
lazyTimenumber0-延迟加载时间

Slots

名称说明
title自定义标题
action自定义右侧操作按钮
default默认区域
footer自定义底部区域
+ + + + \ No newline at end of file diff --git a/components/count-down.html b/components/count-down.html new file mode 100644 index 00000000..9f94ba8a --- /dev/null +++ b/components/count-down.html @@ -0,0 +1,53 @@ + + + + + + CountDown | Vben Admin + + + + + + + + + + + + + + + + +

CountDown

倒计时组件

CountButton

倒计时按钮组件

Usage

<template>
+  <CountButton />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountButton } from '/@/components/CountDown';
+
+  export default defineComponent({
+    components: { CountButton },
+  });
+</script>
+

Props

属性类型默认值可选值说明
valueany--绑定值
countnumber60-倒计时时间
beforeStartFunc()=>promise--倒计时之前执行的函数,返回 true 才会开始执行

CountDownInput

倒计时输入框按钮组件

Usage

<template>
+  <CountdownInput />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountdownInput } from '/@/components/CountDown';
+
+  export default defineComponent({
+    components: { CountdownInput },
+  });
+</script>
+

Props

属性类型默认值可选值说明
valueany--绑定值
sizestring'default', 'large', 'small'-输入框即按钮大小
countnumber60-倒计时时间
sendCodeApi()=>promise--倒计时之前执行的函数,返回 true 才会开始执行
+ + + + \ No newline at end of file diff --git a/components/count-to.html b/components/count-to.html new file mode 100644 index 00000000..c32658c4 --- /dev/null +++ b/components/count-to.html @@ -0,0 +1,44 @@ + + + + + + CountTo | Vben Admin + + + + + + + + + + + + + + + + +

CountTo

数字动画组件

该组件对 vue-countTo 进行了重构,改造成适配 vue3 语法的组件。

Usage

<template>
+  <CountTo prefix="$" :color="'#409EFF'" :startVal="1" :endVal="200000" :duration="8000" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { CountTo } from '/@/components/CountTo/index';
+
+  export default defineComponent({
+    components: {
+      CountTo,
+    },
+  });
+</script>
+

Props

属性类型默认值说明
startValnumber0起始值
endValnumber2021结束值
durationnumber1500动画持续时间
autoplaybooleantrue自动执行
prefixstring-前缀
suffixstring-后缀
separatorstring,分隔符
colorstring-字体颜色
useEasingbooleantrue是否开启动画
transitionstringlinear动画效果
decimalsnumber0保留小数点位数

Methods

名称回调参数说明
start()=>void开始执行动画
reset()=>void重置
+ + + + \ No newline at end of file diff --git a/components/cropper.html b/components/cropper.html new file mode 100644 index 00000000..42095864 --- /dev/null +++ b/components/cropper.html @@ -0,0 +1,97 @@ + + + + + + Cropper | Vben Admin + + + + + + + + + + + + + + + + +

Cropper

图片裁剪组件

CropperImage

图片裁剪组件

Usage

<template>
+  <CropperImage ref="refCropper" :src="img" @cropend="handleCropend" style="width: 40vw" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { CropperImage } from '/@/components/Cropper';
+  import img from '/@/assets/images/header.jpg';
+
+  export default defineComponent({
+    components: {
+      CropperImage,
+    },
+    setup() {
+      const info = ref('');
+      const cropperImg = ref('');
+
+      function handleCropend({ imgBase64, imgInfo }) {
+        info.value = imgInfo;
+        cropperImg.value = imgBase64;
+      }
+
+      return {
+        img,
+        info,
+        cropperImg,
+        handleCropend,
+      };
+    },
+  });
+</script>
+

Props

属性类型默认值说明
srcstring-图片源
altstring-图片 alt
circledbooleanfalse圆形裁剪框
realTimePreviewbooleantrue实时触发预览
heightstring360px高度
crossoriginstring-crossorigin
imageStyleobject``图片样式
optionsobjectDefaultOptionscorpperjs 配置项

DefaultOptions

{
+  aspectRatio: 1,
+  zoomable: true,
+  zoomOnTouch: true,
+  zoomOnWheel: true,
+  cropBoxMovable: true,
+  cropBoxResizable: true,
+  toggleDragModeOnDblclick: true,
+  autoCrop: true,
+  background: true,
+  highlight: true,
+  center: true,
+  responsive: true,
+  restore: true,
+  checkCrossOrigin: true,
+  checkOrientation: true,
+  scalable: true,
+  modal: true,
+  guides: true,
+  movable: true,
+  rotatable: true,
+}
+

CropperAvatar

头像裁剪组件

Usage

<template>
+  <CropperAvatar :uploadApi="uploadApi" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { CropperAvatar } from '/@/components/Cropper';
+  import { uploadApi } from '/@/api/sys/upload';
+
+  export default defineComponent({
+    components: {
+      CropperAvatar,
+    },
+  });
+</script>
+

Props

属性类型默认值说明版本
widthstring,number200px图片源
uploadApi({ file: Blob, name: string }) => Promise<void>-图片上传接口
valueString-当前头像地址(v-model)2.5.3
showBtnBooleantrue是否显示按钮2.5.3
btnTextString-按钮文案2.5.3
btnPropsButtonProps-按钮的其它属性2.5.3

Events

名称参数说明版本
changevalue: String当头像上传完成时触发2.5.3

Methods

名称定义说明版本
openModal()=>void打开上传Modal2.5.3
closeModal()=>void关闭上传Modal2.5.3
+ + + + \ No newline at end of file diff --git a/components/desc.html b/components/desc.html new file mode 100644 index 00000000..a72be79a --- /dev/null +++ b/components/desc.html @@ -0,0 +1,96 @@ + + + + + + Description 详情组件 | Vben Admin + + + + + + + + + + + + + + + + +

Description 详情组件

antv 的 Descriptions 组件进行封装

Usage

<template>
+  <div class="p-4">
+    <Description
+      title="基础示例"
+      :collapseOptions="{ canExpand: true, helpMessage: 'help me' }"
+      :column="3"
+      :data="mockData"
+      :schema="schema"
+    />
+    <Description @register="register" class="mt-4" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { Description, DescItem, useDescription } from '/@/components/Description/index';
+  const mockData: any = {
+    username: 'test',
+    nickName: 'VB',
+    age: 123,
+    phone: '15695909xxx',
+    email: '190848757@qq.com',
+    addr: '厦门市思明区',
+    sex: '男',
+    certy: '3504256199xxxxxxxxx',
+    tag: 'orange',
+  };
+  const schema: DescItem[] = [
+    {
+      field: 'username',
+      label: '用户名',
+    },
+    {
+      field: 'nickName',
+      label: '昵称',
+      render: (curVal, data) => {
+        return `${data.username}-${curVal}`;
+      },
+    },
+    {
+      field: 'phone',
+      label: '联系电话',
+    },
+    {
+      field: 'email',
+      label: '邮箱',
+    },
+    {
+      field: 'addr',
+      label: '地址',
+    },
+  ];
+  export default defineComponent({
+    components: { Description, Alert },
+    setup() {
+      const [register] = useDescription({
+        title: 'useDescription',
+        data: mockData,
+        schema: schema,
+      });
+      return { mockData, schema, register };
+    },
+  });
+</script>
+

useDescription

参考以上示例

const [register] = useDescription(Props);
+

Props

温馨提醒

除以下参数外,官方文档内的 props 也都支持,具体可以参考 antv Description

属性类型默认值可选值说明
titlestring--标题
sizestringsmall-大小
borderedbooleantrue-是否展示边框
columnNumber, Object{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }-一行的 DescriptionItems 数量
useCollapseboolean--是否包裹 CollapseContainer 组件
collapseOptionsObject--CollapseContainer 组件属性
schemaDescItem[]--详情项配置,见下方 DescItem 配置
dataobject--数据源

DescItem

属性类型默认值可选值说明
fieldstring--字段名
labelstring--标签名
labelMinWidthnumber--label 最小宽度
contentMinWidthnumber--content 最小宽度
labelStyleany--label 样式
spannumber--和并列数量
show(data)=>boolean--动态判断当前组件是否显示
render(val: string, data: any)=>VNode,undefined,Element,string,number--自定义渲染 content
+ + + + \ No newline at end of file diff --git a/components/drawer.html b/components/drawer.html new file mode 100644 index 00000000..0dd6bc63 --- /dev/null +++ b/components/drawer.html @@ -0,0 +1,96 @@ + + + + + + Drawer 抽屉组件 | Vben Admin + + + + + + + + + + + + + + + + +

Drawer 抽屉组件

antv 的 drawer 组件进行封装,扩展拖拽,全屏,自适应高度等功能。

Usage

由于 drawer 内部代码一般独立成单独文件,推荐独立成组件来进行开发,所以示例都是以独立的文件来进行说明

独立组件代码,用于写组件内部的内容

<template>
+  <BasicDrawer v-bind="$attrs" title="Drawer Title" width="50%"> Drawer Info. </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicDrawer } from '/@/components/Drawer';
+  export default defineComponent({
+    components: { BasicDrawer },
+  });
+</script>
+

页面引用弹窗

<template>
+  <div>
+    <Drawer @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { useDrawer } from '/@/components/Drawer';
+  import Drawer from './Drawer.vue';
+
+  export default defineComponent({
+    components: { Drawer },
+    setup() {
+      const [register, { openDrawer }] = useDrawer();
+      return {
+        register,
+        openDrawer,
+      };
+    },
+  });
+</script>
+

useDrawer

useDrawer 用于操作组件

const [register, { openDrawer, setDrawerProps }] = useDrawer();
+

register

register 用于注册 useDrawer,如果需要使用 useDrawer 提供的 api,必须将 register 传入组件的 onRegister

原理其实很简单,就是 vue 的组件子传父通信,内部通过 emit("register",instance) 实现。

同时,独立出去的组件需要将 attrs 绑定到 Drawer 的上面。

<BasicDrawer v-bind="$attrs"> Drawer Info. </BasicDrawer>
+

openDrawer

用于打开/关闭弹窗

// true/false: 打开关闭弹窗
+// data: 传递到子组件的数据
+openDrawer(true, data);
+

closeDrawer

用于关闭弹窗

closeDrawer();
+

setDrawerProps

用于更改 drawer 的 props 参数因为 drawer 内容独立成组件,如果在外部页面需要更改 props 可能比较麻烦,所以提供 setDrawerProps 方便更改内部 drawer 的 props

Props 内容可以见下方

setDrawerProps(props);
+

useDrawerInner

用于独立的 Drawer 内部调用

<template>
+  <BasicDrawer v-bind="$attrs" @register="register" title="Drawer Title" width="50%">
+    Drawer Info.
+    <a-button type="primary" @click="closeDrawer">内部关闭drawer</a-button>
+  </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
+  export default defineComponent({
+    components: { BasicDrawer },
+    setup() {
+      const [register, { closeDrawer }] = useDrawerInner();
+      return { register, closeDrawer };
+    },
+  });
+</script>
+

useModalInner用于操作独立组件

const [register, { closeModal, setModalProps }] = useModalInner(callback);
+

callback

type: (data:any)=>void

回调函数用于接收 openDrawer 第二个参数传递的值

openDrawer((data: any) => {
+  console.log(data);
+});
+

closeDrawer

用于关闭抽屉

closeDrawer();
+

changeOkLoading

用于修改确认按钮的 loading 状态

// true or false
+changeOkLoading(true);
+

changeLoading

用于修改 modal 的 loading 状态

// true or false
+changeLoading(true);
+

setDrawerProps

用于更改 drawer 的 props 参数因为 modal 内容独立成组件,如果在外部页面需要更改 props 可能比较麻烦,所以提供setDrawerProps 方便更改内部 drawer 的 props

Props 内容可以见下方

Props

温馨提醒

除以下参数外,官方文档内的 props 也都支持,具体可以参考 antv drawer

属性类型默认值可选值说明
isDetailbooleanfalse-是否为详情模式
loadingbooleanfalse-loading 状态
loadingTextstring``-loading 文本 s
showDetailBackbooleantrue-isDetail=true 状态下是否显示返回按钮
closeFunc() => Promise<boolean>--自定义关闭函数,返回true关闭,否则不关闭
showFooterboolean--是否显示底部
footerHeightnumber60-底部区域高度

Events

事件回调参数说明
close(e)=>void点击关闭回调
visible-change(visible:boolean)=>void弹窗打开关闭时触发
ok(e)=>void点击确定回调
+ + + + \ No newline at end of file diff --git a/components/excel.html b/components/excel.html new file mode 100644 index 00000000..8ff96b8d --- /dev/null +++ b/components/excel.html @@ -0,0 +1,106 @@ + + + + + + Excel 组件 | Vben Admin + + + + + + + + + + + + + + + + +

Excel 组件

excel 导入导出操作

项目中使用到的是 XLSX,具体文档可以参考XLSX 文档

Import

Usage

<template>
+  <ImpExcel @success="loadDataSuccess">
+    <a-button class="m-3">导入Excel</a-button>
+  </ImpExcel>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { ImpExcel, ExcelData } from '/@/components/Excel';
+  export default defineComponent({
+    components: { ImpExcel },
+    setup() {
+      function loadDataSuccess(excelDataList: ExcelData[]) {
+        tableListRef.value = [];
+        console.log(excelDataList);
+        for (const excelData of excelDataList) {
+          const {
+            header,
+            results,
+            meta: { sheetName },
+          } = excelData;
+          const columns: BasicColumn[] = [];
+          for (const title of header) {
+            columns.push({ title, dataIndex: title });
+          }
+          tableListRef.value.push({ title: sheetName, dataSource: results, columns });
+        }
+      }
+      return {
+        loadDataSuccess,
+      };
+    },
+  });
+</script>
+

Events

事件回调参数说明
success(res:ExcelData)=>void导入成功回调
error()=>void导出错误

ExcelData

属性类型默认值说明
header:string[];table 表头
results:T[];table 数据
meta:{ sheetName: string };table title

Export

具体详情可以参考完整版示例

import { jsonToSheetXlsx, aoaToSheetXlsx } from '/@/components/Excel';
+

数组格式数据导出

import { aoaToSheetXlsx } from '/@/components/Excel';
+// 保证data顺序与header一致
+aoaToSheetXlsx({
+  data: [],
+  header: [],
+  filename: '二维数组方式导出excel.xlsx',
+});
+

自定义导出格式

import { jsonToSheetXlsx } from '/@/components/Excel';
+
+jsonToSheetXlsx({
+  data,
+  filename,
+  write2excelOpts: {
+    // 可以是 xlsx/html/csv/txt
+    bookType,
+  },
+});
+

json 格式导出

import { jsonToSheetXlsx } from '/@/components/Excel';
+
+jsonToSheetXlsx({
+  data,
+  filename: '使用key作为默认头部.xlsx',
+});
+
+jsonToSheetXlsx({
+  data,
+  header: {
+    id: 'ID',
+    name: '姓名',
+    age: '年龄',
+    no: '编号',
+    address: '地址',
+    beginTime: '开始时间',
+    endTime: '结束时间',
+  },
+  filename: '自定义头部.xlsx',
+  json2sheetOpts: {
+    // 指定顺序
+    header: ['name', 'id'],
+  },
+});
+

Function

方法回调参数返回值说明
jsonToSheetXlsxFunction(JsonToSheet)json 格式数据,导出到 excel
aoaToSheetXlsxFunction(AoAToSheet)数组格式,导出到 excel

JsonToSheet Type

属性类型默认值说明
dataT[]JSON 对象数组
header?:T;表头未设置则取 JSON 对象的 key 作为 header
filename?:stringexcel-list.xlsx导出的文件名
json2sheetOpts?:JSON2SheetOpts调用 XLSX.utils.json_to_sheet 的可选参数
write2excelOpts?:WritingOptions{ bookType: 'xlsx' }调用 XLSX.writeFile 的可选参数,具体参 XLSX 文档

AoAToSheet Type

属性类型默认值说明
dataT[][];二维数组
header?:T;表头 ;未设置则没有表头
filename?:string;excel-list.xlsx导出的文件名
write2excelOpts?:WritingOptions;{ bookType: 'xlsx' }调用 XLSX.writeFile 的可选参数
+ + + + \ No newline at end of file diff --git a/components/flow-chart.html b/components/flow-chart.html new file mode 100644 index 00000000..697dac77 --- /dev/null +++ b/components/flow-chart.html @@ -0,0 +1,47 @@ + + + + + + FlowChart | Vben Admin + + + + + + + + + + + + + + + + +

FlowChart

流程图组件,基于 didi/LogicFlow 的简单封装。详细配置请参考文档 FlowChart

Usage

<template>
+  <FlowChart :data="demoData" />
+</template>
+
+<script lang="ts">
+  import { FlowChart } from '/@/components/FlowChart';
+  import { PageWrapper } from '/@/components/Page';
+
+  import demoData from './dataTurbo.json';
+  export default {
+    components: { FlowChart, PageWrapper },
+    setup() {
+      return { demoData };
+    },
+  };
+</script>
+

Props

属性类型默认值可选值说明
flowOptionsobject--FlowCharts 配置项
dataobject--流程数据
toolbarbooleantrue-是否显示工具栏
patternItems[]--左侧拖拽列表数据
+ + + + \ No newline at end of file diff --git a/components/form.html b/components/form.html new file mode 100644 index 00000000..7d044d8d --- /dev/null +++ b/components/form.html @@ -0,0 +1,463 @@ + + + + + + Form 表单组件 | Vben Admin + + + + + + + + + + + + + + + + +

Form 表单组件

antv 的 form 组件进行封装,扩展一些常用的功能

如果文档内没有,可以尝试在在线示例内寻找

Usage

useForm 方式

下面是一个使用简单表单的示例,只有一个输入框

<template>
+  <div class="m-4">
+    <BasicForm
+      :labelWidth="100"
+      :schemas="schemas"
+      :actionColOptions="{ span: 24 }"
+      @submit="handleSubmit"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema } from '/@/components/Form';
+  import { CollapseContainer } from '/@/components/Container';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field',
+      component: 'Input',
+      label: '字段1',
+      colProps: {
+        span: 8,
+      },
+      defaultValue: '1',
+      componentProps: {
+        placeholder: '自定义placeholder',
+        onChange: (e) => {
+          console.log(e);
+        },
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const { createMessage } = useMessage();
+      return {
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+      };
+    },
+  });
+</script>
+

template 方式

所有可调用函数见下方 Methods 说明

<template>
+  <div class="m-4">
+    <BasicForm
+      :schemas="schemas"
+      ref="formElRef"
+      :labelWidth="100"
+      @submit="handleSubmit"
+      :actionColOptions="{ span: 24 }"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicForm, FormSchema, FormActionType, FormProps } from '/@/components/Form';
+  import { CollapseContainer } from '/@/components/Container';
+  const schemas: FormSchema[] = [];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const formElRef = ref<Nullable<FormActionType>>(null);
+      return {
+        formElRef,
+        schemas,
+        setProps(props: FormProps) {
+          const formEl = formElRef.value;
+          if (!formEl) return;
+          formEl.setProps(props);
+        },
+      };
+    },
+  });
+</script>
+

useForm

form 组件还提供了 useForm,方便调用函数内部方法

示例

<template>
+  <BasicForm @register="register" @submit="handleSubmit" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '字段1',
+      colProps: {
+        span: 8,
+      },
+      componentProps: {
+        placeholder: '自定义placeholder',
+        onChange: (e: any) => {
+          console.log(e);
+        },
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm, CollapseContainer },
+    setup() {
+      const { createMessage } = useMessage();
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+        setProps,
+      };
+    },
+  });
+</script>
+

参数介绍

const [register, methods] = useForm(props);
+

参数 props 内的值可以是 computed 或者 ref 类型

register

register 用于注册 useForm,如果需要使用 useForm 提供的 api,必须将 register 传入组件的 onRegister

<template>
+  <BasicForm @register="register" @submit="handleSubmit" />
+</template>
+<script>
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register] = useForm();
+      return {
+        register,
+      };
+    },
+  });
+</script>
+

Methods见下方说明

Methods

getFieldsValue

类型: () => Recordable;

说明: 获取表单值

setFieldsValue

类型: <T>(values: T) => Promise<void>

说明: 设置表单字段值

resetFields

类型: ()=> Promise<void>

说明: 重置表单值

validateFields

类型: (nameList?: NamePath[]) => Promise<any>

说明: 校验指定表单项

validate

类型: (nameList?: NamePath[]) => Promise<any>

说明: 校验整个表单

submit

类型: () => Promise<void>

说明: 提交表单

scrollToField

类型: (name: NamePath, options?: ScrollOptions) => Promise<void>

说明: 滚动到对应字段位置

clearValidate

类型: (name?: string | string[]) => Promise<void>

说明: 清空校验

setProps

TIP

设置表单的 props 可以直接在标签上传递,也可以使用 setProps,或者初始化直接写 useForm(props)

类型: (formProps: Partial<FormProps>) => Promise<void>

说明: 设置表单 Props

removeSchemaByFiled

类型: (field: string | string[]) => Promise<void>

说明: 根据 field 删除 Schema

appendSchemaByField

类型: ( schema: FormSchema, prefixField: string | undefined, first?: boolean | undefined ) => Promise<void>

说明: 插入到指定 filed 后面,如果没传指定 field,则插入到最后,当 first = true 时插入到第一个位置

updateSchema

类型: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>

说明: 更新表单的 schema, 只更新函数所传的参数

e.g

updateSchema({ field: 'filed', componentProps: { disabled: true } });
+updateSchema([
+  { field: 'filed', componentProps: { disabled: true } },
+  { field: 'filed1', componentProps: { disabled: false } },
+]);
+

Props

温馨提醒

除以下参数外,官方文档内的 props 也都支持,具体可以参考 antv form

属性类型默认值可选值说明版本
schemasSchema[]--表单配置,见下方 FormSchema 配置
submitOnResetbooleanfalse-重置时是否提交表单
labelColPartial<ColEx>--整个表单通用 LabelCol 配置
wrapperColPartial<ColEx>--整个表单通用 wrapperCol 配置
baseColPropsPartial<ColEx>--配置所有选子项的 ColProps,不需要逐个配置,子项也可单独配置优先与全局
baseRowStyleobject--配置所有 Row 的 style 样式
labelWidthnumber , string--扩展 form 组件,增加 label 宽度,表单内所有组件适用,可以单独在某个项覆盖或者禁用
labelAlignstring-left,rightlabel 布局
mergeDynamicDataobject--额外传递到子组件的参数 values
autoFocusFirstItembooleanfalse-是否聚焦第一个输入框,只在第一个表单项为 input 的时候作用
compactbooleanfalsetrue/false紧凑类型表单,减少 margin-bottom
sizestringdefault'default' , 'small' , 'large'向表单内所有组件传递 size 参数,自定义组件需自行实现 size 接收
disabledbooleanfalsetrue/false向表单内所有组件传递 disabled 属性,自定义组件需自行实现 disabled 接收
autoSetPlaceHolderbooleantrue true/false自动设置表单内组件的 placeholder,自定义组件需自行实现
autoSubmitOnEnterbooleanfalse true/false在 input 中输入时按回车自动提交2.4.0
rulesMessageJoinLabelbooleanfalsetrue/false如果表单项有校验,会自动生成校验信息,该参数控制是否将字段中文名字拼接到自动生成的信息后方
showAdvancedButtonbooleanfalsetrue/false是否显示收起展开按钮
emptySpannumber , Partial<ColEx>0-空白行格,可以是数值或者 col 对象 数
autoAdvancedLinenumber3-如果 showAdvancedButton 为 true,超过指定行数行默认折叠
alwaysShowLinesnumber1-折叠时始终保持显示的行数2.7.1
showActionButtonGroupbooleantruetrue/false是否显示操作按钮(重置/提交)
actionColOptionsPartial<ColEx>--操作按钮外层 Col 组件配置,如果开启 showAdvancedButton,则不用设置,具体见下方 actionColOptions
showResetButtonbooleantrue-是否显示重置按钮
resetButtonOptionsobject-重置按钮配置见下方 ActionButtonOption
showSubmitButtonbooleantrue-是否显示提交按钮
submitButtonOptionsobject-确认按钮配置见下方 ActionButtonOption
resetFunc () => Promise<void>-自定义重置按钮逻辑() => Promise<void>;
submitFunc () => Promise<void>-自定义提交按钮逻辑() => Promise<void>;
fieldMapToTime[string, [string, string], string?][]'timestamp' ,'timestampStartDay' ,momentjs 时间格式用于将表单内时间区域的应设成 2 个字段,见下方说明

ColEx

src/components/Form/src/types/index.ts

ActionButtonOption

BasicButtonProps

export interface ButtonProps extends BasicButtonProps {
+  text?: string;
+}
+

fieldMapToTime

将表单内时间区域的值映射成 2 个字段

如果表单内有时间区间组件,获取到的值是一个数组,但是往往我们传递到后台需要是 2 个字段

useForm({
+  fieldMapToTime: [
+    // data为时间组件在表单内的字段,startTime,endTime为转化后的开始时间与结束时间
+    // 'YYYY-MM-DD'为时间格式,参考moment
+    ['datetime', ['startTime', 'endTime'], 'YYYY-MM-DD'],
+    // 支持多个字段
+    ['datetime1', ['startTime1', 'endTime1'], 'YYYY-MM-DD HH:mm:ss'],
+  ],
+});
+
+// fieldMapToTime没写的时候表单获取到的值
+{
+  datetime: [Date(),Date()]
+}
+//  ['datetime', ['startTime', 'endTime'], 'YYYY-MM-DD'],等同于 dayjs(Date()).format('YYYY-MM-DD'). 之后
+{
+    startTime: '2020-08-12',
+    endTime: '2020-08-15',
+}
+
+// ['datetime', ['startTime', 'endTime'], 'timestamp'],等同于 dayjs(Date()).unix(). 之后
+{
+    startTime: 1597190400,
+    endTime: 1597449600,
+}
+
+// ['datetime', ['startTime', 'endTime'], 'timestampStartDay'],等同于 dayjs(Date()).startOf('day').unix(). 之后
+{
+    startTime: 1597190400,
+    endTime: 1597449600,
+}
+

FormSchema

属性类型默认值可选值说明
fieldstring--字段名
labelstring--标签名
subLabelstring--二级标签名灰色
suffixstring , number , ((values: RenderCallbackParams) => string / number);--组件后面的内容
changeEventstring--表单更新事件名称
helpMessagestring , string[]--标签名右侧温馨提示
helpComponentPropsHelpComponentProps--标签名右侧温馨提示组件 props,见下方 HelpComponentProps
labelWidthstring , number--覆盖统一设置的 labelWidth
disabledLabelWidthbooleanfalsetrue/false禁用 form 全局设置的 labelWidth,自己手动设置 labelCol 和 wrapperCol
componentstring--组件类型,见下方 ComponentType
componentPropsany,()=>{}--所渲染的组件的 props
rulesValidationRule[]--校验规则,见下方 ValidationRule
requiredboolean--简化 rules 配置,为 true 则转化成 [{required:true}]。2.4.0之前的版本只支持 string 类型的值
rulesMessageJoinLabelbooleanfalse-校验信息是否加入 label
itemPropsany--参考下方 FormItem
colPropsColEx--参考上方 actionColOptions
defaultValueobject--所渲渲染组件的初始值
render(renderCallbackParams: RenderCallbackParams) => VNode / VNode[] / string--自定义渲染组件
renderColContent(renderCallbackParams: RenderCallbackParams) => VNode / VNode[] / string--自定义渲染组件(需要自行包含 formItem)
renderComponentContent(renderCallbackParams: RenderCallbackParams) => any / string--自定义渲染组内部的 slot
slotstring--自定义 slot,渲染组件
colSlotstring--自定义 slot,渲染组件 (需要自行包含 formItem)
show boolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--动态判断当前组件是否显示,css 控制,不会删除 dom
ifShow boolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--动态判断当前组件是否显示,js 控制,会删除 dom
dynamicDisabledboolean / ((renderCallbackParams: RenderCallbackParams) => boolean) --动态判断当前组件是否禁用
dynamicRulesboolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--动态判返当前组件你校验规则

RenderCallbackParams

export interface RenderCallbackParams {
+  schema: FormSchema;
+  values: any;
+  model: any;
+  field: string;
+}
+

componentProps

  • 当值为对象类型时,该对象将作为component所对应组件的的 props 传入组件

  • 当值为一个函数时候

参数有 4 个

schema: 表单的整个 schemas

formActionType: 操作表单的函数。与 useForm 返回的操作函数一致

formModel: 表单的双向绑定对象,这个值是响应式的。所以可以方便处理很多操作

tableAction: 操作表格的函数,与 useTable 返回的操作函数一致。注意该参数只在表格内开启搜索表单的时候有值,其余情况为null,

{
+  // 简单例子,值改变的时候操作表格或者修改表单内其他元素的值
+  component:'Input',
+  componentProps: ({ schema, tableAction, formActionType, formModel }) => {
+    return {
+      // xxxx props
+      onChange:e=>{
+        const {reload}=tableAction
+        reload()
+        // or
+        formModel.xxx='123'
+      }
+    };
+  };
+}
+

HelpComponentProps

export interface HelpComponentProps {
+  maxWidth: string;
+  // 是否显示序号
+  showIndex: boolean;
+  // 文本列表
+  text: any;
+  // 颜色
+  color: string;
+  // 字体大小
+  fontSize: string;
+  icon: string;
+  absolute: boolean;
+  // 定位
+  position: any;
+}
+

ComponentType

schema 内组件的可选类型

export type ComponentType =
+  | 'Input'
+  | 'InputGroup'
+  | 'InputPassword'
+  | 'InputSearch'
+  | 'InputTextArea'
+  | 'InputNumber'
+  | 'InputCountDown'
+  | 'Select'
+  | 'ApiSelect'
+  | 'TreeSelect'
+  | 'RadioButtonGroup'
+  | 'RadioGroup'
+  | 'Checkbox'
+  | 'CheckboxGroup'
+  | 'AutoComplete'
+  | 'Cascader'
+  | 'DatePicker'
+  | 'MonthPicker'
+  | 'RangePicker'
+  | 'WeekPicker'
+  | 'TimePicker'
+  | 'Switch'
+  | 'StrengthMeter'
+  | 'Upload'
+  | 'IconPicker'
+  | 'Render'
+  | 'Slider'
+  | 'Rate'
+  | 'Divider'; // v2.7.2新增
+

Divider schema 说明

Divider类型用于在schemas中占位,将会渲染成一个分割线(始终占一整行的版面),可以用于较长表单的版面分隔。请只将 Divider 类型的 schema 当作一个分割线,而不是一个常规的表单字段。

  • Divider仅在showAdvancedButton为 false 时才会显示(也就是说如果启用了表单收起和展开功能,Divider将不会显示)
  • Divider 使用schema中的label以及helpMessage来渲染分割线中的提示内容
  • Divider 可以使用componentProps来设置除type之外的 props
  • Divider 不会渲染AFormItem,因此schema中除labelcomponentPropshelpMessagehelpComponentProps以外的属性不会被用到

自行添加需要的组件类型

src/components/Form/src/componentMap.ts 内,添加需要的组件,并在上方 ComponentType 添加相应的类型 key

方式 1

这种写法适用与适用频率较高的组件

componentMap.set('componentName', 组件);
+
+// ComponentType
+export type ComponentType = xxxx | 'componentName';
+

方式 2

使用 useComponentRegister 进行注册

这种写法只能在当前页使用,页面销毁之后会从 componentMap 删除相应的组件

import { useComponentRegister } from '@/components/form/index';
+
+import { StrengthMeter } from '@/components/strength-meter/index';
+
+useComponentRegister('StrengthMeter', StrengthMeter);
+

提示

方式 2 出现的原因是为了减少打包体积,如果某个组件体积很大,用方式 1 的话可能会使首屏体积增加

render

自定义渲染内容

<template>
+  <div class="m-4">
+    <BasicForm @register="register" @submit="handleSubmit" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, h } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { Input } from 'ant-design-vue';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '字段1',
+      colProps: {
+        span: 8,
+      },
+      rules: [{ required: true }],
+      render: ({ model, field }) => {
+        return h(Input, {
+          placeholder: '请输入',
+          value: model[field],
+          onChange: (e: ChangeEvent) => {
+            model[field] = e.target.value;
+          },
+        });
+      },
+    },
+    {
+      field: 'field2',
+      component: 'Input',
+      label: '字段2',
+      colProps: {
+        span: 8,
+      },
+      rules: [{ required: true }],
+      renderComponentContent: () => {
+        return {
+          suffix: () => 'suffix',
+        };
+      },
+    },
+  ];
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const { createMessage } = useMessage();
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        handleSubmit: (values: any) => {
+          createMessage.success('click search,values:' + JSON.stringify(values));
+        },
+        setProps,
+      };
+    },
+  });
+</script>
+

slot

自定义渲染内容

提示

使用插槽自定义表单域时,请注意 antdv 有关 FormItem 的相关说明

<template>
+  <div class="m-4">
+    <BasicForm @register="register">
+      <template #customSlot="{ model, field }">
+        <a-input v-model:value="model[field]" />
+      </template>
+    </BasicForm>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'compatible-vue';
+  import { BasicForm, useForm } from '@/components/Form/index';
+  import { BasicModal } from '@/components/modal/index';
+  export default defineComponent({
+    name: 'FormDemo',
+    setup(props) {
+      const [register] = useForm({
+        labelWidth: 100,
+        actionColOptions: {
+          span: 24,
+        },
+        schemas: [
+          {
+            field: 'field1',
+            label: '字段1',
+            slot: 'customSlot',
+          },
+        ],
+      });
+      return {
+        register,
+      };
+    },
+  });
+</script>
+

ifShow/show/dynamicDisabled

自定义显示/禁用

<template>
+  <div class="m-4">
+    <BasicForm @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  const schemas: FormSchema[] = [
+    {
+      field: 'field1',
+      component: 'Input',
+      label: '字段1',
+      colProps: {
+        span: 8,
+      },
+      show: ({ values }) => {
+        return !!values.field5;
+      },
+    },
+    {
+      field: 'field2',
+      component: 'Input',
+      label: '字段2',
+      colProps: {
+        span: 8,
+      },
+      ifShow: ({ values }) => {
+        return !!values.field6;
+      },
+    },
+    {
+      field: 'field3',
+      component: 'DatePicker',
+      label: '字段3',
+      colProps: {
+        span: 8,
+      },
+      dynamicDisabled: ({ values }) => {
+        return !!values.field7;
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register, { setProps }] = useForm({
+        labelWidth: 120,
+        schemas,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      return {
+        register,
+        schemas,
+        setProps,
+      };
+    },
+  });
+</script>
+

antv form

Slots

名称说明
formFooter表单底部区域
formHeader表单顶部区域
resetBefore重置按钮前
submitBefore提交按钮前
advanceBefore展开按钮前
advanceAfter展开按钮后

ApiSelect

远程下拉加载组件,该组件可以用于学习参考如何自定义组件集成到 Form 组件内,将自定义组件交由 Form 去管理

Usage

const schemas: FormSchema[] = [
+  {
+    field: 'field',
+    component: 'ApiSelect',
+    label: '字段',
+  },
+];
+

Props

属性类型默认值说明
numberToStringbooleanfalse是否将number值转化为string
api()=>Promise<{ label: string; value: string; disabled?: boolean }[]>-数据接口,接受一个 Promise 对象
paramsobject-接口参数。此属性改变时会自动重新加载接口数据
resultFieldstring-接口返回的字段,如果接口返回数组,可以不填。支持x.x.x格式
labelFieldstringlabel下拉数组项内label显示文本的字段,支持x.x.x格式
valueFieldstringvalue下拉数组项内value实际值的字段,支持x.x.x格式
immediatebooleantrue是否立即请求接口,否则将在第一次点击时候触发请求

ApiTreeSelect

远程下拉树加载组件,和ApiSelect类似,2.6.1 以上版本

Props

属性类型默认值说明
api()=>Promise<{ label: string; value: string; children?: any[] }[]>-数据接口,接受一个 Promise 对象
paramsobject-接口参数。此属性改变时会自动重新加载接口数据
resultFieldstring-接口返回的字段,如果接口返回数组,可以不填。支持x.x.x格式
immediatebooleantrue是否立即请求接口。

RadioButtonGroup

Radio Button 风格的选择按钮

Usage

const schemas: FormSchema[] = [
+  {
+    field: 'field',
+    component: 'RadioButtonGroup',
+    label: '字段',
+  },
+];
+

Props

属性类型默认值说明
options{ label: string; value: string; disabled?: boolean }[]-数据字段
+ + + + \ No newline at end of file diff --git a/components/functional/context-menu.html b/components/functional/context-menu.html new file mode 100644 index 00000000..76c90b39 --- /dev/null +++ b/components/functional/context-menu.html @@ -0,0 +1,71 @@ + + + + + + ContextMenu | Vben Admin + + + + + + + + + + + + + + + + +

ContextMenu

函数式创建右键菜单组件, 只要能拿到 dom 的 event 对象就能为其创建右键菜单。

Usage

<template>
+  <div>
+    <a-button type="primary" @contextmenu="handleContext">Right Click on me</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { useContextMenu } from '/@/hooks/web/useContextMenu';
+  import { CollapseContainer } from '/@/components/Container';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  export default defineComponent({
+    components: { CollapseContainer },
+    setup() {
+      const [createContextMenu] = useContextMenu();
+      const { createMessage } = useMessage();
+      function handleContext(e: MouseEvent) {
+        createContextMenu({
+          event: e,
+          items: [
+            {
+              label: 'New',
+              icon: 'ant-design:plus-outlined',
+              handler: () => {
+                createMessage.success('click new');
+              },
+            },
+            {
+              label: 'Open',
+              icon: 'ant-design:folder-open-filled',
+              handler: () => {
+                createMessage.success('click open');
+              },
+            },
+          ],
+        });
+      }
+      return { handleContext };
+    },
+  });
+</script>
+

createContextMenu

Options

属性类型默认值可选值说明
eventEvent--需要创建的 dom 的 Event 对象
itemsContextMenuItem[]--右键菜单列表,ContextMenuItem见下方说明

ContextMenuItem

属性类型说明
labelstring文本
iconstring图标,参考图标组件
disabledboolean是否禁用
handler()=>void点击触发函数
+ + + + \ No newline at end of file diff --git a/components/functional/loading.html b/components/functional/loading.html new file mode 100644 index 00000000..5bd5e6d9 --- /dev/null +++ b/components/functional/loading.html @@ -0,0 +1,84 @@ + + + + + + Loading | Vben Admin + + + + + + + + + + + + + + + + +

Loading

Usage

<template>
+  <div class="p-5" ref="wrapEl" v-loading="loadingRef" loading-tip="加载中...">
+    <a-alert message="函数方式" />
+
+    <a-button class="my-4 mr-4" type="primary" @click="openFnFullLoading">全屏 Loading</a-button>
+    <a-button class="my-4" type="primary" @click="openFnWrapLoading">容器内 Loading</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs, ref } from 'vue';
+  import { Loading, useLoading } from '/@/components/Loading';
+  export default defineComponent({
+    components: { Loading },
+    setup() {
+      const [openFullLoading, closeFullLoading] = useLoading({
+        tip: '加载中...',
+      });
+
+      const [openWrapLoading, closeWrapLoading] = useLoading({
+        target: wrapEl,
+        props: {
+          tip: '加载中...',
+          absolute: true,
+        },
+      });
+
+      function openFnFullLoading() {
+        openFullLoading();
+
+        setTimeout(() => {
+          closeFullLoading();
+        }, 2000);
+      }
+
+      function openFnWrapLoading() {
+        openWrapLoading();
+
+        setTimeout(() => {
+          closeWrapLoading();
+        }, 2000);
+      }
+
+      return {
+        openFnFullLoading,
+        openFnWrapLoading,
+        ...toRefs(compState),
+      };
+    },
+  });
+</script>
+

useLoading

使用

import { useLoading } from '/@/components/Loading';
+
+const [open, close, setTip] = useLoading(opt: Partial<LoadingProps> | Partial<UseLoadingOptions>);
+

UseLoadingOptions

属性类型默认值可选值说明
targetHTMLElement or Ref<HTMLElement>--挂载的 dom 节点
propsLoadingProps--loading 组件参数

LoadingProps

属性类型默认值可选值说明
tipstring--加载文本
sizedefault, small , largedefault-大小
absolutebooleanfalse-绝对定位,为 false 时可以全屏
loadingboolean--当前加载状态
backgroundstring--背景色,
theme'dark' or 'light'light-背景色主题 ,当背景色不为空时使用背景色

返回值

open

打开 loading

close

关闭 loading

setTip

设置加在提示文案(v2.6.2以上版本)

+ + + + \ No newline at end of file diff --git a/components/functional/preview.html b/components/functional/preview.html new file mode 100644 index 00000000..e39cabde --- /dev/null +++ b/components/functional/preview.html @@ -0,0 +1,78 @@ + + + + + + Preview | Vben Admin + + + + + + + + + + + + + + + + +

Preview

将图片预览组件组件函数化。通过函数方便创建组件

Usage

<template>
+  <div class="p-4">
+    <Alert message="有预览图" type="info" />
+    <div class="flex justify-center mt-4">
+      <img :src="img" v-for="img in imgList" :key="img" class="mr-2" @click="handleClick(img)" />
+    </div>
+    <Alert message="无预览图" type="info" />
+    <a-button @click="handlePreview" type="primary" class="mt-4">预览图片</a-button>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Alert } from 'ant-design-vue';
+  import { createImgPreview } from '/@/components/Preview/index';
+  const imgList: string[] = [
+    'https://picsum.photos/id/66/346/216',
+    'https://picsum.photos/id/67/346/216',
+    'https://picsum.photos/id/68/346/216',
+  ];
+  export default defineComponent({
+    components: { Alert },
+    setup() {
+      function handleClick(img: string) {
+        createImgPreview({ imageList: [img] });
+      }
+
+      function handlePreview() {
+        createImgPreview({ imageList: imgList });
+      }
+      return { imgList, handleClick, handlePreview };
+    },
+  });
+</script>
+

createImgPreview

参数/Options

属性类型默认值可选值说明
imgListstring[]--图片列表
indexnumber0-初始预览时的图片索引
scaleStepnumber--缩放步进值(每次缩放的幅度)。默认为自动(当前缩放值的10%)
defaultWidthnumber--默认宽度(单位px)。当提供此值时,所有图片初始时都会被缩放至此宽度
maskClosablebooleanfalsetrue/false点击遮罩时是否自动关闭预览
rememberStatebooleanfalsetrue/false是否记住每张图片各自的缩放状态
onImgLoad({ index: number, url: string, dom: HTMLImageElement }) => void--图片加载成功时的回调函数
onImgError({ index: number, url: string, dom: HTMLImageElement }) => void--图片加载失败时的回调函数

返回值/PreviewActions

可用于控制当前预览状态

interface PreviewActions {
+  // 重置状态
+  resume: () => void;
+  // 关闭预览
+  close: () => void;
+  // 显示前一张
+  prev: () => void;
+  // 显示后一张
+  next: () => void;
+  // 设置缩放比例(针对当前图片)
+  setScale: (scale: number) => void;
+  // 设置旋转角度(针对当前图片)
+  setRotate: (rotate: number) => void;
+}
+
+ + + + \ No newline at end of file diff --git a/components/glob/button.html b/components/glob/button.html new file mode 100644 index 00000000..1d57d10e --- /dev/null +++ b/components/glob/button.html @@ -0,0 +1,36 @@ + + + + + + button 按钮 | Vben Admin + + + + + + + + + + + + + + + + +

button 按钮

二次封装按钮组件,且使用相同的组件名替换全局的 a-button 组件

TIP

  • 按钮不需要 import,已经全局注册,直接使用 a-button 标签即可
  • 如果是 Tsx 文件,需要手动 import

Usage

<template>
+  <a-button color="success">成功按钮</a-button>
+  <a-button color="error">错误按钮</a-button>
+  <a-button color="warning">警告按钮</a-button>
+</template>
+

Props

提示

保持 anv design button 组件 原有功能的情况下扩展以下属性

属性类型默认值说明
color'error','warning', 'success'-按钮的颜色场景状态颜色,
preIconstring-按钮文本前图标,参考 Icon 组件
postIconstring-按钮文本后图标,参考 Icon 组件
iconSizenumber14按钮图标大小
+ + + + \ No newline at end of file diff --git a/components/icon.html b/components/icon.html new file mode 100644 index 00000000..134871c0 --- /dev/null +++ b/components/icon.html @@ -0,0 +1,66 @@ + + + + + + icon 图标组件 | Vben Admin + + + + + + + + + + + + + + + + +

icon 图标组件

Icon

用于项目内组件的展示,基本支持所有图标库(支持按需加载,只打包所用到的图标)

icon 组件位于 src/components/Icon

TIP

icon 的值可以在 IconifyNetlify 上查询

Usage

<template>
+  <Icon icon="gg:loadbar-doc"></Icon>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Icon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { Icon },
+  });
+</script>
+

Props

属性类型默认值说明
iconstring-图标名
colorstring-图标颜色
sizenumber16图标大小
prefixstring-图标前缀

提示

如果 icon 值以 |svg 结尾,则会渲染成 SvgIcon 组件

SvgIcon

用于使用项目 svg 雪碧图

Usage

<template>
+  <div>
+    <SvgIcon name="test"> </SvgIcon>
+  </div>
+</template>
+<script>
+  import { SvgIcon } from '/@/components/Icon';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { SvgIcon },
+  });
+</script>
+

Props

属性类型默认值说明
namestring-svg 图标名
sizenumber16图标大小

IconPicker

本组件详细说明请参阅图标选择器

Usage

<template>
+  <div>
+    <IconPicker />
+  </div>
+</template>
+<script>
+  import { IconPicker } from '/@/components/Icon';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { IconPicker },
+  });
+</script>
+

Props

属性类型默认值说明
widthstring100%宽度
pageSizenumber140每页显示的图标数
copybooleanfalse是否可以复制
modestringiconify备选图标池,为 svg 时,会读取所有 svg sprite 图标。详见下方说明

mode 说明

  • modeiconify时,会使用预生成的图标集数据作为备选图标池
  • modesvg时,会使用 /src/assets/icons 下的所有svg图标(可包含一级子目录)作为备选图标池,详见vite-plugin-svg-icons
+ + + + \ No newline at end of file diff --git a/components/introduction.html b/components/introduction.html new file mode 100644 index 00000000..a5aa5e57 --- /dev/null +++ b/components/introduction.html @@ -0,0 +1,45 @@ + + + + + + 前言 | Vben Admin + + + + + + + + + + + + + + + + +

前言

注意事项

组件的 defaultXXX 属性不要使用,ant-design-vue 2.2 版本之后将会逐步移除。二次封装的组件也不兼容 defaultXXX 属性。

Usage

该项目的组件大部分没有进行全局注册。采用了按需引入注册方式,如下

<template>
+  <ConfigProvider>
+    <router-view />
+  </ConfigProvider>
+</template>
+
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { ConfigProvider } from 'ant-design-vue';
+  export default defineComponent({
+    name: 'App',
+    components: { ConfigProvider },
+  });
+</script>
+
+ + + + \ No newline at end of file diff --git a/components/json-preview.html b/components/json-preview.html new file mode 100644 index 00000000..82832057 --- /dev/null +++ b/components/json-preview.html @@ -0,0 +1,47 @@ + + + + + + JsonPreview | Vben Admin + + + + + + + + + + + + + + + + +

JsonPreview

json 数据预览组件

Usage

<template>
+  <JsonPreview :data="data" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { JsonPreview } from '/@/components/CodeEditor';
+
+  export default defineComponent({
+    components: { JsonPreview },
+    setup() {
+      return {
+        data: {},
+      };
+    },
+  });
+</script>
+

Props

属性类型默认值可选值说明
dataobject--需要预览的 Json 数据
+ + + + \ No newline at end of file diff --git a/components/lazy-container.html b/components/lazy-container.html new file mode 100644 index 00000000..99bf6657 --- /dev/null +++ b/components/lazy-container.html @@ -0,0 +1,73 @@ + + + + + + LazyContainer | Vben Admin + + + + + + + + + + + + + + + + +

LazyContainer

延时加载/懒加载组件, 只在组件可见或者延迟一段时间才进行加载

Usage

<template>
+  <div class="p-4 lazy-base-demo">
+    <div class="lazy-base-demo-wrap">
+      <h1>向下滚动</h1>
+      <LazyContainer @init="() => {}">
+        <TargetContent />
+        <template #skeleton>
+          <Skeleton :rows="10" />
+        </template>
+      </LazyContainer>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Skeleton } from 'ant-design-vue';
+  import TargetContent from './TargetContent.vue';
+  import { LazyContainer } from '/@/components/Container/index';
+  export default defineComponent({
+    components: { LazyContainer, TargetContent, Skeleton },
+  });
+</script>
+<style lang="less" scoped>
+  .lazy-base-demo {
+    &-wrap {
+      display: flex;
+      width: 50%;
+      height: 2000px;
+      margin: 20px auto;
+      text-align: center;
+      background: #fff;
+      justify-content: center;
+      flex-direction: column;
+      align-items: center;
+    }
+
+    h1 {
+      height: 1300px;
+      margin: 20px 0;
+    }
+  }
+</style>
+

Props

属性类型默认值可选值说明
timeoutnumber--等待时间,如果指定了时间,不论可见与否,在指定时间之后自动加载
viewportHTMLElement--组件所在的视口,如果组件是在页面容器内滚动,视口就是该容器
thresholdstring0px-预加载阈值, css 单位
direction'vertical', 'horizontal' , vertical-视口的滚动方向, vertical 代表垂直方向,horizontal 代表水平方向
tagstring'div-包裹组件的外层容器的标签名
transitionNamestring'lazy-container-transition 动画 name
maxWaitingTimenumber'80-最大等待时间

Events

事件回调参数说明
init()=>void初始化之后

Slots

名称说明
default默认区域
skeleton懒加载骨架屏
+ + + + \ No newline at end of file diff --git a/components/loading.html b/components/loading.html new file mode 100644 index 00000000..3bd4d3de --- /dev/null +++ b/components/loading.html @@ -0,0 +1,74 @@ + + + + + + Loading | Vben Admin + + + + + + + + + + + + + + + + +

Loading

Usage

<template>
+  <div class="p-5" ref="wrapEl" v-loading="loadingRef" loading-tip="加载中...">
+    <a-button class="my-4 mr-4" type="primary" @click="openCompFullLoading">全屏 Loading</a-button>
+    <a-button class="my-4" type="primary" @click="openCompAbsolute">容器内 Loading</a-button>
+    <Loading :loading="loading" :absolute="absolute" :tip="tip" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs, ref } from 'vue';
+  import { Loading } from '/@/components/Loading';
+  export default defineComponent({
+    components: { Loading },
+    setup() {
+      const compState = reactive({
+        absolute: false,
+        loading: false,
+        tip: '加载中...',
+      });
+
+      function openLoading(absolute: boolean) {
+        compState.absolute = absolute;
+        compState.loading = true;
+        setTimeout(() => {
+          compState.loading = false;
+        }, 2000);
+      }
+
+      function openCompFullLoading() {
+        openLoading(false);
+      }
+
+      function openCompAbsolute() {
+        openLoading(true);
+      }
+
+      return {
+        openCompFullLoading,
+        openCompAbsolute,
+        ...toRefs(compState),
+      };
+    },
+  });
+</script>
+

Props

属性类型默认值可选值说明
tipstring--加载文本
sizedefault, small , largedefault-大小
absolutebooleanfalse-绝对定位,为 false 时可以全屏
loadingboolean--当前加载状态
backgroundstring--背景色
theme'dark' or 'light'light-背景色主题,当背景色不为空时使用背景色
+ + + + \ No newline at end of file diff --git a/components/markdown.html b/components/markdown.html new file mode 100644 index 00000000..818ec7a4 --- /dev/null +++ b/components/markdown.html @@ -0,0 +1,64 @@ + + + + + + Markdown | Vben Admin + + + + + + + + + + + + + + + + +

Markdown

基于 Vditor 的 MarkDown 编辑器

Usage

<template>
+  <div class="p-4">
+    <a-button @click="toggleTheme" class="mb-2" type="primary">黑暗主题</a-button>
+    <MarkDown v-model:value="value" ref="markDownRef" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { MarkDown, MarkDownActionType } from '/@/components/Markdown';
+  export default defineComponent({
+    components: { MarkDown },
+    setup() {
+      const markDownRef = ref<Nullable<MarkDownActionType>>(null);
+      const valueRef = ref(`
+# title
+
+# content
+`);
+
+      function toggleTheme() {
+        const markDown = unref(markDownRef);
+        if (!markDown) return;
+        const vditor = markDown.getVditor();
+        vditor.setTheme('dark');
+      }
+      return {
+        value: valueRef,
+        toggleTheme,
+        markDownRef,
+      };
+    },
+  });
+</script>
+

Props

TIP

除以下两个外,props 还可以传入 vidtor 的所有属性。可用 v-bind 统一绑定

属性类型默认值可选值说明
v-modelstring--双向绑定文本值
heightnumber--高度

Methods

名称回调参数说明
getVditorFunction获取 vditor 实例
+ + + + \ No newline at end of file diff --git a/components/modal.html b/components/modal.html new file mode 100644 index 00000000..ac74f757 --- /dev/null +++ b/components/modal.html @@ -0,0 +1,114 @@ + + + + + + Modal 弹窗 | Vben Admin + + + + + + + + + + + + + + + + +

Modal 弹窗

对 antv 的 modal 组件进行封装,扩展拖拽,全屏,自适应高度等功能

代码路径 src/components/Modal

Usage

由于弹窗内代码一般作为单文件组件存在,也推荐这样做,所以示例都为单文件组件形式

TIP

注意 v-bind="$attrs"记得写,用于将弹窗组件的 attribute 传入 BasicModal 组件

// Modal.vue
+<template>
+  <BasicModal v-bind="$attrs" title="Modal Title" :helpMessage="['提示1', '提示2']">
+    Modal Info.
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicModal } from '/@/components/Modal';
+  export default defineComponent({
+    components: { BasicModal },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

页面引用弹窗

// Page.vue
+<template>
+  <div class="px-10">
+    <Modal @register="register" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { useModal } from '/@/components/Modal';
+  import Modal from './Modal.vue';
+  export default defineComponent({
+    components: { Modal },
+    setup() {
+      const [register, { openModal }] = useModal();
+      return {
+        register,
+        openModal,
+      };
+    },
+  });
+</script>
+

useModal

用于外部组件调用

useModal 用于操作组件

const [register, { openModal, setModalProps }] = useModal();
+

register

register 用于注册 useModal,如果需要使用 useModal 提供的 api,必须将 register 传入组件的 onRegister

原理其实很简单,就是 vue 的组件子传父通信,内部通过 emit("register",instance) 实现。

同时独立出去的组件需要将 attrs 绑定到 BasicModal 上面。

<template>
+  <BasicModal v-bind="$attrs"></BasicModal>
+</template>
+

openModal

用于打开/关闭弹窗

// true/false: 打开关闭弹窗
+// data: 传递到子组件的数据
+openModal(true, data);
+

closeModal

用于关闭弹窗

closeModal();
+

setModalProps

用于更改 modal 的 props 参数因为 modal 内容独立成组件,如果在外部页面需要更改 props 可能比较麻烦,所以提供 setModalProps 方便更改内部 modal 的 props

Props 内容可以见下方

setModalProps(props);
+

useModalInner

用于独立的 Modal 内部调用

Usage

<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="register"
+    title="Modal Title"
+    :helpMessage="['提示1', '提示2']"
+  >
+    <a-button type="primary" @click="closeModal" class="mr-2">从内部关闭弹窗</a-button>
+
+    <a-button type="primary" @click="setModalProps">从内部修改title</a-button>
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  export default defineComponent({
+    components: { BasicModal },
+    setup() {
+      const [register, { closeModal, setModalProps }] = useModalInner();
+      return {
+        register,
+        closeModal,
+        setModalProps: () => {
+          setModalProps({ title: 'Modal New Title' });
+        },
+      };
+    },
+  });
+</script>
+

useModalInner用于操作独立组件

const [register, { closeModal, setModalProps }] = useModalInner(callback);
+

callback

type: (data:any)=>void

回调函数用于接收 openModal 第二个参数传递的值

useModal((data: any) => {
+  console.log(data);
+});
+

closeModal

用于关闭弹窗

closeModal();
+

changeOkLoading

用于修改确认按钮的 loading 状态

changeOkLoading(true);
+

changeLoading

用于修改 modal 的 loading 状态

// true or false
+changeLoading(true);
+

setModalProps

用于更改 modal 的 props 参数因为 modal 内容独立成组件,如果在外部页面需要更改 props 可能比较麻烦,所以提供 setModalProps 方便更改内部 modal 的 props

Props 内容可以见下方

Props

TIP

除以下参数外,组件库文档内的 props 也都支持,具体可以参考 antv modal

属性类型默认值可选值说明
titlestring--modal 标题
heightnumber--固定 modal 的高度
minHeightnumber--设置 modal 的最小高度
draggablebooleantruetrue/false是否开启拖拽
useWrapperbooleantruetrue/false是否开启自适应高度,开启后会跟随屏幕变化自适应内容,并出现滚动条
wrapperFooterOffsetnumber0-开启是适应高度后,如果超过屏幕高度,底部和顶部会保持一样的间距,该参数可以用来缩小底部的间距
canFullscreenbooleantruetrue/false是否可以进行全屏
defaultFullscreenbooleanfalsetrue/false默认全屏
loadingbooleanfalsetrue/falseloading 状态
loadingTipstring--loading 文本
showCancelBtnbooleantruetrue/false显示关闭按钮
showOkBtnbooleantruetrue/false显示确认按钮
helpMessagestring , string[]--标题右侧提示文本
centeredbooleanfalsetrue/false是否居中弹窗
cancelTextstring'关闭'-关闭按钮文本
okTextstring'保存'-确认按钮文本
closeFunc() => Promise<boolean>关闭函数-关闭前执行,返回 true 则关闭,否则不关闭

Events

事件回调参数说明
okfunction(e)点击确定回调
cancelfunction(e)点击取消回调
visible-change(visible:boolean)=>{}打开或者关闭触发

Slots

名称说明
default默认区域
footer底部区域(会替换掉默认的按钮)
insertFooter关闭按钮的左边(不使用footer插槽时有效)
centerFooter关闭按钮和确认按钮的中间(不使用footer插槽时有效)
appendFooter确认按钮的右边(不使用footer插槽时有效)
+ + + + \ No newline at end of file diff --git a/components/page.html b/components/page.html new file mode 100644 index 00000000..e7608b04 --- /dev/null +++ b/components/page.html @@ -0,0 +1,67 @@ + + + + + + Page | Vben Admin + + + + + + + + + + + + + + + + +

Page

页面相关组件

PageWrapper

用于包裹页面组件

Usage

<template>
+  <div>
+    <PageWrapper>
+      <template #left>left</template>
+      <template #right>right</template>
+    </PageWrapper>
+  </div>
+</template>
+<script>
+  import { PageWrapper } from '/@/components/Page';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { PageWrapper },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

Props

属性类型默认值说明
titlestring-pageHeader title
dense是否缩小主体区域false为 true 将会取消 padding/margin
contentstring-pageHeader Content 内容
contentStyleobject-主体区域样式
contentClassstring-主体区域 class
contentBackgroundboolean-主体区域背景
contentFullHeightbooleanfalse主体区域是否占满整个屏幕高度
fixedHeightbooleanfalse固定主体区域高度

Slots

pageHeader 的 slot 都支持

名称说明
leftFooterPageFooter 左侧区域
rightFooterPageFooter 右侧区域
headerContentpageHeader 主体内容
default主体区域

用于页面底部工具栏

使用

<template>
+  <div>
+    <PageFooter>
+      <template #left>left</template>
+      <template #right>right</template>
+    </PageFooter>
+  </div>
+</template>
+<script>
+  import { PageFooter } from '/@/components/Page';
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    components: { PageFooter },
+    setup() {
+      return {};
+    },
+  });
+</script>
+

Slots

名称说明
left左侧区域
right右侧区域
+ + + + \ No newline at end of file diff --git a/components/pop-confirm-button.html b/components/pop-confirm-button.html new file mode 100644 index 00000000..2d09ae0f --- /dev/null +++ b/components/pop-confirm-button.html @@ -0,0 +1,42 @@ + + + + + + PopConfirmButton 按钮 | Vben Admin + + + + + + + + + + + + + + + + +

PopConfirmButton 按钮

带有 PopConfirm 下拉菜单功能的按钮

Usage

<template>
+  <PopConfirmButton>按钮文本</PopConfirmButton>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { PopConfirmButton } from '/@/components/Button';
+  export default defineComponent({
+    components: { PopConfirmButton },
+  });
+</script>
+

Props

提示

保持 anv design popconfirm 组件 原有功能的情况下扩展以下属性

属性类型默认值说明
enablebooleantrue是否启用下拉菜单,为 false 则显示默认按钮
+ + + + \ No newline at end of file diff --git a/components/qrcode.html b/components/qrcode.html new file mode 100644 index 00000000..c18b9373 --- /dev/null +++ b/components/qrcode.html @@ -0,0 +1,122 @@ + + + + + + QrCode | Vben Admin + + + + + + + + + + + + + + + + +

QrCode

用于生成二维码的组件

Usage

<template>
+  <QrCode :value="qrCodeUrl" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { QrCode, QrCodeActionType } from '/@/components/Qrcode/index';
+  import LogoImg from '/@/assets/images/logo.png';
+  const qrCodeUrl = 'https://www.vvbin.cn';
+  export default defineComponent({
+    components: { QrCode },
+    setup() {
+      const qrRef = ref<Nullable<QrCodeActionType>>(null);
+      function download() {
+        const qrEl = unref(qrRef);
+        if (!qrEl) return;
+        qrEl.download('文件名');
+      }
+      return {
+        qrCodeUrl,
+        LogoImg,
+        download,
+        qrRef,
+      };
+    },
+  });
+</script>
+<style scoped>
+  .qrcode-demo-item {
+    width: 30%;
+    margin-right: 1%;
+  }
+</style>
+

Props

属性类型默认值可选值说明
valuestring--二维码地址
optionsQRCodeRenderersOptions--二维码配置 ,见 QRCodeRenderersOptions
widthnumber2-宽度
logostring|LogoType--中间 logo 配置,见 LogoType
tag渲染标签canvascanvas | imgimg 不支持内嵌 logo

QRCodeRenderersOptions

/**
+ * 定义margin的宽度。.
+ * Default: 4
+ */
+margin?: number;
+/**
+ * 比例因子。值1表示每个模块1像素(黑点)。
+ * Default: 4
+ */
+scale?: number;
+/**
+ * 为输出图像强制指定宽度。
+ * 如果宽度太小而不能包含qr符号,则此选项将被忽略。
+ * 优先于规模。
+ */
+width?: number;
+color?: {
+  /**
+   * 暗模块的颜色。值必须为十六进制格式(RGBA).
+   * 注意:深色应始终比color.light暗。.
+   * Default: #000000ff
+   */
+  dark?: string;
+  /**
+   * 照明模块的颜色。值必须为十六进制格式(RGBA).
+   * Default: #ffffffff
+   */
+  light?: string;
+};
+
+

LogoType

{
+  // logo图片
+  src: string;
+  // logo大小
+  logoSize: number;
+  // 背景颜色
+  bgColor: string;
+  // logo圆角
+  logoRadius: number;
+}
+

Methods

名称回调参数说明
downloadFunction(fileName:string)下载

事件

名称回调参数说明
done(data: QrcodeDoneEventParams)=>void绘制完成
error(error)=>void生成二维码时发生错误

QrcodeDoneEventParams

{
+  url: string;  // 二维码DataURL数据
+  ctx?: CanvasRenderingContext2D;  // 该对象为画布的2D渲染上下文,仅在tag为canvas时有效,可用于自定义绘制
+}
+

done 事件回调中可以对二维码进行自定义的绘制,示例代码如下:

<QrCode
+  :value="qrCodeUrl"
+  :width="200"
+  @done="onQrcodeDone"
+/>
+
function onQrcodeDone({ ctx }) {
+  if (ctx instanceof CanvasRenderingContext2D) {
+    // 额外绘制
+    ctx.fillStyle = 'black';
+    ctx.font = '16px "微软雅黑"';
+    ctx.textBaseline = 'bottom';
+    ctx.textAlign = 'center';
+    ctx.fillText('你帅你先扫', 100, 195, 200);
+  }
+}
+

有关 CanvasRenderingContext2D 的更多资料以及绘制方法,请参考MDN

+ + + + \ No newline at end of file diff --git a/components/scroll-container.html b/components/scroll-container.html new file mode 100644 index 00000000..43fe6d95 --- /dev/null +++ b/components/scroll-container.html @@ -0,0 +1,89 @@ + + + + + + ScrollContainer | Vben Admin + + + + + + + + + + + + + + + + +

ScrollContainer

参考 element-ui 的 el-scrollbar 组件实现

滚动容器组件

Usage

<template>
+  <div class="p-4">
+    <div class="my-4">
+      <a-button @click="scrollTo(100)">滚动到100px位置</a-button>
+      <a-button @click="scrollTo(800)">滚动到800px位置</a-button>
+      <a-button @click="scrollTo(0)">滚动到顶部</a-button>
+      <a-button @click="scrollBottom()">滚动到底部</a-button>
+    </div>
+    <div class="scroll-wrap">
+      <ScrollContainer ref="scrollRef">
+        <ul>
+          <template v-for="index in 100" :key="index">
+            <li>{{ index }}</li>
+          </template>
+        </ul>
+      </ScrollContainer>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { ScrollContainer, ScrollActionType } from '/@/components/Container/index';
+  export default defineComponent({
+    components: { CollapseContainer, ScrollContainer },
+    setup() {
+      const scrollRef = ref<Nullable<ScrollActionType>>(null);
+      const getScroll = () => {
+        const scroll = unref(scrollRef);
+        if (!scroll) {
+          throw new Error('scroll is Null');
+        }
+        return scroll;
+      };
+
+      function scrollTo(top: number) {
+        getScroll()?.scrollTo(top);
+      }
+
+      function scrollBottom() {
+        getScroll()?.scrollBottom();
+      }
+
+      return {
+        scrollTo,
+        scrollRef,
+        scrollBottom,
+      };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .scroll-wrap {
+    width: 50%;
+    height: 300px;
+    background: #fff;
+  }
+</style>
+

Methods

名称回调参数说明
getScrollWrap()=>HtmlElement获取滚动容器 el
scrollBottomFunction滚动到底部
scrollToFunction(to:number,duration = 500)滚动到指定位置

Slots

名称说明
default默认区域
+ + + + \ No newline at end of file diff --git a/components/strength-meter.html b/components/strength-meter.html new file mode 100644 index 00000000..f17e5570 --- /dev/null +++ b/components/strength-meter.html @@ -0,0 +1,58 @@ + + + + + + StrengthMeter | Vben Admin + + + + + + + + + + + + + + + + +

StrengthMeter

用于校验密码强度

Usage

<template>
+  <div class="p-4 flex justify-center">
+    <div class="demo-wrap p-10">
+      <StrengthMeter placeholder="默认" />
+      <StrengthMeter placeholder="禁用" disabled />
+      <br />
+      <StrengthMeter placeholder="隐藏input" :show-input="false" value="!@#qwe12345" />
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import StrengthMeter from '/@/components/StrengthMeter/index';
+  export default defineComponent({
+    components: {
+      StrengthMeter,
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .demo-wrap {
+    width: 50%;
+    background: #fff;
+    border-radius: 10px;
+  }
+</style>
+

Props

属性类型默认值可选值说明
valuestring--校验的值
showInputbooleantrue-是否显示 input
disabledbooleanfalse-是否禁用

Events

事件回调参数说明
score-changenumber强度值改变触发
changestringinput 值改变触发
+ + + + \ No newline at end of file diff --git a/components/table.html b/components/table.html new file mode 100644 index 00000000..d5b8e7a7 --- /dev/null +++ b/components/table.html @@ -0,0 +1,342 @@ + + + + + + Table 表格 | Vben Admin + + + + + + + + + + + + + + + + +

Table 表格

antv 的 table 组件进行封装

如果文档内没有,可以尝试在在线示例内寻找

Usage

示例

<template>
+  <div class="p-4">
+    <BasicTable
+      title="基础示例"
+      titleHelpMessage="温馨提醒"
+      :columns="columns"
+      :dataSource="data"
+      :canResize="canResize"
+      :loading="loading"
+      :striped="striped"
+      :bordered="border"
+      :pagination="{ pageSize: 20 }"
+    >
+      <template #toolbar>
+        <a-button type="primary"> 操作按钮 </a-button>
+      </template>
+    </BasicTable>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicTable } from '/@/components/Table';
+  import { getBasicColumns, getBasicData } from './tableData';
+
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      return {
+        columns: getBasicColumns(),
+        data: getBasicData(),
+      };
+    },
+  });
+</script>
+

template 示例

所有可调用函数见下方 Methods 说明

<template>
+  <div class="p-4">
+    <BasicTable
+      :canResize="false"
+      title="RefTable示例"
+      titleHelpMessage="使用Ref调用表格内方法"
+      ref="tableRef"
+      :api="api"
+      :columns="columns"
+      rowKey="id"
+      :rowSelection="{ type: 'checkbox' }"
+    />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, unref } from 'vue';
+  import { BasicTable, TableActionType } from '/@/components/Table';
+  import { getBasicColumns, getBasicShortColumns } from './tableData';
+  import { demoListApi } from '/@/api/demo/table';
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      const tableRef = ref<Nullable<TableActionType>>(null);
+
+      function getTableAction() {
+        const tableAction = unref(tableRef);
+        if (!tableAction) {
+          throw new Error('tableAction is null');
+        }
+        return tableAction;
+      }
+      function changeLoading() {
+        getTableAction().setLoading(true);
+        setTimeout(() => {
+          getTableAction().setLoading(false);
+        }, 1000);
+      }
+      return {
+        tableRef,
+        api: demoListApi,
+        columns: getBasicColumns(),
+        changeLoading,
+      };
+    },
+  });
+</script>
+

BasicColumn 和 tableAction 通过权限和业务控制显示隐藏的示例

<template>
+  <div class="p-4">
+    <BasicTable @register="registerTable">
+      <template #action="{ record }">
+        <TableAction
+          :actions="[
+            {
+              label: '编辑',
+              onClick: handleEdit.bind(null, record),
+              auth: 'other', // 根据权限控制是否显示: 无权限,不显示
+            },
+            {
+              label: '删除',
+              icon: 'ic:outline-delete-outline',
+              onClick: handleDelete.bind(null, record),
+              auth: 'super', // 根据权限控制是否显示: 有权限,会显示
+            },
+          ]"
+          :dropDownActions="[
+            {
+              label: '启用',
+              popConfirm: {
+                title: '是否启用?',
+                confirm: handleOpen.bind(null, record),
+              },
+              ifShow: (_action) => {
+                return record.status !== 'enable'; // 根据业务控制是否显示: 非enable状态的不显示启用按钮
+              },
+            },
+            {
+              label: '禁用',
+              popConfirm: {
+                title: '是否禁用?',
+                confirm: handleOpen.bind(null, record),
+              },
+              ifShow: () => {
+                return record.status === 'enable'; // 根据业务控制是否显示: enable状态的显示禁用按钮
+              },
+            },
+            {
+              label: '同时控制',
+              popConfirm: {
+                title: '是否动态显示?',
+                confirm: handleOpen.bind(null, record),
+              },
+              auth: 'super', // 同时根据权限和业务控制是否显示
+              ifShow: () => {
+                return true; // 根据业务控制是否显示
+              },
+            },
+          ]"
+        />
+      </template>
+    </BasicTable>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTable, useTable, BasicColumn, TableAction } from '/@/components/Table';
+
+  import { demoListApi } from '/@/api/demo/table';
+  const columns: BasicColumn[] = [
+    {
+      title: '姓名',
+      dataIndex: 'name',
+      auth: 'test', // 根据权限控制是否显示: 无权限,不显示
+    },
+    {
+      title: '地址',
+      dataIndex: 'address',
+      auth: 'super', // 同时根据权限控制是否显示
+      ifShow: (_column) => {
+        return true; // 根据业务控制是否显示
+      },
+    },
+  ];
+  export default defineComponent({
+    components: { BasicTable, TableAction },
+    setup() {
+      const [registerTable] = useTable({
+        title: 'TableAction组件及固定列示例',
+        api: demoListApi,
+        columns: columns,
+        bordered: true,
+        actionColumn: {
+          width: 250,
+          title: 'Action',
+          dataIndex: 'action',
+          slots: { customRender: 'action' },
+        },
+      });
+      function handleEdit(record: Recordable) {
+        console.log('点击了编辑', record);
+      }
+      function handleDelete(record: Recordable) {
+        console.log('点击了删除', record);
+      }
+      function handleOpen(record: Recordable) {
+        console.log('点击了启用', record);
+      }
+      return {
+        registerTable,
+        handleEdit,
+        handleDelete,
+        handleOpen,
+      };
+    },
+  });
+</script>
+

useTable

使用组件自带的 useTable 可以方便使用表单

下面是一个使用简单表格的示例,

<template>
+  <BasicTable @register="registerTable" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTable, useTable } from '/@/components/Table';
+  import { getBasicColumns, getBasicShortColumns } from './tableData';
+  import { demoListApi } from '/@/api/demo/table';
+  export default defineComponent({
+    components: { BasicTable },
+    setup() {
+      const [
+        registerTable,
+        {
+          setLoading,
+        },
+      ] = useTable({
+        api: demoListApi,
+        columns: getBasicColumns(),
+      });
+
+      function changeLoading() {
+        setLoading(true);
+        setTimeout(() => {
+          setLoading(false);
+        }, 1000);
+      }
+      }
+      return {
+        registerTable,
+        changeLoading,
+      };
+    },
+  });
+</script>
+

Usage

用于调用 Table 内部方法及 table 参数配置

// 表格的props也可以直接注册到useTable内部
+const [register, methods] = useTable(props);
+

register

register 用于注册 useTable,如果需要使用useTable提供的 api,必须将 register 传入组件的 onRegister

<template>
+  <BasicTable @register="register" />
+</template>
+<script>
+  export default defineComponent({
+    components: { BasicForm },
+    setup() {
+      const [register] = useTable();
+      return { register };
+    },
+  });
+</script>
+

Methods

setProps

类型:(props: Partial<BasicTableProps>) => void

说明: 用于设置表格参数

reload

类型:(opt?: FetchParams) => Promise<void>

说明: 刷新表格

redoHeight

类型:() => void

说明: 重新计算表格高度

setLoading

类型:(loading: boolean) => void

说明: 设置表格 loading 状态

getDataSource

获取表格数据

类型:<T = Recordable>() => T[]

说明: 获取表格数据

getRawDataSource

获取后端接口原始数据

类型:<T = Recordable>() => T

说明: 获取后端接口原始数据

getColumns

类型:(opt?: GetColumnsParams) => BasicColumn[]

说明: 获取表格数据

setColumns

类型:(columns: BasicColumn[] | string[]) => void

说明: 设置表头数据

setTableData

类型:<T = Recordable>(values: T[]) => void

说明: 设置表格数据

setPagination

类型:(info: Partial<PaginationProps>) => void

说明: 设置分页信息

deleteSelectRowByKey

类型:(key: string) => void

说明: 根据 key 删除取消选中行

getSelectRowKeys

类型:() => string[]

说明: 获取选中行的 keys

getSelectRows

类型:<T = Recordable>() => T[]

说明: 获取选中行的 rows

clearSelectedRowKeys

类型:() => void

说明: 清空选中行

setSelectedRowKeys

类型:(rowKeys: string[] | number[]) => void

说明: 设置选中行

getPaginationRef

类型:() => PaginationProps | boolean

说明: 获取当前分页信息

getShowPagination

类型:() => boolean

说明: 获取当前是否显示分页

setShowPagination

类型:(show: boolean) => Promise<void>

说明: 设置当前是否显示分页

getRowSelection

类型:() => TableRowSelection<Recordable>

说明: 获取勾选框信息

updateTableData

类型:(index: number, key: string, value: any)=>void

说明: 更新表格数据

updateTableDataRecord

类型: (rowKey: string | number, record: Recordable) => Recordable | void

说明: 根据唯一的 rowKey 更新指定行的数据.可用于不刷新整个表格而局部更新数据

deleteTableDataRecord

类型: (rowKey: string | number | string[] | number[]) => void

说明: 根据唯一的rowKey 动态删除指定行的数据.可用于不刷新整个表格而局部更新数据

insertTableDataRecord

类型: (record: Recordable, index?: number) => Recordable | void

说明: 可根据传入的 index 值决定插入数据行的位置,不传则是顺序插入,可用于不刷新整个表格而局部更新数据

getForm

类型:() => FormActionType

说明: 如果开启了搜索区域。可以通过该函数获取表单对象函数进行操作

expandAll

类型:() => void

说明: 展开树形表格

collapseAll

类型:() => void

说明: 折叠树形表格

Props

温馨提醒

  • 除以下参数外,官方文档内的 props 也都支持,具体可以参考 antv table
  • 注意:defaultExpandAllRowsdefaultExpandedRowKeys 属性在basicTable中不受支持,并且在antv table v2.2.0之后也被移除。
属性类型默认值可选值说明版本
clickToRowSelectbooleantrue-点击行是否选中 checkbox 或者 radio。需要开启
sortFn(sortInfo: SorterResult<any>) => any--自定义排序方法。见下方全局配置说明
filterFn(sortInfo: Partial<Recordable<string[]>>) => any--自定义过滤方法。见下方全局配置说明
showTableSettingbooleanfalse-显示表格设置工具
tableSettingTableSetting--表格设置工具配置,见下方 TableSetting
stripedbooleantrue-斑马纹
insetbooleanfalse-取消表格的默认 padding
autoCreateKeybooleantrue-是否自动生成 key
showSummarybooleanfalse-是否显示合计行
summaryDataany[]--自定义合计数据。如果有则显示该数据
emptyDataIsShowTablebooleantrue-在启用搜索表单的前提下,是否在表格没有数据的时候显示表格
summaryFunc(...arg) => any[]--计算合计行的方法
canRowDragbooleanfalse-是否可拖拽行排序
canColDragbooleanfalse-是否可拖拽列
isTreeTablebooleanfalse-是否树表
api(...arg: any) => Promise<any>--请求接口,可以直接将src/api内的函数直接传入
beforeFetch(T)=>T--请求之前对参数进行处理
afterFetch(T)=>T--请求之后对返回值进行处理
handleSearchInfoFn(T)=>T--开启表单后,在请求之前处理搜索条件参数
fetchSettingFetchSetting--接口请求配置,可以配置请求的字段和响应的字段名,见下方全局配置说明
immediatebooleantrue-组件加载后是否立即请求接口,在 api 有传的情况下,如果为 false,需要自行使用 reload 加载表格数据
searchInfoany--额外的请求参数
useSearchFormbooleanfalse-使用搜索表单
formConfigany--表单配置,参考表单组件的 Props
columnsany--表单列信息 BasicColumn[]
showIndexColumnbooleanture-是否显示序号列
indexColumnPropsany--序号列配置 BasicColumn
actionColumnany--表格右侧操作列配置 BasicColumn
ellipsisbooleantrue-文本超过宽度是否显示...
canResizebooleantrue-是否可以自适应高度(如果置于PageWrapper组件内,请勿启用PageWrapper的fixedHeight属性,二者不可同时使用)
clearSelectOnPageChangebooleanfalse-切换页码是否重置勾选状态
resizeHeightOffsetnumber0-表格自适应高度计算结果会减去这个值
rowSelectionany--选择列配置
titlestring--表格标题
titleHelpMessagestring | string[]--表格标题右侧温馨提醒
maxHeightnumber--表格最大高度,超出会显示滚动条
dataSourceany[]--表格数据,非 api 加载情况
borderedbooleanfalse-是否显示表格边框
paginationany--分页信息配置,为 false 不显示分页
loadingbooleanfalse-表格 loading 状态
scrollany--参考官方文档 scroll
beforeEditSubmit({record: Recordable,index: number,key: string | number,value: any}) => Promise<any>--单元格编辑状态提交回调,返回false将阻止单元格提交数据到table。该回调在行编辑模式下无效。2.7.2

TableSetting

{
+  // 是否显示刷新按钮
+  redo?: boolean;
+  // 是否显示尺寸调整按钮
+  size?: boolean;
+  // 是否显示字段调整按钮
+  setting?: boolean;
+  // 是否显示全屏按钮
+  fullScreen?: boolean;
+}
+

BasicColumn

除 参考官方 Column 配置外,扩展以下参数

属性类型默认值可选值说明
defaultHiddenbooleanfalse-默认隐藏,可在列配置显示
helpMessagestring|string[]--列头右侧帮助文本
editboolean--是否开启单元格编辑
editRowboolean--是否开启行编辑
editablebooleanfalse-是否处于编辑状态
editComponentComponentTypeInput-编辑组件
editComponentPropsany--对应编辑组件的 props
editRule((text: string, record: Recordable) => Promise<string>)--对应编辑组件的表单校验
editValueMap(value: any) => string--对应单元格值枚举
onEditRow()=>void--触发行编辑
formatCellFormat--单元格格式化
authRoleEnumRoleEnum[]stringstring[]--根据权限编码来控制当前列是否显示
ifShowboolean | ((action: ActionItem) => boolean)--根据业务状态来控制当前列是否显示

EditComponentType

export type ComponentType =
+  | 'Input'
+  | 'InputNumber'
+  | 'Select'
+  | 'ApiSelect'
+  | 'Checkbox'
+  | 'Switch'
+  | 'DatePicker'  // v2.5.0 以上
+  | 'TimePicker'; // v2.5.0 以上
+

CellFormat

export type CellFormat =
+  | string
+  | ((text: string, record: Recordable, index: number) => string | number)
+  | Map<string | number, any>;
+

事件

温馨提醒

除以下事件外,官方文档内的 event 也都支持,具体可以参考 antv table

事件回调参数说明
fetch-successFunction({items,total})接口请求成功后触发
fetch-errorFunction(error)错误信息
selection-changeFunction({keys,rows})勾选事件触发
row-clickFunction(record, index, event)行点击触发
row-dbClickFunction(record, index, event)行双击触发
row-contextmenuFunction(record, index, event)行右键触发
row-mouseenterFunction(record, index, event)行移入触发
row-mouseleaveFunction(record, index, event)行移出触发
edit-endFunction({record, index, key, value})单元格编辑完成触发
edit-cancelFunction({record, index, key, value})单元格取消编辑触发
edit-row-endFunction()行编辑结束触发
edit-changeFunction({column,value,record})单元格编辑组件的 value 发生变化时触发

edit-change 说明

从版本 2.4.2 起,对于 edit-change 事件,record 中的 editValueRefs 装载了当前行的所有编辑组件(如果有的话)的值的 ref 对象,可用于处理同一行中的编辑组件的联动。请看下面的例子

      function onEditChange({ column, record }) {
+        // 当同一行的单价或者数量发生变化时,更新合计金额(三个数据均为当前行编辑组件的值)
+        if (column.dataIndex === 'qty' || column.dataIndex === 'price') {
+          const { editValueRefs: { total, qty, price } } = record;
+          total.value = unref(qty) * unref(price);
+        }
+      }
+

Slots

温馨提醒

除以下参数外,官方文档内的 slot 也都支持,具体可以参考 antv table

名称说明版本
tableTitle表格顶部左侧区域
toolbar表格顶部右侧区域
expandedRowRender展开行区域
headerTop表格顶部区域(标题上方)2.6.1

Form-Slots

当开启 form 表单后。以form-xxxx为前缀的 slot 会被视为 form 的 slot

xxxx 为 form 组件的 slot。具体参考form 组件文档

e.g

form-submitBefore
+

ColumnSetting组件

字段调整组件

提供了可视化操作表格每一列的是否展示、位置、固定;包括序号列、勾选列。会响应tableMethodssetColumnssetProps方法的更改内容。

值得注意的是

序号列勾选列是在table的props中定义的,对应的字段分别是showIndexColumnrowSelection。因此在动态改变表格列配置的时候,建议使用setProps方法,并显式地设置这两个字段的值来保证达到预期效果

// ...
+const [registerTable, { setProps }] = useTable({...})
+
+setProps({
+  columns: [], // 表格的列配置 BasicColumn[]
+  showIndexColumn: false, // 是否展示序号列
+  rowSelection: false // 勾选列配置
+})
+

内置组件(只能用于表格内部)

TableAction

用于表格右侧操作列渲染

Props

属性类型默认值可选值说明版本
actionsActionItem[]--右侧操作列按钮列表
dropDownActionsActionItem[]--右侧操作列更多下拉按钮列表
stopButtonPropagationbooleanfalsetrue/false是否阻止操作按钮的click事件冒泡2.5.0

ActionItem

export interface ActionItem {
+  // 按钮文本
+  label: string;
+  // 是否禁用
+  disabled?: boolean;
+  // 按钮颜色
+  color?: 'success' | 'error' | 'warning';
+  // 按钮类型
+  type?: string;
+  // button组件props
+  props?: any;
+  // 按钮图标
+  icon?: string;
+  // 气泡确认框
+  popConfirm?: PopConfirm;
+  // 是否显示分隔线,v2.0.0+
+  divider?: boolean;
+  // 根据权限编码来控制当前列是否显示,v2.4.0+
+  auth?: RoleEnum | RoleEnum[] | string | string[];
+  // 根据业务状态来控制当前列是否显示,v2.4.0+
+  ifShow?: boolean | ((action: ActionItem) => boolean);
+  // 点击回调
+  onClick?: Fn;
+  // Tooltip配置,2.5.3以上版本支持,可以配置为string,或者完整的tooltip属性
+  tooltip?: string | TooltipProps
+}
+

有关TooltipProps的说明,请参考tooltip

PopConfirm

export interface PopConfirm {
+  title: string;
+  okText?: string;
+  cancelText?: string;
+  confirm: Fn;
+  cancel?: Fn;
+  icon?: string;
+}
+

TableImg

用于渲染单元格图片,支持图片预览

Props

属性类型默认值可选值说明版本
imgListstring[]--图片地址列表
sizenumber--图片大小
simpleShowbooleanfalsetrue/false简单显示模式(只显示第一张图片)2.5.0
showBadgebooleantruetrue/false简单模式下是否显示计数Badge2.5.0
marginnumber4-常规模式下的图片间距2.5.0
srcPrefixstring--在每一个图片src前插入的内容2.5.0

全局配置

componentsSettings 可以配置全局参数。用于统一整个项目的风格。可以通过 props 传值覆盖

+ + + + \ No newline at end of file diff --git a/components/time.html b/components/time.html new file mode 100644 index 00000000..08dc086a --- /dev/null +++ b/components/time.html @@ -0,0 +1,52 @@ + + + + + + Time | Vben Admin + + + + + + + + + + + + + + + + +

Time

相对时间组件

Usage

<template>
+  <Time :value="time" />
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, toRefs } from 'vue';
+  import { Time } from '/@/components/Time';
+
+  export default defineComponent({
+    components: { Time },
+    setup() {
+      const now = new Date().getTime();
+      const state = reactive({
+        time: now - 60 * 3 * 1000,
+      });
+      return {
+        ...toRefs(state),
+        now,
+      };
+    },
+  });
+</script>
+

Props

属性类型默认值可选值说明
valuestring,Date,number--时间值
stepnumber60-刷新时间
modestringrelative-模式,date:日期,datetime:时间戳,relative:相对时间
+ + + + \ No newline at end of file diff --git a/components/tinymce.html b/components/tinymce.html new file mode 100644 index 00000000..07a44933 --- /dev/null +++ b/components/tinymce.html @@ -0,0 +1,50 @@ + + + + + + Tinymce | Vben Admin + + + + + + + + + + + + + + + + +

Tinymce

富文本组件位于 src/components/TinyMce

富文本组件使用的是 CDN 方式引入

可在 /@/components/TinyMce/src/Editor.vue 更改下面 CDN 地址

const CDN_URL = 'https://cdn.bootcdn.net/ajax/libs/tinymce/5.5.1';
+

Usage

<template>
+  <Tinymce v-model="value" @change="handleChange" width="100%" />
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { Tinymce } from '/@/components/Tinymce/index';
+
+  export default defineComponent({
+    components: { Tinymce },
+    setup() {
+      const value = ref('hello world!');
+      function handleChange(value: string) {
+        console.log(value);
+      }
+      return { handleChange, value };
+    },
+  });
+</script>
+

Props

属性类型默认值说明
optionsany{}tinymce 的配置项
value(v-model)string-双向绑定值
heightnumber , string400高度
widthnumber , stringauto宽度
toolbarstring[]-工具栏
pluginsstring[]-插件
showImageUploadbooleantrue是否显示上传按钮

Events

事件回调参数返回值说明
change(str:string)=>{}富文本内容改变触发事件
+ + + + \ No newline at end of file diff --git a/components/transition.html b/components/transition.html new file mode 100644 index 00000000..6c085456 --- /dev/null +++ b/components/transition.html @@ -0,0 +1,125 @@ + + + + + + Transition | Vben Admin + + + + + + + + + + + + + + + + +

Transition

用于页面/组件切换动画

Usage

<template>
+  <div class="p-4">
+    <div class="flex">
+      <Select
+        :options="options"
+        v-model:value="value"
+        placeholder="选择动画"
+        :style="{ width: '150px' }"
+      />
+      <a-button type="primary" class="ml-4" @click="start"> start </a-button>
+    </div>
+    <component :is="`${value}Transition`">
+      <div class="box" v-show="show"></div>
+    </component>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { Select } from 'ant-design-vue';
+  import {
+    FadeTransition,
+    ScaleTransition,
+    SlideYTransition,
+    ScrollYTransition,
+    SlideYReverseTransition,
+    ScrollYReverseTransition,
+    SlideXTransition,
+    ScrollXTransition,
+    SlideXReverseTransition,
+    ScrollXReverseTransition,
+    ScaleRotateTransition,
+    ExpandXTransition,
+    ExpandTransition,
+  } from '/@/components/Transition/index';
+
+  const transitionList = [
+    'Fade',
+    'Scale',
+    'SlideY',
+    'ScrollY',
+    'SlideYReverse',
+    'ScrollYReverse',
+    'SlideX',
+    'ScrollX',
+    'SlideXReverse',
+    'ScrollXReverse',
+    'ScaleRotate',
+    'ExpandX',
+    'Expand',
+  ];
+  const options = transitionList.map((item) => ({
+    label: item,
+    value: item,
+    key: item,
+  }));
+
+  export default defineComponent({
+    components: {
+      Select,
+      FadeTransition,
+      ScaleTransition,
+      SlideYTransition,
+      ScrollYTransition,
+      SlideYReverseTransition,
+      ScrollYReverseTransition,
+      SlideXTransition,
+      ScrollXTransition,
+      SlideXReverseTransition,
+      ScrollXReverseTransition,
+      ScaleRotateTransition,
+      ExpandXTransition,
+      ExpandTransition,
+    },
+    setup() {
+      const value = ref('Fade');
+      const show = ref(true);
+      function start() {
+        show.value = false;
+        setTimeout(() => {
+          show.value = true;
+        }, 300);
+      }
+      return { options, value, start, show };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .box {
+    width: 150px;
+    height: 150px;
+    margin-top: 20px;
+    background: pink;
+  }
+</style>
+
+ + + + \ No newline at end of file diff --git a/components/tree.html b/components/tree.html new file mode 100644 index 00000000..7787b29a --- /dev/null +++ b/components/tree.html @@ -0,0 +1,104 @@ + + + + + + Tree | Vben Admin + + + + + + + + + + + + + + + + +

Tree

antv 的 tree 组件进行封装

Usage

<template>
+  <BasicTree :treeData="treeData" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicTree } from '/@/components/Tree/index';
+  import { treeData } from './data';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import { TreeItem } from '/@/components/Tree/index';
+
+  export const treeData: TreeItem[] = [
+    {
+      title: 'parent 1',
+      key: '0-0',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '0-0-0' },
+        {
+          title: 'leaf',
+          key: '0-0-1',
+          children: [
+            { title: 'leaf', key: '0-0-0-0' },
+            { title: 'leaf', key: '0-0-0-1' },
+          ],
+        },
+      ],
+    },
+    {
+      title: 'parent 2',
+      key: '1-1',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '1-1-0' },
+        { title: 'leaf', key: '1-1-1' },
+      ],
+    },
+    {
+      title: 'parent 3',
+      key: '2-2',
+      icon: 'home|svg',
+      children: [
+        { title: 'leaf', key: '2-2-0' },
+        { title: 'leaf', key: '2-2-1' },
+      ],
+    },
+  ];
+  export default defineComponent({
+    components: { BasicTree, CollapseContainer },
+    setup() {
+      return { treeData };
+    },
+  });
+</script>
+

Props

温馨提醒

除以下参数外,官方文档内的 props 也都支持,具体可以参考 antv tree

属性类型默认值可选值说明版本
treeDataTreeItem[]--树组件数据
rightMenuListContextMenuItem[]--右键菜单列表
checkedKeysstring[]--勾选的节点
selectedKeysstring[]--选中的节点
expandedKeysstring[]--展开的节点
actionListActionItem[]--鼠标移动上去右边操作按钮列表
titlestring--定制标题字符串
toolbarboolean--是否显示工具栏
searchboolean--显示搜索框
clickRowToExpandboolean--是否在点击行时自动展开
beforeRightClick(node, event)=>ContextMenuItem[]--右键点击回调,可返回右键菜单列表数据来生成右键菜单
rightMenuListContextMenuItem[]--右键菜单列表数据
defaultExpandLevelstring | number--初次渲染后默认展开的层级2.4.1
defaultExpandAllbooleanfalsetrue/false初次渲染后默认全部2.4.1
searchValue(v-model)string--当前搜索词2.7.1

注意

defaultExpandLeveldefaultExpandAll 仅在初次渲染时生效。如果basicTree是在创建完毕之后才设置的treeData(如异步数据),需要在更新后自己调用basicTree提供的expandAllfilterByLevel来执行展开

ActionItem

{
+  // 渲染的图标
+  render: (record: any) => any;
+  // 是否显示
+  show?: boolean | ((record: Recordable) => boolean);
+}
+

ContextMenuItem

{
+  // 文本
+  label: string;
+  // 图标
+  icon?: string;
+  // 是否禁用
+  disabled?: boolean;
+  // 事件
+  handler?: (...arg) => any;
+  // 是否显示分隔线
+  divider?: boolean;
+  // 子级菜单数据
+  children?: ContextMenuItem[];
+}
+

Slots

温馨提醒

官方文档内的 slot 都支持,具体可以参考 antv tree

Methods

名称回调参数说明
checkAll(checkAll: boolean) => void选择所有
expandAll(expandAll: boolean) => void展开所有
setExpandedKeys(keys: Keys) => void设置展开节点
getExpandedKeys() => Keys获取展开节点
setSelectedKeys(keys: Keys) => void设置选中节点
getSelectedKeys() => Keys获取选中节点
setCheckedKeys(keys: CheckKeys) => void设置勾选节点
getCheckedKeys() => CheckKeys获取勾选节点
filterByLevel(level: number) => void显示指定等级
insertNodeByKey(opt: InsertNodeParams) => void插入子节点到指定节点内
deleteNodeByKey(key: string) => void根据 key 删除节点
updateNodeByKey(key: string, node: Omit<TreeItem, 'key'>) => void根据 key 更新节点
setSearchValue(value: string) => void设置当前搜索词(v2.7.1)
getSearchValue() => string获取当前搜索词(v2.7.1)
+ + + + \ No newline at end of file diff --git a/components/upload.html b/components/upload.html new file mode 100644 index 00000000..5dedd1ed --- /dev/null +++ b/components/upload.html @@ -0,0 +1,61 @@ + + + + + + Upload | Vben Admin + + + + + + + + + + + + + + + + +

Upload

文件上传组件

Usage

<template>
+  <BasicUpload :maxSize="20" :maxNumber="10" @change="handleChange" :api="uploadApi" />
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicUpload } from '/@/components/Upload';
+  import { uploadApi } from '/@/api/sys/upload';
+
+  export default defineComponent({
+    components: { BasicUpload },
+    setup() {
+      return {
+        uploadApi,
+        handleChange: (list: string[]) => {
+          createMessage.info(`已上传文件${JSON.stringify(list)}`);
+        },
+      };
+    },
+  });
+</script>
+

Config

.env.development.env.production 配置开发和生产的文件上传地址

# .env.development
+
+VITE_PROXY=[["/upload","http://localhost:3001/upload"]]
+
+# 如果没有跨域问题,则直接使用真实上传地址
+VITE_GLOB_UPLOAD_URL=/upload
+
+# .env.production
+VITE_GLOB_UPLOAD_URL=/upload
+
+

Props

属性类型默认值可选值说明
valuestring[]--已上传的文件列表,支持v-model
showPreviewNumberbooleantrue-是否显示预览数量
emptyHidePreviewbooleanfalse-没有上传文件时是否隐藏预览
helpTextstring--帮助文本
maxSizenumber2-单个文件最大体积,单位 M
maxNumbernumberInfinity-最大上传数量,Infinity 则不限制
acceptstring[]--限制上传格式,可使用文件后缀名(点号可选)或MIME字符串。例如 ['.doc,','docx','application/msword','image/*']
multipleboolean--开启多文件上传
uploadParamsany--上传携带的参数
apiFn--上传接口,为上面配置的接口

Events

事件回调参数返回值说明版本
change(fileList)=>void文件列表内容改变触发事件
delete(record)=>void在上传列表中删除文件的事件
preview-delete(url:string)=>void在预览列表中删除文件的事件2.5.3
+ + + + \ No newline at end of file diff --git a/components/verify.html b/components/verify.html new file mode 100644 index 00000000..2cbada77 --- /dev/null +++ b/components/verify.html @@ -0,0 +1,76 @@ + + + + + + BasicDragVerify | Vben Admin + + + + + + + + + + + + + + + + +

BasicDragVerify

拖动校验组件

BasicDragVerify

Usage

<template>
+  <div class="p-10">
+    <BasicDragVerify @success="handleSuccess" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicDragVerify, DragVerifyActionType, PassingData } from '/@/components/Verify/index';
+  export default defineComponent({
+    components: { BasicDragVerify },
+    setup() {
+      function handleSuccess(data: PassingData) {
+        const { time } = data;
+        createMessage.success(`校验成功,耗时${time}`);
+      }
+      return {
+        handleSuccess,
+        handleBtnClick,
+      };
+    },
+  });
+</script>
+

Props

属性类型默认值说明
valueboolean-是否通过
textstring请按住滑块拖动未拖动时候显示文字
successTextstring验证通过验证成功后显示文本
heightstring|string40高度
widthstring|string260宽度
circlebooleanfalse是否圆角
wrapStyleany-外层容器样式
contentStyleany-主体内容样式
barStyleany-bar 样式
actionStyleany-拖拽按钮样式

Methods

名称回调参数说明
resume()=>{}还原初始值

RotateDragVerify

图片还原正方向校验组件

Usage

<template>
+  <div class="p-10">
+    <RotateDragVerify :src="img" ref="el" @success="handleSuccess" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { RotateDragVerify } from '/@/components/Verify/index';
+
+  import img from '/@/assets/images/header.jpg';
+  export default defineComponent({
+    components: { RotateDragVerify },
+    setup() {
+      const handleSuccess = () => {
+        console.log('success!');
+      };
+      return {
+        handleSuccess,
+        img,
+      };
+    },
+  });
+</script>
+

props

属性类型默认值说明
srcstring-图片地址
imgWidthnumber-图片宽度
imgWrapStyleany-图片外层容器样式
minDegreenumber-最小旋转角度
maxDegreenumber-最大旋转角度
diffDegreenumber-误差角度
valueboolean-是否通过
textstring请按住滑块拖动未拖动时候显示文字
successTextstring验证通过验证成功后显示文本
heightstring|string40高度
widthstring|string260宽度
circlebooleanfalse是否圆角
wrapStyleany-外层容器样式
contentStyleany-主体内容样式
barStyleany-bar 样式
actionStyleany-拖拽按钮样式

Methods

名称回调参数说明
resumeFunction还原初始值
+ + + + \ No newline at end of file diff --git a/components/virtual-scroll.html b/components/virtual-scroll.html new file mode 100644 index 00000000..eb1825f1 --- /dev/null +++ b/components/virtual-scroll.html @@ -0,0 +1,90 @@ + + + + + + VirtualScroll | Vben Admin + + + + + + + + + + + + + + + + +

VirtualScroll

虚拟滚动组件(用于大量数据纯展示时使用)

Usage

<template>
+  <div class="p-4 virtual-scroll-demo">
+    <Divider>基础滚动示例</Divider>
+    <div class="virtual-scroll-demo-wrap">
+      <VirtualScroll :itemHeight="41" :items="data" :height="300" :width="300">
+        <template v-slot="{ item }">
+          <div class="virtual-scroll-demo__item">{{ item.title }}</div>
+        </template>
+      </VirtualScroll>
+    </div>
+
+    <Divider>即使不可见,也预先加载50条数据,防止空白</Divider>
+    <div class="virtual-scroll-demo-wrap">
+      <VirtualScroll :itemHeight="41" :items="data" :height="300" :width="300" :bench="50">
+        <template v-slot="{ item }">
+          <div class="virtual-scroll-demo__item">{{ item.title }}</div>
+        </template>
+      </VirtualScroll>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { VirtualScroll } from '/@/components/VirtualScroll/index';
+
+  import { Divider } from 'ant-design-vue';
+  const data: any[] = (() => {
+    const arr: any[] = [];
+    for (let index = 1; index < 20000; index++) {
+      arr.push({
+        title: '列表项' + index,
+      });
+    }
+    return arr;
+  })();
+  export default defineComponent({
+    components: { VirtualScroll, Divider },
+    setup() {
+      return { data: data };
+    },
+  });
+</script>
+<style lang="less" scoped>
+  .virtual-scroll-demo {
+    &-wrap {
+      display: flex;
+      margin: 0 30%;
+      background: #fff;
+      justify-content: center;
+    }
+
+    /deep/ &__item {
+      height: 40px;
+      padding: 0 20px;
+      line-height: 40px;
+      border-bottom: 1px solid #ddd;
+    }
+  }
+</style>
+

Props

属性类型默认值可选值说明
heightstring|number--高度
widthstring|number--宽度
maxHeightstring|number--最大高度
maxWidthstring|number--最大宽度
minHeightstring|number--最小高度
minWidthstring|number--最小宽度
itemHeightstring|number--每个选项高度,必传
itemsany[]--选项列表

Slots

名称说明
default默认
+ + + + \ No newline at end of file diff --git a/dep/cors.html b/dep/cors.html new file mode 100644 index 00000000..d85b3355 --- /dev/null +++ b/dep/cors.html @@ -0,0 +1,31 @@ + + + + + + 跨域处理 | Vben Admin + + + + + + + + + + + + + + + + +

跨域处理

产生原因

跨域产生的原因是由于前端地址与后台接口不是同源,从而导致 ajax 不能发送

非同源产生的问题

  1. Cookie、LocalStorage 和 IndexDB 无法获取
  2. DOM 无法获得
  3. AJAX 请求不能发送

同源条件

协议端口主机 三者相同即为同源

反之,其中只要 某一个 不一样则为不同源

解决方式

本地开发跨域

本地开发一般使用下面 3 种方式进行处理

  1. vite 的 proxy 进行代理
  2. 后台开启 cors
  3. 使用 nginx 转发请求

项目内部自带第一种方式,具体可以参考服务端交互-本地开发环境接口地址修改

生产环境跨域

生产环境一般使用下面 2 种方式进行处理

  1. 后台开启 cors
  2. 使用 nginx 转发请求

后台开启 cors 不需要前端做任何改动

nginx 配置文件可以查看nginx 配置

+ + + + \ No newline at end of file diff --git a/dep/dark.html b/dep/dark.html new file mode 100644 index 00000000..0c4567b8 --- /dev/null +++ b/dep/dark.html @@ -0,0 +1,56 @@ + + + + + + 黑暗主题 | Vben Admin + + + + + + + + + + + + + + + + +

黑暗主题

介绍

项目已经内置了黑暗主题切换,只需配置自己需要的颜色变量,即可在项目中使用

原理

通过 vite-plugin-theme 插件,将所有的颜色变量抽取到独立的 css 文件,并且全部在 html 上面加上 css 选择器。通过改变 html 标签的 data-theme 属性来进行黑暗主题切换

配置

黑暗主题颜色配置通过 vite-plugin-theme 实现,具体代码在 build/vite/plugin/theme

antdDarkThemePlugin({
+  darkModifyVars: {
+    ...generateModifyVars(true),
+    'text-color': '#c9d1d9',
+    'text-color-base': '#c9d1d9',
+    'component-background': '#151515',
+    'text-color-secondary': '#8b949e',
+    'border-color-base': '#303030',
+    'item-active-bg': '#111b26',
+    'app-content-background': 'rgb(255 255 255 / 4%)',
+  },
+});
+

切换

只需要使用 vite-plugin-theme 提供的函数来进行切换即可

import { darkCssIsReady, loadDarkThemeCss } from 'vite-plugin-theme/es/client';
+
+export async function updateDarkTheme(mode: string | null = 'light') {
+  const htmlRoot = document.getElementById('htmlRoot');
+  if (mode === 'dark') {
+    if (import.meta.env.PROD && !darkCssIsReady) {
+      await loadDarkThemeCss();
+    }
+    htmlRoot?.setAttribute('data-theme', 'dark');
+  } else {
+    htmlRoot?.setAttribute('data-theme', 'light');
+  }
+}
+
+ + + + \ No newline at end of file diff --git a/dep/i18n.html b/dep/i18n.html new file mode 100644 index 00000000..4d7415fd --- /dev/null +++ b/dep/i18n.html @@ -0,0 +1,150 @@ + + + + + + 国际化 | Vben Admin + + + + + + + + + + + + + + + + +

国际化

如果你使用的 vscode 开发工具,则推荐安装 I18n-ally 这个插件

I18n-ally 插件

安装了该插件后,你的代码内可以实时看到对应的语言内容

配置默认语言

src/settings/localeSetting.ts 内可以配置默认语言

export const LOCALE: { [key: string]: LocaleType } = {
+  ZH_CN: 'zh_CN',
+  EN_US: 'en',
+};
+
+export const localeSetting: LocaleSetting = {
+  // 是否显示语言选择器
+  showPicker: true,
+  // 当前语言
+  locale: LOCALE.ZH_CN,
+  // 默认语言
+  fallback: LOCALE.ZH_CN,
+  // 允许的语言
+  availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US],
+};
+
+// 配置语言列表
+export const localeList: DropMenu[] = [
+  {
+    text: '简体中文',
+    event: 'zh_CN',
+  },
+  {
+    text: 'English',
+    event: 'en',
+  },
+];
+

配置

src/locales/setupI18n.ts 内引入的 i18n 这个无需修改

语言文件

src/locales/lang/ 可以配置具体的语言

# locales/lang/
+
+# 中文语言
+zh_CN:
+  component: 组件相关
+  layout: 布局相关
+  routes: 路由菜单相关
+  sys: 系统页面相关
+
+en: 同上
+
+

语言导入逻辑说明

  1. 初始化

src/locales/setupI18n 内的根语言文件可以看到

const defaultLocal = await import(`./lang/${locale}.ts`);
+

这会导入 src/locales/lang/{lang}.ts 文件语言包,此文件会导入对应语言下的所有文件。

import { genMessage } from '../helper';
+import antdLocale from 'ant-design-vue/es/locale/zh_CN';
+import momentLocale from 'moment/dist/locale/zh-cn';
+
+const modules = import.meta.globEager('./zh_CN/**/*.ts');
+export default {
+  message: {
+    ...genMessage(modules, 'zh_CN'),
+    antdLocale,
+  },
+  momentLocale,
+  momentLocaleName: 'zh-cn',
+};
+

并将其按相应的目录结构转化为多层级的

例:

lang/zh_CN/components/modal.ts 的文件内容为

{
+  title: '标题';
+}
+

则在使用的使用直接使用 t('components.modal.title') 进行获取。

这样做的好处在于更容易管理大型项目的多语言。如果不需要分模块划分,可以直接自己手动导入即可。

使用

引入项目自带的 useI18n 注意不要引入 vue-i18n 的 useI18n

import { useI18n } from '/@/hooks/web/useI18n';
+
+const { t } = useI18n();
+
+const title = t('components.modal.title');
+

切换语言

切换语言需要使用 src/locales/useLocale.ts

import { useLocale } from '/@/locales/useLocale';
+
+const { changeLocale } = useLocale();
+
+changeLocale('en');
+

新增

语言文件

src/locales/lang/ 增加对应语言的文件即可

新增语言

目前项目自带的语言只有 zh_CNen 两种

如果需要新增,按以下操作即可

  1. src/locales/lang/ 下新增相应的语言目录及语言文件并引入 引入 ant-design-vue 和 moment 对应的语言包
  2. types/config.d.ts 内加上预览类型定义
  3. src/settings/localeSetting.ts 修改语言配置

远程读取语言数据

目前项目会在 src/main.ts 内等待 setupI18n 这个函数执行完之后才会渲染界面,所以只需在 setupI18n 内发送 ajax 请求,将对应的数据设置到 i18n 实例上即可

// src/main.ts
+await setupI18n(app);
+
+app.mount('#app', true);
+

setupI18n 函数

代码: src/locales/setupI18n/

如下所示,这里会先设置一个默认语言,默认语言可以设置在本地,也可以在这里等待接口返回默认语言

// setup i18n instance with glob
+export async function setupI18n(app: App) {
+  const options = await createI18nOptions();
+  i18n = createI18n(options) as I18n;
+  app.use(i18n);
+}
+
+async function createI18nOptions(): Promise<I18nOptions> {
+  const locale = localeStore.getLocale;
+
+  // 这里改成接口获取
+  const defaultLocal = await import(`./lang/${locale}.ts`);
+  const message = defaultLocal.default?.message ?? {};
+
+  return {
+    legacy: false,
+    locale,
+    fallbackLocale: fallback,
+    messages: {
+      [locale]: message,
+    },
+    availableLocales: availableLocales,
+    sync: true,
+    silentTranslationWarn: true,
+    missingWarn: false,
+    silentFallbackWarn: true,
+  };
+}
+

changeLocale 函数

代码: src/locales/useLocale/

当手动切换语言的时候会触发 useLocale 函数,useLocale 也是异步函数,只需等待接口返回响应的数据后,再进行设置即可

async function changeLocale(locale: LocaleType) {
+  const globalI18n = i18n.global;
+  const currentLocale = unref(globalI18n.locale);
+  if (currentLocale === locale) return locale;
+
+  if (loadLocalePool.includes(locale)) {
+    setI18nLanguage(locale);
+    return locale;
+  }
+  // 这里改成接口获取
+  const langModule = ((await import(`./lang/${locale}.ts`)) as any).default as LangModule;
+  if (!langModule) return;
+
+  const { message, momentLocale, momentLocaleName } = langModule;
+
+  globalI18n.setLocaleMessage(locale, message);
+  moment.updateLocale(momentLocaleName, momentLocale);
+  loadLocalePool.push(locale);
+
+  setI18nLanguage(locale);
+  return locale;
+}
+
+ + + + \ No newline at end of file diff --git a/dep/icon.html b/dep/icon.html new file mode 100644 index 00000000..502ab00d --- /dev/null +++ b/dep/icon.html @@ -0,0 +1,193 @@ + + + + + + 图标 | Vben Admin + + + + + + + + + + + + + + + + +

图标

项目中有以下多种图标使用方式。

组件库图标

使用 ant-design-vue 提供的图标

<template>
+  <StarOutlined />
+  <StarFilled />
+  <StarTwoTone twoToneColor="#eb2f96" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { StarOutlined, StarFilled, StarTwoTone } from '@ant-design/icons-vue';
+  export default defineComponent({
+    components: { StarOutlined, StarFilled, StarTwoTone },
+  });
+</script>
+

Svg Sprite 图标

使用

将需要的 svg 图标放到src/assets/icons

例: test.svg

  1. 使用SvgIcon组件进行展示
<template>
+  <SvgIcon name="test" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { SvgIcon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { SvgIcon },
+  });
+</script>
+
  1. 使用Icon组件进行展示

|svg 结尾会自动使用SvgIcon组件

<template>
+  <Icon name="test|svg" />
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Icon } from '/@/components/Icon';
+  export default defineComponent({
+    components: { Icon },
+  });
+</script>
+

Iconify 图标

使用方式请参考 Icon 组件

项目中使用到的是 vite-plugin-purge-icons 这个插件来进行图标实现。

  1. 安装依赖

+yarn add @iconify/iconify
+
+yarn add @iconify/json @purge-icons/generated -D
+
+
  1. vite.config.ts内引入插件
import PurgeIcons from 'vite-plugin-purge-icons';
+
+export default {
+  plugins: [PurgeIcons()],
+};
+
  1. 编写 Icon 组件

完整代码 src/components/Icon/src/Icon.vue

<template>
+  <SvgIcon :size="size" :name="getSvgIcon" v-if="isSvgIcon" :class="[$attrs.class]" :spin="spin" />
+  <span
+    v-else
+    ref="elRef"
+    :class="[$attrs.class, 'app-iconify anticon', spin && 'app-iconify-spin']"
+    :style="getWrapStyle"
+  ></span>
+</template>
+<script lang="ts">
+  import type { PropType } from 'vue';
+  import {
+    defineComponent,
+    ref,
+    watch,
+    onMounted,
+    nextTick,
+    unref,
+    computed,
+    CSSProperties,
+  } from 'vue';
+
+  import SvgIcon from './SvgIcon.vue';
+  import Iconify from '@purge-icons/generated';
+  import { isString } from '/@/utils/is';
+  import { propTypes } from '/@/utils/propTypes';
+
+  const SVG_END_WITH_FLAG = '|svg';
+  export default defineComponent({
+    name: 'GIcon',
+    components: { SvgIcon },
+    props: {
+      // icon name
+      icon: propTypes.string,
+      // icon color
+      color: propTypes.string,
+      // icon size
+      size: {
+        type: [String, Number] as PropType<string | number>,
+        default: 16,
+      },
+      spin: propTypes.bool.def(false),
+      prefix: propTypes.string.def(''),
+    },
+    setup(props) {
+      const elRef = ref<ElRef>(null);
+
+      const isSvgIcon = computed(() => props.icon?.endsWith(SVG_END_WITH_FLAG));
+      const getSvgIcon = computed(() => props.icon.replace(SVG_END_WITH_FLAG, ''));
+      const getIconRef = computed(() => `${props.prefix ? props.prefix + ':' : ''}${props.icon}`);
+
+      const update = async () => {
+        if (unref(isSvgIcon)) return;
+
+        const el = unref(elRef);
+        if (!el) return;
+
+        await nextTick();
+        const icon = unref(getIconRef);
+        if (!icon) return;
+
+        const svg = Iconify.renderSVG(icon, {});
+        if (svg) {
+          el.textContent = '';
+          el.appendChild(svg);
+        } else {
+          const span = document.createElement('span');
+          span.className = 'iconify';
+          span.dataset.icon = icon;
+          el.textContent = '';
+          el.appendChild(span);
+        }
+      };
+
+      const getWrapStyle = computed((): CSSProperties => {
+        const { size, color } = props;
+        let fs = size;
+        if (isString(size)) {
+          fs = parseInt(size, 10);
+        }
+
+        return {
+          fontSize: `${fs}px`,
+          color: color,
+          display: 'inline-flex',
+        };
+      });
+
+      watch(() => props.icon, update, { flush: 'post' });
+
+      onMounted(update);
+
+      return { elRef, getWrapStyle, isSvgIcon, getSvgIcon };
+    },
+  });
+</script>
+<style lang="less">
+  .app-iconify {
+    display: inline-block;
+    // vertical-align: middle;
+
+    &-spin {
+      svg {
+        animation: loadingCircle 1s infinite linear;
+      }
+    }
+  }
+
+  span.iconify {
+    display: block;
+    min-width: 1em;
+    min-height: 1em;
+    background-color: @iconify-bg-color;
+    border-radius: 100%;
+  }
+</style>
+

图标选择器

图标集预生成

由于图标选择器这个比较特殊的存在,项目会打包一些比较多的图标,图标选择器的图标需要事先指定并生成相应的文件。

生成

  • 执行图标生成命令
yarn gen:icon
+
  • 这里会让你选择本地还是在线生成,两种方式各有利弊。如下图所示

local 表示本地,online 表示在线,回车确认

  • 选择你要生成的图标集,回车确认

  • 选择图标输出的目录(项目默认 src/components/Icon/data),可以直接回车选择默认

到这里图标集已经生成完成了,此时你的图标选择器已经是你所选的的图标集的图标了。

注意不要频繁更新

如果前面选择的是本地生成的话,频繁更换图标集,可能会导致图标丢失或者显示不出来

优缺点

  • 在线图标(项目默认,推荐)

该方式会在图标选择器使用到图标的时候进行在线请求,然后缓存对应的图标到浏览器。可以有效减少代码打包体积。

如果你的项目可以访问外网,建议可以使用这种方式

缺点: 在局域网或者无法访问到外网的环境中图标显示不出来

  • 本地图标

该方式会在打包的时候将图标选择器的图标全部打包到 js 内。在使用的时候不会额外的请求在线图标

缺点: 打包体积会偏大,具体的体积增加得看前面选择图标集的时候选择的图标数量的多少决定

+ + + + \ No newline at end of file diff --git a/dep/lint.html b/dep/lint.html new file mode 100644 index 00000000..df1f0c94 --- /dev/null +++ b/dep/lint.html @@ -0,0 +1,51 @@ + + + + + + Lint | Vben Admin + + + + + + + + + + + + + + + + +

Lint

介绍

使用 lint 的好处

具备基本工程素养的同学都会注重编码规范,而代码风格检查(Code Linting,简称 Lint)是保障代码规范一致性的重要手段。

遵循相应的代码规范有以下好处

  • 较少 bug 错误率
  • 高效的开发效率
  • 更高的可读性

项目内集成了以下几种代码校验方式

  1. eslint 用于校验代码格式规范
  2. commitlint 用于校验 git 提交信息规范
  3. stylelint 用于校验 css/less 规范
  4. prettier 代码格式化

WARNING

lint 不是必须的,但是很有必要,一个项目做大了以后或者参与人员过多后,就会出现各种风格迥异的代码,对后续的维护造成了一定的麻烦

ESLint

ESLint 是一个代码规范和错误检查工具,有以下几个特性

  • 所有东西都是可以插拔的。你可以调用任意的 rule api 或者 formatter api 去打包或者定义 rule or formatter。
  • 任意的 rule 都是独立的
  • 没有特定的 coding style,你可以自己配置

手动校验代码

# 执行下面代码.能修复的会自动修复,不能修复的需要手动修改
+yarn run lint:eslint
+

配置项

项目的 eslint 配置位于根目录下 .eslintrc.js 内,可以根据团队自行修改代码规范

编辑器配合

推荐使用 vscode 进行开发,vscode 自带 eslint 插件,可以自动修改一些错误。

同时项目内也自带了 vscode eslint 配置,具体在 .vscode/setting.json 文件夹内部。只要使用 vscode 开发不用任何设置即可使用

CommitLint

在一个团队中,每个人的 git 的 commit 信息都不一样,五花八门,没有一个机制很难保证规范化,如何才能规范化呢?可能你想到的是 git 的 hook 机制,去写 shell 脚本去实现。这当然可以,其实 JavaScript 有一个很好的工具可以实现这个模板,它就是 commitlint(用于校验 git 提交信息规范)。

配置

commit-lint 的配置位于项目根目录下 commitlint.config.js

Git 提交规范

  • 参考 vue 规范 (Angular)

    • feat 增加新功能
    • fix 修复问题/BUG
    • style 代码风格相关无影响运行结果的
    • perf 优化/性能提升
    • refactor 重构
    • revert 撤销修改
    • test 测试相关
    • docs 文档/注释
    • chore 依赖更新/脚手架配置修改等
    • workflow 工作流改进
    • ci 持续集成
    • mod 不确定分类的修改
    • wip 开发中
    • types 类型修改

如何关闭

.husky/commit-msg 内注释以下代码即可

# npx --no-install commitlint --edit "$1"
+

示例


+git commit -m 'feat(home): add home page'
+
+

Stylelint

stylelint 用于校验项目内部 css 的风格,加上编辑器的自动修复,可以很好的统一项目内部 css 风格

配置

stylelint 配置位于根目录下 stylelint.config.js

编辑器配合

如果您使用的是 vscode 编辑器的话,只需要安装下面插件,即可在保存的时候自动格式化文件内部 css 样式

插件

StyleLint

Prettier

prettier 可以用于统一项目代码风格,统一的缩进,单双引号,尾逗号等等风格

配置

prettier 配置文件位于项目根目录下 prettier.config.js

编辑器配合

如果您使用的是 vscode 编辑器的话,只需要安装下面插件,即可在保存的时候自动格式化文件内部 js 格式

插件

Prettier

Git Hook

git hook 一般结合各种 lint,在 git 提交代码的时候进行代码风格校验,如果校验没通过,则不会进行提交。需要开发者自行修改后再次进行提交

husky

有一个问题就是校验会校验全部代码,但是我们只想校验我们自己提交的代码,这个时候就可以使用 husky。

最有效的解决方案就是将 Lint 校验放到本地,常见做法是使用 husky 或者 pre-commit 在本地提交之前先做一次 Lint 校验。

项目在 .husky 内部定义了相应的 hooks

如何关闭

# 删除husky依赖即可
+yarn remove huksy
+
+

如何跳过某一个检查

# 加上 --no-verify即可跳过git hook校验(--no-verify 简写为 -n)
+git commit -m "xxx" --no-verify
+

lint-staged

用于自动修复提交文件风格问题

lint-staged 配置位于项目 .husky 目录下 lintstagedrc.js

module.exports = {
+  // 对指定格式文件 在提交的时候执行相应的修复命令
+  '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
+  '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --write--parser json'],
+  'package.json': ['prettier --write'],
+  '*.vue': ['eslint --fix', 'stylelint --fix', 'prettier --write', 'git add .'],
+  '*.{scss,less,styl,css,html}': ['stylelint --fix', 'prettier --write', 'git add .'],
+  '*.md': ['prettier --write'],
+};
+
+ + + + \ No newline at end of file diff --git a/guide/auth.html b/guide/auth.html new file mode 100644 index 00000000..922dddf1 --- /dev/null +++ b/guide/auth.html @@ -0,0 +1,260 @@ + + + + + + 权限 | Vben Admin + + + + + + + + + + + + + + + + +

权限

项目中集成了三种权限处理方式:

  1. 通过用户角色来过滤菜单(前端方式控制),菜单和路由分开配置
  2. 通过用户角色来过滤菜单(前端方式控制),菜单由路由配置自动生成
  3. 通过后台来动态生成路由表(后台方式控制)

前端角色权限

实现原理: 在前端固定写死路由的权限,指定路由有哪些权限可以查看。只初始化通用的路由,需要权限才能访问的路由没有被加入路由表内。在登陆后或者其他方式获取用户角色后,通过角色去遍历路由表,获取该角色可以访问的路由表,生成路由表,再通过 router.addRoutes 添加到路由实例,实现权限的过滤。

缺点: 权限相对不自由,如果后台改动角色,前台也需要跟着改动。适合角色较固定的系统

实现

  1. 项目配置将系统内权限模式改为 ROLE 模式
// ! 改动后需要清空浏览器缓存
+const setting: ProjectConfig = {
+  // 权限模式
+  permissionMode: PermissionModeEnum.ROLE,
+};
+
  1. 在路由表配置路由所需的权限,如果不配置,默认可见(见注释)
import type { AppRouteModule } from '/@/router/types';
+
+import { getParentLayout, LAYOUT } from '/@/router/constant';
+import { RoleEnum } from '/@/enums/roleEnum';
+import { t } from '/@/hooks/web/useI18n';
+
+const permission: AppRouteModule = {
+  path: '/permission',
+  name: 'Permission',
+  component: LAYOUT,
+  redirect: '/permission/front/page',
+  meta: {
+    icon: 'ion:key-outline',
+    title: t('routes.demo.permission.permission'),
+  },
+
+  children: [
+    {
+      path: 'front',
+      name: 'PermissionFrontDemo',
+      component: getParentLayout('PermissionFrontDemo'),
+      meta: {
+        title: t('routes.demo.permission.front'),
+      },
+      children: [
+        {
+          path: 'auth-pageA',
+          name: 'FrontAuthPageA',
+          component: () => import('/@/views/demo/permission/front/AuthPageA.vue'),
+          meta: {
+            title: t('routes.demo.permission.frontTestA'),
+            roles: [RoleEnum.SUPER],
+          },
+        },
+        {
+          path: 'auth-pageB',
+          name: 'FrontAuthPageB',
+          component: () => import('/@/views/demo/permission/front/AuthPageB.vue'),
+          meta: {
+            title: t('routes.demo.permission.frontTestB'),
+            roles: [RoleEnum.TEST],
+          },
+        },
+      ],
+    },
+  ],
+};
+
+export default permission;
+
  1. 在路由钩子内动态判断

详细代码见 src/router/guard/permissionGuard.ts

// 这里只列举了主要代码
+const routes = await permissionStore.buildRoutesAction();
+
+routes.forEach((route) => {
+  router.addRoute(route as unknown as RouteRecordRaw);
+});
+
+const redirectPath = (from.query.redirect || to.path) as string;
+const redirect = decodeURIComponent(redirectPath);
+const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect };
+permissionStore.setDynamicAddedRoute(true);
+next(nextData);
+

permissionStore.buildRoutesAction 用于过滤动态路由,详细代码见 src/store/modules/permission.ts

// 主要代码
+if (permissionMode === PermissionModeEnum.ROLE) {
+  const routeFilter = (route: AppRouteRecordRaw) => {
+    const { meta } = route;
+    const { roles } = meta || {};
+    if (!roles) return true;
+    return roleList.some((role) => roles.includes(role));
+  };
+  routes = filter(asyncRoutes, routeFilter);
+  routes = routes.filter(routeFilter);
+  // Convert multi-level routing to level 2 routing
+  routes = flatMultiLevelRoutes(routes);
+}
+

动态更换角色

系统提供 usePermission 方便角色相关操作

import { usePermission } from '/@/hooks/web/usePermission';
+import { RoleEnum } from '/@/enums/roleEnum';
+
+export default defineComponent({
+  setup() {
+    const { changeRole } = usePermission();
+    // 更换为test角色
+    // 动态更改角色,传入角色名称,可以是数组
+    changeRole(RoleEnum.TEST);
+    return {};
+  },
+});
+

细粒度权限

函数方式

usePermission 还提供了按钮级别的权限控制。

<template>
+  <a-button v-if="hasPermission([RoleEnum.TEST, RoleEnum.SUPER])" color="error" class="mx-4">
+    拥有[test,super]角色权限可见
+  </a-button>
+</template>
+<script lang="ts">
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { RoleEnum } from '/@/enums/roleEnum';
+
+  export default defineComponent({
+    setup() {
+      const { hasPermission } = usePermission();
+
+      return { hasPermission };
+    },
+  });
+</script>
+

组件方式

具体查看权限组件使用

指令方式

TIP

指令方式不能动态更改权限

<a-button v-auth="RoleEnum.SUPER" type="primary" class="mx-4"> 拥有super角色权限可见</a-button>
+

后台动态获取

实现原理: 是通过接口动态生成路由表,且遵循一定的数据结构返回。前端根据需要处理该数据为可识别的结构,再通过 router.addRoutes 添加到路由实例,实现权限的动态生成。

实现

  1. 项目配置将系统内权限模式改为 BACK 模式
// ! 改动后需要清空浏览器缓存
+const setting: ProjectConfig = {
+  // 权限模式
+  permissionMode: PermissionModeEnum.BACK,
+};
+
  1. 路由拦截,与角色权限模式一致

permissionStore.buildRoutesAction 用于过滤动态路由,详细代码见 /@/store/modules/permission.ts

// 主要代码
+if (permissionMode === PermissionModeEnum.BACK) {
+  const { createMessage } = useMessage();
+
+  createMessage.loading({
+    content: t('sys.app.menuLoading'),
+    duration: 1,
+  });
+
+  // !Simulate to obtain permission codes from the background,
+  // this function may only need to be executed once, and the actual project can be put at the right time by itself
+  let routeList: AppRouteRecordRaw[] = [];
+  try {
+    this.changePermissionCode();
+    routeList = (await getMenuList()) as AppRouteRecordRaw[];
+  } catch (error) {
+    console.error(error);
+  }
+
+  // Dynamically introduce components
+  routeList = transformObjToRoute(routeList);
+
+  //  Background routing to menu structure
+  const backMenuList = transformRouteToMenu(routeList);
+  this.setBackMenuList(backMenuList);
+
+  routeList = flatMultiLevelRoutes(routeList);
+  routes = [PAGE_NOT_FOUND_ROUTE, ...routeList];
+}
+

getMenuList 返回值格式

返回值由多个路由模块组成

注意

后端接口返回的数据中必须包含PageEnum.BASE_HOME指定的路由(path定义于src/enums/pageEnum.ts

[
+  {
+    path: '/dashboard',
+    name: 'Dashboard',
+    component: '/dashboard/welcome/index',
+    meta: {
+      title: 'routes.dashboard.welcome',
+      affix: true,
+      icon: 'ant-design:home-outlined',
+    },
+  },
+  {
+    path: '/permission',
+    name: 'Permission',
+    component: 'LAYOUT',
+    redirect: '/permission/front/page',
+    meta: {
+      icon: 'carbon:user-role',
+      title: 'routes.demo.permission.permission',
+    },
+    children: [
+      {
+        path: 'back',
+        name: 'PermissionBackDemo',
+        meta: {
+          title: 'routes.demo.permission.back',
+        },
+
+        children: [
+          {
+            path: 'page',
+            name: 'BackAuthPage',
+            component: '/demo/permission/back/index',
+            meta: {
+              title: 'routes.demo.permission.backPage',
+            },
+          },
+          {
+            path: 'btn',
+            name: 'BackAuthBtn',
+            component: '/demo/permission/back/Btn',
+            meta: {
+              title: 'routes.demo.permission.backBtn',
+            },
+          },
+        ],
+      },
+    ],
+  },
+];
+

动态更换菜单

系统提供 usePermission 方便角色相关操作

import { usePermission } from '/@/hooks/web/usePermission';
+import { RoleEnum } from '/@/enums/roleEnum';
+
+export default defineComponent({
+  setup() {
+    const { changeMenu } = usePermission();
+
+    // 更改菜单的实现需要自行去修改
+    changeMenu();
+    return {};
+  },
+});
+

细粒度权限

函数方式

usePermission 还提供了按钮级别的权限控制。

<template>
+  <a-button v-if="hasPermission(['20000', '2000010'])" color="error" class="mx-4">
+    拥有[20000,2000010]code可见
+  </a-button>
+</template>
+<script lang="ts">
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { RoleEnum } from '/@/enums/roleEnum';
+
+  export default defineComponent({
+    setup() {
+      const { hasPermission } = usePermission();
+      return { hasPermission };
+    },
+  });
+</script>
+

组件方式

具体查看权限组件使用

指令方式

TIP

指令方式不能动态更改权限

<a-button v-auth="'1000'" type="primary" class="mx-4"> 拥有code ['1000']权限可见 </a-button>
+

如何初始化 code

通常,如需做按钮级别权限,后台会提供相应的 code,或者类型的判断标识。这些编码只需要在登录后获取一次即可。

import { getPermCodeByUserId } from '/@/api/sys/user';
+import { permissionStore } from '/@/store/modules/permission';
+async function changePermissionCode(userId: string) {
+  // 从后台获取当前用户拥有的编码
+  const codeList = await getPermCodeByUserId({ userId });
+  permissionStore.commitPermCodeListState(codeList);
+}
+
+ + + + \ No newline at end of file diff --git a/guide/component.html b/guide/component.html new file mode 100644 index 00000000..e87cdb77 --- /dev/null +++ b/guide/component.html @@ -0,0 +1,145 @@ + + + + + + 组件注册 | Vben Admin + + + + + + + + + + + + + + + + +

组件注册

按需引入

项目目前的组件注册机制是按需注册,是在需要用到的页面才引入。

<template>
+  <Menu>
+    <SubMenu></SubMenu>
+  <Menu>
+
+  <menu>
+    <sub-menu></sub-menu>
+  <menu>
+</template>
+<script>
+import { Menu } from 'ant-design-vue';
+export default defineComponent({
+  components: {
+    Menu: Menu,
+    SubMenu: Menu.SubMenu
+  },
+})
+</script>
+

tsx 文件注册

tsx 文件内不能使用全局注册组件

import { Menu } from 'ant-design-vue';
+
+export default defineComponent({
+  setup() {
+    return () => (
+      <Menu>
+        <Menu.SubMenu></Menu.SubMenu>
+      </Menu>
+    );
+  },
+});
+

全局注册

如果不习惯按需引入方式,可以进行全局注册。全局注册也分两种方式

全局按需注册

只注册需要的组件

代码地址:src/components/registerGlobComp.ts

import {
+  // Need
+  Button as AntButton,
+  Optional
+  Select,
+  Alert,
+  Checkbox,
+  DatePicker,
+  Radio,
+  Switch,
+  Card,
+  List,
+  Tabs,
+  Descriptions,
+  Tree,
+  Table,
+  Divider,
+  Modal,
+  Drawer,
+  Dropdown,
+  Tag,
+  Tooltip,
+  Badge,
+  Popover,
+  Upload,
+  Transfer,
+  Steps,
+  PageHeader,
+  Result,
+  Empty,
+  Avatar,
+  Menu,
+  Breadcrumb,
+  Form,
+  Input,
+  Row,
+  Col,
+  Spin,
+} from 'ant-design-vue';
+
+export function registerGlobComp(app: App) {
+  app
+    .use(Select)
+    .use(Alert)
+    .use(Breadcrumb)
+    .use(Checkbox)
+    .use(DatePicker)
+    .use(Radio)
+    .use(Switch)
+    .use(Card)
+    .use(List)
+    .use(Descriptions)
+    .use(Tree)
+    .use(Table)
+    .use(Divider)
+    .use(Modal)
+    .use(Drawer)
+    .use(Dropdown)
+    .use(Tag)
+    .use(Tooltip)
+    .use(Badge)
+    .use(Popover)
+    .use(Upload)
+    .use(Transfer)
+    .use(Steps)
+    .use(PageHeader)
+    .use(Result)
+    .use(Empty)
+    .use(Avatar)
+    .use(Menu)
+    .use(Tabs)
+    .use(Form)
+    .use(Input)
+    .use(Row)
+    .use(Col)
+    .use(Spin);
+}
+

全量注册

  • main.ts
import { createApp } from 'vue';
+import Antd from 'ant-design-vue';
+import 'ant-design-vue/dist/antd.less';
+const app = createApp(App);
+app.use(Antd);
+
  • 删除以下代码
if (import.meta.env.DEV) {
+  import('ant-design-vue/dist/antd.less');
+}
+
+ + + + \ No newline at end of file diff --git a/guide/deploy.html b/guide/deploy.html new file mode 100644 index 00000000..56261acf --- /dev/null +++ b/guide/deploy.html @@ -0,0 +1,139 @@ + + + + + + 构建&部署 | Vben Admin + + + + + + + + + + + + + + + + +

构建&部署

前言

由于是展示项目,所以打包后相对较大,如果项目中没有用到的插件,可以删除对应的文件或者路由,不引用即可,没有引用就不会打包。

当然,你也可以使用精简版 vue-vben-admin-thin 进行开发。

构建

项目开发完成之后,执行以下命令进行构建

yarn build
+

构建打包成功之后,会在根目录生成 dist 文件夹,里面就是构建打包好的文件

旧版浏览器兼容

.env.production

设置 VITE_LEGACY=true 即可打包出兼容旧版浏览器的代码

VITE_LEGACY = true
+

预览

发布之前可以在本地进行预览,有多种方式,这里介绍两种

不能直接打开构建后的 html 文件

  • 使用项目自定的命令进行预览(推荐)
# 先打包再进行预览
+yarn preview
+# 直接预览本地 dist 文件目录
+yarn preview:dist
+
  • 本地服务器预览(通过 live-server)
# 1.全局安装live-server
+yarn global add live-server
+# 2. 进入打包的后目录
+cd ./dist
+# 本地预览,默认端口8080
+live-server
+# 指定端口
+live-server --port 9000
+

分析构建文件体积

如果你的构建文件很大,可以通过项目内置 rollup-plugin-analyzer 插件进行代码体积分析,从而优化你的代码。

yarn report
+
+

运行之后,在自动打开的页面可以看到具体的体积分布,以分析哪些依赖有问题。

TIP

左上角可以切换 显示 gzip 或者 brotli

压缩

开启 gzip 压缩

开启 gzip,并配合 nginx 的 gzip_static 功能可以大大加快页面访问速度

TIP

只需开启 VITE_BUILD_COMPRESS='gzip' 即可在打包的同时生成 .gz 文件

# 根据自己路径来配置更改
+# 例如部署在nginx /next/路径下  则VITE_PUBLIC_PATH=/next/
+VITE_PUBLIC_PATH=/
+

开启 brotli 压缩

brotli 是比 gzip 压缩率更高的算法,可以与 gzip 共存不会冲突,需要 nginx 安装指定模块并开启即可。

TIP

只需开启 VITE_BUILD_COMPRESS='brotli' 即可在打包的同时生成 .br 文件

# 根据自己路径来配置更改
+# 例如部署在nginx /next/路径下  则VITE_PUBLIC_PATH=/next/
+VITE_PUBLIC_PATH=/
+

同时开启 gzip 与 brotli

只需开启 VITE_BUILD_COMPRESS='brotli,gzip' 即可在打包的同时生成 .gz.br 文件。

gzip 与 brotli 在 nginx 内的配置

http {
+  # 开启gzip
+  gzip on;
+  # 开启gzip_static
+  # gzip_static 开启后可能会报错,需要安装相应的模块, 具体安装方式可以自行查询
+  # 只有这个开启,vue文件打包的.gz文件才会有效果,否则不需要开启gzip进行打包
+  gzip_static on;
+  gzip_proxied any;
+  gzip_min_length 1k;
+  gzip_buffers 4 16k;
+  #如果nginx中使用了多层代理 必须设置这个才可以开启gzip。
+  gzip_http_version 1.0;
+  gzip_comp_level 2;
+  gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
+  gzip_vary off;
+  gzip_disable "MSIE [1-6]\.";
+
+  # 开启 brotli压缩
+  # 需要安装对应的nginx模块,具体安装方式可以自行查询
+  # 可以与gzip共存不会冲突
+  brotli on;
+  brotli_comp_level 6;
+  brotli_buffers 16 8k;
+  brotli_min_length 20;
+  brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
+}
+

部署

注意

项目默认是在生产环境开启 Mock,这样做非常不好,只是为了演示环境有数据,不建议在生产环境使用 Mock,而应该使用真实的后台接口,并将 Mock 关闭。

发布

简单的部署只需要将最终生成的静态文件,dist 文件夹的静态文件发布到你的 cdn 或者静态服务器即可,需要注意的是其中的 index.html 通常会是你后台服务的入口页面,在确定了 js 和 css 的静态之后可能需要改变页面的引入路径。

例如上传到 nginx

/srv/www/project/index.html

# nginx配置
+location / {
+  # 不缓存html,防止程序更新后缓存继续生效
+  if ($request_filename ~* .*\.(?:htm|html)$) {
+    add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
+    access_log on;
+  }
+  # 这里是vue打包文件dist内的文件的存放路径
+  root   /srv/www/project/;
+  index  index.html index.htm;
+}
+
+

部署时可能会发现资源路径不对,只需要修改.env.production文件即可。

# 根据自己路径来配置更改
+# 注意需要以 / 开头和结尾
+VITE_PUBLIC_PATH=/
+VITE_PUBLIC_PATH=/xxx/
+

前端路由与服务端的结合

项目前端路由使用的是 vue-router,所以你可以选择两种方式:history 和 hash。

  • hash 默认会在 url 后面拼接#
  • history 则不会,不过 history 需要服务器配合

可在 src/router/index.ts 内进行 mode 修改

import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
+
+createRouter({
+  history: createWebHashHistory(),
+  // or
+  history: createWebHistory(),
+});
+

history 路由模式下服务端配置

开启 history 模式需要服务器配置,更多的服务器配置详情可以看 history-mode

这里以 nginx 配置为例

部署到根目录

server {
+  listen 80;
+  location / {
+    # 用于配合 History 使用
+    try_files $uri $uri/ /index.html;
+  }
+}
+

部署到非根目录

  1. 首先需要在打包的时候更改配置
# 在.env.production内,配置子目录路径
+VITE_PUBLIC_PATH = /sub/
+
server {
+    listen       80;
+    server_name  localhost;
+    location /sub/ {
+      # 这里是vue打包文件dist内的文件的存放路径
+      alias   /srv/www/project/;
+      index index.html index.htm;
+      try_files $uri $uri/ /sub/index.html;
+    }
+}
+

使用 nginx 处理跨域

使用 nginx 处理项目部署后的跨域问题

  1. 配置前端项目接口地址
# 在.env.production内,配置接口地址
+VITE_GLOB_API_URL=/api
+
  1. 在 nginx 配置请求转发到后台
server {
+  listen       8080;
+  server_name  localhost;
+  # 接口代理,用于解决跨域问题
+  location /api {
+    proxy_set_header Host $host;
+    proxy_set_header X-Real-IP $remote_addr;
+    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+    # 后台接口地址
+    proxy_pass http://110.110.1.1:8080/api;
+    proxy_redirect default;
+    add_header Access-Control-Allow-Origin *;
+    add_header Access-Control-Allow-Headers X-Requested-With;
+    add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
+  }
+}
+
+ + + + \ No newline at end of file diff --git a/guide/design.html b/guide/design.html new file mode 100644 index 00000000..dea4e5a8 --- /dev/null +++ b/guide/design.html @@ -0,0 +1,107 @@ + + + + + + 样式 | Vben Admin + + + + + + + + + + + + + + + + +

样式

介绍

主要介绍如何在项目中使用和规划样式文件。

默认使用 less 作为预处理语言,建议在使用前或者遇到疑问时学习一下 Less 的相关特性(如果想获取基础的 CSS 知识或查阅属性,请参考 MDN 文档)。

项目中使用的通用样式,都存放于 src/design/ 下面。

.
+├── ant # ant design 一些样式覆盖
+├── color.less # 颜色
+├── index.less # 入口
+├── public.less # 公共类
+├── theme.less # 主题相关
+├── config.less  # 每个组件都会自动引入样式
+├── transition # 动画相关
+└── var # 变量
+
+

全局注入

config.less 这个文件会被全局注入到所有文件,所以在页面内可以直接使用变量而不需要手动引入

<style lang="less" scoped>
+  // 这里已经隐式注入了 config.less
+</style>
+

tailwindcss(2.5.0+)

项目中引用到了 tailwindcss,具体可以见文件使用说明。

语法如下:

<div class="relative w-full h-full px-4"></div>
+

windicss(2.5.0 已弃用)

项目中使用了 windicss,具体参见文件使用说明。

语法如下:

<div class="relative w-full h-full px-4"></div>
+

注意事项

windcss 目前会造成本地开发内存溢出,所以后续可能会考虑切换到 TailwindCss,两者基本相同。

所以尽量少用 Windicss 新增的特性,防止后续切换成本高。

为什么使用 Less

主要是因为 Ant Design 默认使用 less 作为样式语言,使用 Less 可以跟其保持一致。

开启 scoped

没有加 scoped 属性,默认会编译成全局样式,可能会造成全局污染

<style></style>
+
+<style scoped></style>
+

温馨提醒

使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。

深度选择器

有时我们可能想明确地制定一个针对子组件的规则。

如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符。有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/::v-deep 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作。

详情可以查看 RFC0023-scoped-styles-changes

使用 scoped 后,父组件的样式将不会渗透到子组件中,所以可以使用以下方式解决:

<style scoped>
+  /* deep selectors */
+  ::v-deep(.foo) {
+  }
+  /* shorthand */
+  :deep(.foo) {
+  }
+
+  /* targeting slot content */
+  ::v-slotted(.foo) {
+  }
+  /* shorthand */
+  :slotted(.foo) {
+  }
+
+  /* one-off global rule */
+  ::v-global(.foo) {
+  }
+  /* shorthand */
+  :global(.foo) {
+  }
+</style>
+

CSS Modules

针对样式覆盖问题,还有一种方案是使用 CSS Modules 模块化方案。使用方式如下。

<template>
+  <span :class="$style.span1">hello</span>
+</template>
+
+<script>
+  import { useCSSModule } from 'vue';
+
+  export default {
+    setup(props, context) {
+      const $style = useCSSModule();
+      const moduleAStyle = useCSSModule('moduleA');
+      return {
+        $style,
+        moduleAStyle,
+      };
+    },
+  };
+</script>
+
+<style lang="less" module>
+  .span1 {
+    color: green;
+    font-size: 30px;
+  }
+</style>
+
+<style lang="less" module="moduleA">
+  .span1 {
+    color: green;
+    font-size: 30px;
+  }
+</style>
+

重复引用问题

加上 reference 可以解决页面内重复引用导致实际生成的 style 样式表重复的问题。

这步已经全局引入了。所以可以不写,直接使用变量

<style lang="less" scoped>
+  /* 该行代码已全局引用。可以不用单独引入 */
+  @import (reference) '../../design/config.less';
+<style>
+
+ + + + \ No newline at end of file diff --git a/guide/electron.html b/guide/electron.html new file mode 100644 index 00000000..e2ded74a --- /dev/null +++ b/guide/electron.html @@ -0,0 +1,37 @@ + + + + + + Electron | Vben Admin + + + + + + + + + + + + + + + + +

Electron

URL 模式

这种模式会先启动 vite 服务,Electron 使用 Url 地址来进行渲染

使用

从 GitHub 获取代码

Electron 代码在 electron-main 分支

# clone electron-main分支代码
+git clone -b electron-main https://github.com/vbenjs/vue-vben-admin vben-admin-electron
+

安装依赖

yarn
+

提示

首次下载 Electron 依赖会比较慢,可以在项目根目录下新建.npmrc文件,填入下方内容即可

ELETRON_MIRROR=https://npm.taobao.org/mirrors/electron/
+

运行

yarn dev:app
+

打包

yarn build:app
+

标准模式

TODO: 待适配

+ + + + \ No newline at end of file diff --git a/guide/index.html b/guide/index.html new file mode 100644 index 00000000..4198f70c --- /dev/null +++ b/guide/index.html @@ -0,0 +1,146 @@ + + + + + + 开始 | Vben Admin + + + + + + + + + + + + + + + + +

开始

本文会帮助你从头启动项目

前言

关于组件

项目虽然二次封装了一些组件,但是可能不能满足大部分的要求。所以,如果组件不满足你的要求,完全可以不用甚至删除代码自己写,不必坚持使用项目自带的组件。

环境准备

本地环境需要安装 pnpmNode.jsGit

注意

  • 推荐使用pnpm,否则依赖可能安装不上。
  • Node.js 版本要求12.x以上,且不能为13.x版本,这里推荐 14.x 及以上。

工具配置

如果您使用的 IDE 是vscode(推荐)的话,可以安装以下工具来提高开发效率及代码格式化

代码获取

注意

注意存放代码的目录及所有父级目录不能存在中文、韩文、日文以及空格,否则安装依赖后启动会出错。

从 GitHub 获取代码

# clone 代码
+git clone https://github.com/vbenjs/vue-vben-admin.git
+
+

从 Gitee 获取代码

如果从 github clone 代码较慢的话,可以尝试用 Gitee 同步代码到自己的仓库,再 clone 下来即可。

也可以通过下方地址进行 clone

git clone https://gitee.com/annsion/vue-vben-admin.git
+

注意

Gitee的代码可能不是最新的

安装

安装 Node.js

如果您电脑未安装Node.js,请安装它。

验证

# 出现相应npm版本即可
+npm -v
+# 出现相应node版本即可
+node -v
+
+

如果你需要同时存在多个 node 版本,可以使用 Nvm 或者其他工具进行 Node.js 进行版本管理。

安装依赖

pnpm 安装

必须使用 pnpm进行依赖安装(若其他包管理器安装不了需要自行处理)。

如果未安装pnpm,可以用下面命令来进行全局安装

# 全局安装pnpm
+npm install -g pnpm
+# 验证
+pnpm -v # 出现对应版本号即代表安装成功
+

依赖安装命令

在项目根目录下,打开命令窗口执行,耐心等待安装完成即可

# 安装依赖
+pnpm i
+

imagemin 依赖安装失败解决方法

由于 imagemin 在国内安装困难,提供以下几个解决方案:

  1. 使用 yarn 在 package.json 内配置(推荐,项目内已集成,前提是必须使用 yarn)
"resolutions": {
+  "bin-wrapper": "npm:bin-wrapper-china"
+}
+
  1. 使用 npm,在电脑 host 文件加上如下配置即可
199.232.4.133 raw.githubusercontent.com
+

安装依赖时 husky 安装失败

请查看你的源码是否从 github 直接下载的,直接下载是没有 .git 文件夹的,而 husky 需要依赖 git 才能安装。此时需使用 git init 初始化项目,再尝试重新安装即可。

npm script

"scripts": {
+  # 安装依赖
+  "bootstrap": "yarn install",
+  # 运行项目
+  "serve": "npm run dev",
+  # 运行项目
+  "dev": "vite",
+  # 构建项目
+  "build": "vite build && esno ./build/script/postBuild.ts",
+  # 清空缓存后构建项目
+  "build:no-cache": "yarn clean:cache && npm run build",
+  # 生成打包分析,在 `Mac OS` 电脑上执行完成后会自动打开界面,在 `Window` 电脑上执行完成后需要打开 `./build/.cache/stats.html` 查看
+  "report": "cross-env REPORT=true npm run build",
+  # 类型检查
+  "type:check": "vue-tsc --noEmit --skipLibCheck",
+  # 预览打包后的内容(先打包在进行预览)
+  "preview": "npm run build && vite preview",
+  # 直接预览本地 dist 文件目录
+  "preview:dist": "vite preview",
+  # 生成 ChangeLog
+  "log": "conventional-changelog -p angular -i CHANGELOG.md -s",
+  # 删除缓存
+  "clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite",
+  # 删除 node_modules (`window` 系统手动删除该目录较慢,可以使用该命令来进行删除)
+  "clean:lib": "rimraf node_modules",
+  # 执行 eslint 校验,并修复部分问题
+  "lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
+  # 执行 prettier 格式化(该命令会对项目所有代码进行 prettier 格式化,请谨慎执行)
+  "lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
+  # 执行 stylelint 格式化
+  "lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
+  "lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
+  "lint:pretty": "pretty-quick --staged",
+  # 对打包结果进行 gzip 测试
+  "test:gzip": "http-server dist --cors --gzip -c-1",
+  # 对打包目录进行 brotli 测试
+  "test:br": "http-server dist --cors --brotli -c-1",
+  # 重新安装依赖,见下方说明
+  "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
+  "install:husky": "is-ci || husky install",
+  # 生成图标集,见下方说明
+  "gen:icon": "esno ./build/generate/icon/index.ts",
+  "postinstall": "npm run install:husky"
+},
+

生成图标集

该命令会生成所选择的图标集,提供给图标选择器使用。具体使用方式请查看 图标集生成

重新安装依赖

该命令会先删除 node_modulesyarn.lockpackage.lock.json 后再进行依赖重新安装(安装速度会明显变慢)。

接下来你可以修改代码进行业务开发了。我们内建了模拟数据、HMR 实时预览、状态管理、国际化、全局路由等各种实用的功能辅助开发,请阅读其他章节了解更多。

目录说明


+.
+├── build # 打包脚本相关
+│   ├── config # 配置文件
+│   ├── generate # 生成器
+│   ├── script # 脚本
+│   └── vite # vite配置
+├── mock # mock文件夹
+├── public # 公共静态资源目录
+├── src # 主目录
+│   ├── api # 接口文件
+│   ├── assets # 资源文件
+│   │   ├── icons # icon sprite 图标文件夹
+│   │   ├── images # 项目存放图片的文件夹
+│   │   └── svg # 项目存放svg图片的文件夹
+│   ├── components # 公共组件
+│   ├── design # 样式文件
+│   ├── directives # 指令
+│   ├── enums # 枚举/常量
+│   ├── hooks # hook
+│   │   ├── component # 组件相关hook
+│   │   ├── core # 基础hook
+│   │   ├── event # 事件相关hook
+│   │   ├── setting # 配置相关hook
+│   │   └── web # web相关hook
+│   ├── layouts # 布局文件
+│   │   ├── default # 默认布局
+│   │   ├── iframe # iframe布局
+│   │   └── page # 页面布局
+│   ├── locales # 多语言
+│   ├── logics # 逻辑
+│   ├── main.ts # 主入口
+│   ├── router # 路由配置
+│   ├── settings # 项目配置
+│   │   ├── componentSetting.ts # 组件配置
+│   │   ├── designSetting.ts # 样式配置
+│   │   ├── encryptionSetting.ts # 加密配置
+│   │   ├── localeSetting.ts # 多语言配置
+│   │   ├── projectSetting.ts # 项目配置
+│   │   └── siteSetting.ts # 站点配置
+│   ├── store # 数据仓库
+│   ├── utils # 工具类
+│   └── views # 页面
+├── test # 测试
+│   └── server # 测试用到的服务
+│       ├── api # 测试服务器
+│       ├── upload # 测试上传服务器
+│       └── websocket # 测试ws服务器
+├── types # 类型文件
+├── vite.config.ts # vite配置文件
+└── windi.config.ts # windcss配置文件
+
+
+ + + + \ No newline at end of file diff --git a/guide/introduction.html b/guide/introduction.html new file mode 100644 index 00000000..fd78415b --- /dev/null +++ b/guide/introduction.html @@ -0,0 +1,39 @@ + + + + + + 介绍 | Vben Admin + + + + + + + + + + + + + + + + +

介绍

简介

Vue-Vben-Admin 是一个基于 Vue3.0ViteAnt-Design-VueTypeScript 的后台解决方案,目标是为开发中大型项目提供开箱即用的解决方案。包括二次封装组件、utils、hooks、动态菜单、权限校验、按钮级别权限控制等功能。项目会使用前端较新的技术栈,可以作为项目的启动模版,以帮助你快速搭建企业级中后台产品原型。也可以作为一个示例,用于学习 vue3vitets 等主流技术。该项目会持续跟进最新技术,并将其应用在项目中。

文档

  • 中文文档地址为 vben-admin-doc,采用 Vitepress 开发。如发现文档有误,欢迎提 pr 帮助我们改进。
  • 英文文档暂时没有时间来写,欢迎有时间的同学来帮忙写英文文档。

本地运行文档

如需本地运行文档,请拉取代码到本地。

# 拉取代码
+git clone https://github.com/vbenjs/vue-vben-admin-doc
+
+# 安装依赖
+yarn
+
+# 运行项目
+yarn dev
+

需要掌握的基础知识

本项目需要一定前端基础知识,请确保掌握 Vue 的基础知识,以便能处理一些常见的问题。 建议在开发前先学一下以下内容,提前了解和学习这些知识,会对项目理解非常有帮助:

模版

该版本主要是提供一些 Demo 示例及插件的使用集成方式,主要用于参考。如果对项目不是很熟悉,不建议在此基础上进行开发,请使用下方提供的精简版本。

vue-vben-admin 精简版本。删除了相关示例、无用文件及功能、依赖。可以根据自身需求安装对应的依赖。因为使用的是 vite,依赖删除不会导致相关组件或者 hook 发出警告。只在需要的时候安装对应的库即可。

vite 插件推荐

如果这些插件对你有帮助,可以给一个 star 支持下

浏览器支持

本地开发推荐使用Chrome 最新版浏览器,不支持Chrome 80以下版本。

生产环境支持现代浏览器,不支持 IE。

IEIE EdgeEdgeFirefoxFirefoxChromeChromeSafariSafari
not supportlast 2 versionslast 2 versionslast 2 versionslast 2 versions

如何加入我们

  • Vue-Vben-Admin 还在持续更新中,本项目欢迎您的参与,共同维护,逐步完善,将项目做得更强。同时整个项目本着一切免费的原则,原则上不会收取任何费用及版权,可以放心使用。
  • 如果你想加入我们,可以多提供一些好的建议或者提交 pr,我们会根据你的活跃度邀请你加入。
+ + + + \ No newline at end of file diff --git a/guide/lib.html b/guide/lib.html new file mode 100644 index 00000000..18fd6bbe --- /dev/null +++ b/guide/lib.html @@ -0,0 +1,52 @@ + + + + + + 引入外部模块 | Vben Admin + + + + + + + + + + + + + + + + +

引入外部模块

除了自带组件以外,有时我们还需要引入其他外部模块。我们以 ant-design-vue 为例:

安装

安装 ant-design-vue

# 在终端输入下面的命令完成安装
+yarn add ant-design-vue
+

使用

全局使用

import { createApp } from 'vue';
+import App from './App.vue';
+import Antd from 'ant-design-vue';
+const app = createApp(App);
+app.use(Antd);
+app.mount('#app');
+

局部使用

<template>
+  <Button>text</Button>
+</template>
+
+<script>
+  import { defineComponent } from 'vue';
+  import { Button } from 'ant-design-vue';
+  export default defineComponent({
+    components: {
+      Button,
+    },
+  });
+</script>
+

注意

  • 如果组件有依赖样式,则需要再引入样式文件
+ + + + \ No newline at end of file diff --git a/guide/menu.html b/guide/menu.html new file mode 100644 index 00000000..d82797f8 --- /dev/null +++ b/guide/menu.html @@ -0,0 +1,89 @@ + + + + + + 菜单 | Vben Admin + + + + + + + + + + + + + + + + +

菜单

项目菜单配置存放于 src/router/menus 下面

提示

菜单必须和路由匹配才能显示

菜单项类型

export interface Menu {
+  //  菜单名
+  name: string;
+  // 菜单图标,如果没有,则会尝试使用route.meta.icon
+  icon?: string;
+  // 菜单路径
+  path: string;
+  // 是否禁用
+  disabled?: boolean;
+  // 子菜单
+  children?: Menu[];
+  // 菜单标签设置
+  tag: {
+    // 为true则显示小圆点
+    dot: boolean;
+    // 内容
+    content: string';
+    // 类型
+    type: 'error' | 'primary' | 'warn' | 'success';
+  };
+  // 是否隐藏菜单
+  hideMenu?: boolean;
+}
+

菜单模块

一个菜单文件会被当作一个模块

提示

children 的 path 字段不需要以/开头

import type { MenuModule } from '/@/router/types';
+import { t } from '/@/hooks/web/useI18n';
+const menu: MenuModule = {
+  orderNo: 10,
+  menu: {
+    name: t('routes.dashboard.dashboard'),
+    path: '/dashboard',
+
+    children: [
+      {
+        path: 'analysis',
+        name: t('routes.dashboard.analysis'),
+      },
+      {
+        path: 'workbench',
+        name: t('routes.dashboard.workbench'),
+      },
+    ],
+  },
+};
+export default menu;
+

以上模块会转化成以下结构

[
+  path: '/dashboard',
+  name: t('routes.dashboard.dashboard'),
+  children: [
+    {
+      path: 'dashboard/analysis',
+      name: t('routes.dashboard.analysis'),
+    },
+    {
+      path: 'dashboard/workbench',
+      name: t('routes.dashboard.workbench'),
+    },
+  ],
+]
+

新增菜单

直接在 src/router/routes/modules 内新增一个模块文件即可。

不需要手动引入,放在src/router/routes/modules 内的文件会自动被加载。

菜单排序

在菜单模块内,设置 orderNo 变量,数值越大,排序越靠后

+ + + + \ No newline at end of file diff --git a/guide/mock.html b/guide/mock.html new file mode 100644 index 00000000..3c047948 --- /dev/null +++ b/guide/mock.html @@ -0,0 +1,443 @@ + + + + + + 数据 mock&联调 | Vben Admin + + + + + + + + + + + + + + + + +

数据 mock&联调

开发环境

如果前端应用和后端接口服务器没有运行在同一个主机上,你需要在开发环境下将接口请求代理到接口服务器。

如果是同一个主机,可以直接请求具体的接口地址。

配置

开发环境时候,接口地址在项目根目录下

.env.development 文件配置

# vite 本地跨域代理
+VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+# 接口地址
+VITE_GLOB_API_URL=/api
+

TIP

  • .env 文件中的字段如果是字符串,则无需加引号,默认全部为字符串
  • VITE_PROXY 不能换行

跨域处理

如果你在 src/api/ 下面的接口为下方代码,且 .env.development 文件配置如下注释,则在控制台看到的地址为 http://localhost:3100/basic-api/login

由于 /basic-api 匹配到了设置的 VITE_PROXY,所以上方实际是请求 http://localhost:3000/login,这样同时也解决了跨域问题。(3100为项目端口号,http://localhost:3000为PROXY代理的目标地址)

// .env.development
+// VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+// VITE_GLOB_API_URL=/basic-api
+
+enum Api {
+  Login = '/login',
+}
+
+/**
+ * @description: 用户登陆
+ */
+export function loginApi(params: LoginParams) {
+  return http.request<LoginResultModel>({
+    url: Api.Login,
+    method: 'POST',
+    params,
+  });
+}
+

没有跨域时的配置

如果没有跨域问题,可以直接忽略 VITE_PROXY 配置,直接将接口地址设置在 VITE_GLOB_API_URL

# 例如接口地址为 http://localhost:3000 则
+VITE_GLOB_API_URL=http://localhost:3000
+

如果有跨域问题,将 VITE_GLOB_API_URL 设置为跟 VITE_PROXY 内其中一个数组的第一个项一致的值即可。

下方的接口地址设置为 /basic-api,当请求发出的时候会经过 Vite 的 proxy 代理,匹配到了我们设置的 VITE_PROXY 规则,将 /basic-api 转化为 http://localhost:3000 进行请求

# 例如接口地址为 http://localhost:3000 则
+VITE_PROXY=[["/basic-api","http://localhost:3000"]]
+# 接口地址
+VITE_GLOB_API_URL=/basic-api
+

跨域原理解析

vite.config.ts 配置文件中,提供了 server 的 proxy 功能,用于代理 API 请求。

server: {
+  proxy: {
+    "/basic-api":{
+      target: 'http://localhost:3000',
+      changeOrigin: true,
+      ws: true,
+      rewrite: (path) => path.replace(new RegExp(`^/basic-api`), ''),
+    }
+  },
+},
+

注意

从浏览器控制台的 Network 看,请求是 http://localhost:3000/basic-api/xxx,这是因为 proxy 配置不会改变本地请求的 url。

生产环境

生产环境接口地址在项目根目录下 .env.production 文件配置。

生产环境接口地址值需要修改 VITE_GLOB_API_URL,如果出现跨域问题,可以使用 nginx 或者后台开启 cors 进行处理

打包后如何进行地址修改?

VITE_GLOB_* 开头的变量会在打包的时候注入 _app.config.js 文件内。

dist/_app.config.js 修改相应的接口地址后刷新页面即可,不需要在根据不同环境打包多次,一次打包可以用于多个不同接口环境的部署。

接口请求

在 vue-vben-admin 中:

  1. 页面交互操作;
  2. 调用统一管理的 api 请求函数;
  3. 使用封装的 axios.ts 发送请求;
  4. 获取服务端返回数据
  5. 更新 data;

接口统一存放于 src/api/ 下面管理

以登陆接口为例:

src/api/ 内新建模块文件,其中参数与返回值最好定义一下类型,方便校验。虽然麻烦,但是后续维护字段很方便。

TIP

类型定义文件可以抽取出去统一管理,具体参考项目

import { defHttp } from '/@/utils/http/axios';
+import { LoginParams, LoginResultModel } from './model/userModel';
+
+enum Api {
+  Login = '/login',
+}
+
+export function loginApi(params: LoginParams) {
+  return defHttp.request<LoginResultModel>({
+    url: Api.Login,
+    method: 'POST',
+    params,
+  });
+}
+

axios 配置

axios 请求封装存放于 src/utils/http/axios 文件夹内部

index.ts 文件内容需要根据项目自行修改外,其余文件无需修改


+├── Axios.ts // axios实例
+├── axiosCancel.ts // axiosCancel实例,取消重复请求
+├── axiosTransform.ts // 数据转换类
+├── checkStatus.ts // 返回状态值校验
+├── index.ts // 接口返回统一处理
+
+

index.ts 配置说明

const axios = new VAxios({
+  // 认证方案,例如: Bearer
+  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
+  authenticationScheme: '',
+  // 接口超时时间 单位毫秒
+  timeout: 10 * 1000,
+  // 接口可能会有通用的地址部分,可以统一抽取出来
+  prefixUrl: prefix,
+  headers: { 'Content-Type': ContentTypeEnum.JSON },
+  // 数据处理方式,见下方说明
+  transform,
+  // 配置项,下面的选项都可以在独立的接口请求中覆盖
+  requestOptions: {
+    // 默认将prefix 添加到url
+    joinPrefix: true,
+    // 是否返回原生响应头 比如:需要获取响应头时使用该属性
+    isReturnNativeResponse: false,
+    // 需要对返回数据进行处理
+    isTransformRequestResult: true,
+    // post请求的时候添加参数到url
+    joinParamsToUrl: false,
+    // 格式化提交参数时间
+    formatDate: true,
+    // 消息提示类型
+    errorMessageMode: 'message',
+    // 接口地址
+    apiUrl: globSetting.apiUrl,
+    //  是否加入时间戳
+    joinTime: true,
+    // 忽略重复请求
+    ignoreCancelToken: true,
+  },
+});
+

transform 数据处理说明

类型定义,见 axiosTransform.ts 文件

export abstract class AxiosTransform {
+  /**
+   * @description: 请求之前处理配置
+   */
+  beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig;
+
+  /**
+   * @description: 请求成功处理
+   */
+  transformRequestData?: (res: AxiosResponse<Result>, options: RequestOptions) => any;
+
+  /**
+   * @description: 请求失败处理
+   */
+  requestCatch?: (e: Error) => Promise<any>;
+
+  /**
+   * @description: 请求之前的拦截器
+   */
+  requestInterceptors?: (config: AxiosRequestConfig) => AxiosRequestConfig;
+
+  /**
+   * @description: 请求之后的拦截器
+   */
+  responseInterceptors?: (res: AxiosResponse<any>) => AxiosResponse<any>;
+
+  /**
+   * @description: 请求之前的拦截器错误处理
+   */
+  requestInterceptorsCatch?: (error: Error) => void;
+
+  /**
+   * @description: 请求之后的拦截器错误处理
+   */
+  responseInterceptorsCatch?: (error: Error) => void;
+}
+
+
+

项目默认 transform 处理逻辑,可以根据各自项目进行处理。一般需要更改的部分为下方代码,见代码注释说明

/**
+ * @description: 数据处理,方便区分多种处理方式
+ */
+const transform: AxiosTransform = {
+  /**
+   * @description: 处理请求数据。如果数据不是预期格式,可直接抛出错误
+   */
+  transformRequestHook: (res: AxiosResponse<Result>, options: RequestOptions) => {
+    const { t } = useI18n();
+    const { isTransformResponse, isReturnNativeResponse } = options;
+    // 是否返回原生响应头 比如:需要获取响应头时使用该属性
+    if (isReturnNativeResponse) {
+      return res;
+    }
+    // 不进行任何处理,直接返回
+    // 用于页面代码可能需要直接获取code,data,message这些信息时开启
+    if (!isTransformResponse) {
+      return res.data;
+    }
+    // 错误的时候返回
+
+    const { data } = res;
+    if (!data) {
+      // return '[HTTP] Request has no return value';
+      throw new Error(t('sys.api.apiRequestFailed'));
+    }
+    //  这里 code,result,message为 后台统一的字段,需要在 types.ts内修改为项目自己的接口返回格式
+    const { code, result, message } = data;
+
+    // 这里逻辑可以根据项目进行修改
+    const hasSuccess = data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS;
+    if (hasSuccess) {
+      return result;
+    }
+
+    // 在此处根据自己项目的实际情况对不同的code执行不同的操作
+    // 如果不希望中断当前请求,请return数据,否则直接抛出异常即可
+    let timeoutMsg = '';
+    switch (code) {
+      case ResultEnum.TIMEOUT:
+        timeoutMsg = t('sys.api.timeoutMessage');
+      default:
+        if (message) {
+          timeoutMsg = message;
+        }
+    }
+
+    // errorMessageMode=‘modal’的时候会显示modal错误弹窗,而不是消息提示,用于一些比较重要的错误
+    // errorMessageMode='none' 一般是调用时明确表示不希望自动弹出错误提示
+    if (options.errorMessageMode === 'modal') {
+      createErrorModal({ title: t('sys.api.errorTip'), content: timeoutMsg });
+    } else if (options.errorMessageMode === 'message') {
+      createMessage.error(timeoutMsg);
+    }
+
+    throw new Error(timeoutMsg || t('sys.api.apiRequestFailed'));
+  },
+
+  // 请求之前处理config
+  beforeRequestHook: (config, options) => {
+    const { apiUrl, joinPrefix, joinParamsToUrl, formatDate, joinTime = true } = options;
+
+    if (joinPrefix) {
+      config.url = `${urlPrefix}${config.url}`;
+    }
+
+    if (apiUrl && isString(apiUrl)) {
+      config.url = `${apiUrl}${config.url}`;
+    }
+    const params = config.params || {};
+    if (config.method?.toUpperCase() === RequestEnum.GET) {
+      if (!isString(params)) {
+        // 给 get 请求加上时间戳参数,避免从缓存中拿数据。
+        config.params = Object.assign(params || {}, joinTimestamp(joinTime, false));
+      } else {
+        // 兼容restful风格
+        config.url = config.url + params + `${joinTimestamp(joinTime, true)}`;
+        config.params = undefined;
+      }
+    } else {
+      if (!isString(params)) {
+        formatDate && formatRequestDate(params);
+        config.data = params;
+        config.params = undefined;
+        if (joinParamsToUrl) {
+          config.url = setObjToUrlParams(config.url as string, config.data);
+        }
+      } else {
+        // 兼容restful风格
+        config.url = config.url + params;
+        config.params = undefined;
+      }
+    }
+    return config;
+  },
+
+  /**
+   * @description: 请求拦截器处理
+   */
+  requestInterceptors: (config, options) => {
+    // 请求之前处理config
+    const token = getToken();
+    if (token) {
+      // jwt token
+      config.headers.Authorization = options.authenticationScheme
+        ? `${options.authenticationScheme} ${token}`
+        : token;
+    }
+    return config;
+  },
+
+  /**
+   * @description: 响应拦截器处理
+   */
+  responseInterceptors: (res: AxiosResponse<any>) => {
+    return res;
+  },
+
+  /**
+   * @description: 响应错误处理
+   */
+  responseInterceptorsCatch: (error: any) => {
+    const { t } = useI18n();
+    const errorLogStore = useErrorLogStoreWithOut();
+    errorLogStore.addAjaxErrorInfo(error);
+    const { response, code, message, config } = error || {};
+    const errorMessageMode = config?.requestOptions?.errorMessageMode || 'none';
+    const msg: string = response?.data?.error?.message ?? '';
+    const err: string = error?.toString?.() ?? '';
+    let errMessage = '';
+
+    try {
+      if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
+        errMessage = t('sys.api.apiTimeoutMessage');
+      }
+      if (err?.includes('Network Error')) {
+        errMessage = t('sys.api.networkExceptionMsg');
+      }
+
+      if (errMessage) {
+        if (errorMessageMode === 'modal') {
+          createErrorModal({ title: t('sys.api.errorTip'), content: errMessage });
+        } else if (errorMessageMode === 'message') {
+          createMessage.error(errMessage);
+        }
+        return Promise.reject(error);
+      }
+    } catch (error) {
+      throw new Error(error);
+    }
+
+    checkStatus(error?.response?.status, msg, errorMessageMode);
+    return Promise.reject(error);
+  },
+};
+

更改参数格式

项目接口默认为 Json 参数格式,即 headers: { 'Content-Type': ContentTypeEnum.JSON },

如果需要更改为 form-data 格式,更改 headers 的 'Content-TypeContentTypeEnum.FORM_URLENCODED 即可

多个接口地址

当项目中需要用到多个接口地址时, 可以在 src/utils/http/axios/index.ts 导出多个 axios 实例

// 目前只导出一个默认实例,接口地址对应的是环境变量中的 VITE_GLOB_API_URL 接口地址
+export const defHttp = createAxios();
+
+// 需要有其他接口地址的可以在后面添加
+
+// other api url
+export const otherHttp = createAxios({
+  requestOptions: {
+    apiUrl: 'xxx',
+  },
+});
+

删除请求 URL 携带的时间戳参数

如果不需要 url 上面默认携带的时间戳参数 ?_t=xxx

const axios = new VAxios({
+  requestOptions: {
+    // 是否加入时间戳
+    joinTime: false,
+  },
+});
+

Mock 服务

Mock 数据是前端开发过程中必不可少的一环,是分离前后端开发的关键链路。通过预先跟服务器端约定好的接口,模拟请求数据甚至逻辑,能够让前端开发独立自主,不会被服务端的开发进程所阻塞。

本项目使用 vite-plugin-mock 来进行 mock 数据处理。项目内 mock 服务分本地和线上

本地 Mock

本地 mock 采用 Node.js 中间件进行参数拦截(不采用 mock.js 的原因是本地开发看不到请求参数和响应结果)。

如何新增 mock 接口

如果你想添加 mock 数据,只要在根目录下找到 mock 文件,添加对应的接口,对其进行拦截和模拟数据。

在 mock 文件夹内新建文件

TIP

文件新增后会自动更新,不需要手动重启,可以在代码控制台查看日志信息 mock 文件夹内会自动注册,排除以_开头的文件夹及文件

例:

import { MockMethod } from 'vite-plugin-mock';
+import { resultPageSuccess } from '../_util';
+
+const demoList = (() => {
+  const result: any[] = [];
+  for (let index = 0; index < 60; index++) {
+    result.push({
+      id: `${index}`,
+      beginTime: '@datetime',
+      endTime: '@datetime',
+      address: '@city()',
+      name: '@cname()',
+      'no|100000-10000000': 100000,
+      'status|1': ['正常', '启用', '停用'],
+    });
+  }
+  return result;
+})();
+
+export default [
+  {
+    url: '/api/table/getDemoList',
+    timeout: 1000,
+    method: 'get',
+    response: ({ query }) => {
+      const { page = 1, pageSize = 20 } = query;
+      return resultPageSuccess(page, pageSize, demoList);
+    },
+  },
+] as MockMethod[];
+

TIP

mock 的值可以直接使用 mockjs 的语法。

接口格式

{
+  url: string; // mock 接口地址
+  method?: MethodType; // 请求方式
+  timeout?: number; // 延时时间
+  statusCode: number; // 响应状态码
+  response: ((opt: { // 响应结果
+      body: any;
+      query: any;
+  }) => any) | object;
+}
+

参数获取

GET 接口: ({ query }) => { }

POST 接口: ({ body }) => { }

util 说明

可在 代码 中查看

TIP

util 只作为服务处理结果数据使用。可以不用,如需使用可自行封装,需要将对应的字段改为接口的返回结构

匹配

src/api 下面,如果接口匹配到 mock,则会优先使用 mock 进行响应

import { defHttp } from '/@/utils/http/axios';
+import { LoginParams, LoginResultModel } from './model/userModel';
+
+enum Api {
+  Login = '/login',
+}
+
+/**
+ * @description: user login api
+ */
+export function loginApi(params: LoginParams) {
+  return defHttp.request<LoginResultModel>(
+    {
+      url: Api.Login,
+      method: 'POST',
+      params,
+    },
+    {
+      errorMessageMode: 'modal',
+    }
+  );
+}
+// 会匹配到上方的
+export default [
+  {
+    url: '/api/login',
+    timeout: 1000,
+    method: 'POST',
+    response: ({ body }) => {
+      return resultPageSuccess({});
+    },
+  },
+] as MockMethod[];
+

接口有了,如何去掉 mock

当后台接口已经开发完成,只需要将相应的 mock 函数去掉即可。

以上方接口为例,假如后台接口 login 已经开发完成,则只需要删除/注释掉下方代码即可

export default [
+  {
+    url: '/api/login',
+    timeout: 1000,
+    method: 'POST',
+    response: ({ body }) => {
+      return resultPageSuccess({});
+    },
+  },
+] as MockMethod[];
+

线上 mock

由于该项目是一个展示类项目,线上也是用 mock 数据,所以在打包后同时也集成了 mock。通常项目线上一般为正式接口。

项目线上 mock 采用的是 mockjs 进行 mock 数据模拟。

线上如何开启 mock

注意

线上开启 mock 只适用于一些简单的示例网站及预览网站。一定不要在正式的生产环境开启!!!

  1. 修改 .env.production 文件内的 VITE_USE_MOCK 的值为 true
VITE_USE_MOCK = true;
+
  1. mock/_createProductionServer.ts 文件中引入需要的 mock 文件
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
+
+const modules = import.meta.globEager('./**/*.ts');
+
+const mockModules: any[] = [];
+Object.keys(modules).forEach((key) => {
+  if (key.includes('/_')) {
+    return;
+  }
+  mockModules.push(...modules[key].default);
+});
+
+export function setupProdMockServer() {
+  createProdMockServer(mockModules);
+}
+
  1. build/vite/plugin/mock.ts 里面引入
import { viteMockServe } from 'vite-plugin-mock';
+
+export function configMockPlugin(isBuild: boolean) {
+  return viteMockServe({
+    injectCode: `
+      import { setupProdMockServer } from '../mock/_createProductionServer';
+
+      setupProdMockServer();
+      `,
+  });
+}
+

为什么通过插件注入代码而不是直接在 main.ts 内插入

在插件内通过 injectCode 插入代码,方便控制 mockjs 是否被打包到最终代码内。如果在 main.ts 内判断,如果关闭了 mock 功能,mockjs 也会打包到构建文件内,这样会增加打包体积。

到这里线上 mock 就配置完成了。线上与本地差异不大,比较大的区别是线上在控制台内看不到接口请求日志。

+ + + + \ No newline at end of file diff --git a/guide/router.html b/guide/router.html new file mode 100644 index 00000000..655df449 --- /dev/null +++ b/guide/router.html @@ -0,0 +1,291 @@ + + + + + + 路由 | Vben Admin + + + + + + + + + + + + + + + + +

路由

项目路由配置存放于 src/router/routes 下面。 src/router/routes/modules用于存放路由模块,在该目录下的文件会自动注册。

配置

模块说明

src/router/routes/modules 内的 .ts 文件会被视为一个路由模块。

一个路由模块包含以下结构

import type { AppRouteModule } from '/@/router/types';
+
+import { LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+
+const dashboard: AppRouteModule = {
+  path: '/dashboard',
+  name: 'Dashboard',
+  component: LAYOUT,
+  redirect: '/dashboard/analysis',
+  meta: {
+    icon: 'ion:grid-outline',
+    title: t('routes.dashboard.dashboard'),
+  },
+  children: [
+    {
+      path: 'analysis',
+      name: 'Analysis',
+      component: () => import('/@/views/dashboard/analysis/index.vue'),
+      meta: {
+        affix: true,
+        title: t('routes.dashboard.analysis'),
+      },
+    },
+    {
+      path: 'workbench',
+      name: 'Workbench',
+      component: () => import('/@/views/dashboard/workbench/index.vue'),
+      meta: {
+        title: t('routes.dashboard.workbench'),
+      },
+    },
+  ],
+};
+export default dashboard;
+

多级路由

注意事项

  • 整个项目所有路由 name 不能重复
  • 所有的多级路由最终都会转成二级路由,所以不能内嵌子路由
  • 除了 layout 对应的 path 前面需要加 /,其余子路由都不要以/开头

示例

import type { AppRouteModule } from '/@/router/types';
+import { getParentLayout, LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+const permission: AppRouteModule = {
+  path: '/level',
+  name: 'Level',
+  component: LAYOUT,
+  redirect: '/level/menu1/menu1-1/menu1-1-1',
+  meta: {
+    icon: 'ion:menu-outline',
+    title: t('routes.demo.level.level'),
+  },
+
+  children: [
+    {
+      path: 'tabs/:id', 
+      name: 'TabsParams',
+      component: getParentLayout('TabsParams'),
+      meta: {
+        carryParam: true,
+        hidePathForChildren: true, // 本级path将会在子级菜单中合成完整path时会忽略这一层级
+      },
+      children: [
+        path: 'tabs/id1', // 其上级有标记hidePathForChildren,所以本级在生成菜单时最终的path为  /level/tabs/id1
+        name: 'TabsParams',
+        component: getParentLayout('TabsParams'),
+        meta: {
+          carryParam: true,
+          ignoreRoute: true,  // 本路由仅用于菜单生成,不会在实际的路由表中出现
+        },
+      ]
+    },
+    {
+      path: 'menu1',
+      name: 'Menu1Demo',
+      component: getParentLayout('Menu1Demo'),
+      meta: {
+        title: 'Menu1',
+      },
+      redirect: '/level/menu1/menu1-1/menu1-1-1',
+      children: [
+        {
+          path: 'menu1-1',
+          name: 'Menu11Demo',
+          component: getParentLayout('Menu11Demo'),
+          meta: {
+            title: 'Menu1-1',
+          },
+          redirect: '/level/menu1/menu1-1/menu1-1-1',
+          children: [
+            {
+              path: 'menu1-1-1',
+              name: 'Menu111Demo',
+              component: () => import('/@/views/demo/level/Menu111.vue'),
+              meta: {
+                title: 'Menu111',
+              },
+            },
+          ],
+        },
+      ],
+    },
+  ],
+};
+
+export default permission;
+

Meta 配置说明

export interface RouteMeta {
+  // 路由title  一般必填
+  title: string;
+  // 动态路由可打开Tab页数
+  dynamicLevel?: number;
+  // 动态路由的实际Path, 即去除路由的动态部分;
+  realPath?: string;
+  // 是否忽略权限,只在权限模式为Role的时候有效
+  ignoreAuth?: boolean;
+  // 可以访问的角色,只在权限模式为Role的时候有效
+  roles?: RoleEnum[];
+  // 是否忽略KeepAlive缓存
+  ignoreKeepAlive?: boolean;
+  // 是否固定标签
+  affix?: boolean;
+  // 图标,也是菜单图标
+  icon?: string;
+  // 内嵌iframe的地址
+  frameSrc?: string;
+  // 指定该路由切换的动画名
+  transitionName?: string;
+  // 隐藏该路由在面包屑上面的显示
+  hideBreadcrumb?: boolean;
+  // 如果该路由会携带参数,且需要在tab页上面显示。则需要设置为true
+  carryParam?: boolean;
+  // 隐藏所有子菜单
+  hideChildrenInMenu?: boolean;
+  // 当前激活的菜单。用于配置详情页时左侧激活的菜单路径
+  currentActiveMenu?: string;
+  // 当前路由不再标签页显示
+  hideTab?: boolean;
+  // 当前路由不再菜单显示
+  hideMenu?: boolean;
+  // 菜单排序,只对第一级有效
+  orderNo?: number;
+  // 忽略路由。用于在ROUTE_MAPPING以及BACK权限模式下,生成对应的菜单而忽略路由。2.5.3以上版本有效
+  ignoreRoute?: boolean;
+  // 是否在子级菜单的完整path中忽略本级path。2.5.3以上版本有效
+  hidePathForChildren?: boolean;
+}
+

外部页面嵌套

只需要将 frameSrc 设置为需要跳转的地址即可

const IFrame = () => import('/@/views/sys/iframe/FrameBlank.vue');
+{
+  path: 'doc',
+  name: 'Doc',
+  component: IFrame,
+  meta: {
+    frameSrc: 'https://vvbin.cn/doc-next/',
+    title: t('routes.demo.iframe.doc'),
+  },
+},
+

外链

只需要将 path 设置为需要跳转的HTTP 地址即可

{
+  path: 'https://vvbin.cn/doc-next/',
+  name: 'DocExternal',
+  component: IFrame,
+  meta: {
+    title: t('routes.demo.iframe.docExternal'),
+  },
+}
+

动态路由Tab自动关闭功能

若需要开启该功能,需要在动态路由的meta中设置如下两个参数:

  • dynamicLevel 最大能打开的Tab标签页数
  • realPath 动态路由实际路径(考虑到动态路由有时候可能存在N层的情况, 例:/:id/:subId/:...), 为了减少计算开销, 使用配置方式事先规定好路由的实际路径(注意: 该参数若不设置,将无法使用该功能)
{
+  path: 'detail/:id',
+  name: 'TabDetail',
+  component: () => import('/@/views/demo/feat/tabs/TabDetail.vue'),
+  meta: {
+    currentActiveMenu: '/feat/tabs',
+    title: t('routes.demo.feat.tabDetail'),
+    hideMenu: true,
+    dynamicLevel: 3,
+    realPath: '/feat/tabs/detail',
+  },
+}
+

图标

这里的 icon 配置,会同步到 菜单(icon 的值可以查看此处)。

新增路由

如何新增一个路由模块

  1. src/router/routes/modules 内新增一个模块文件。

示例,新增 test.ts 文件

import type { AppRouteModule } from '/@/router/types';
+import { LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+
+const dashboard: AppRouteModule = {
+  path: '/about',
+  name: 'About',
+  component: LAYOUT,
+  redirect: '/about/index',
+  meta: {
+    icon: 'simple-icons:about-dot-me',
+    title: t('routes.dashboard.about'),
+  },
+  children: [
+    {
+      path: 'index',
+      name: 'AboutPage',
+      component: () => import('/@/views/sys/about/index.vue'),
+      meta: {
+        title: t('routes.dashboard.about'),
+        icon: 'simple-icons:about-dot-me',
+      },
+    },
+  ],
+};
+
+export default dashboard;
+

此时路由已添加完成,不需要手动引入,放在src/router/routes/modules 内的文件会自动被加载。

验证

访问 ip:端口/about/index 出现对应组件内容即代表成功

路由刷新

项目中采用的是重定向方式

实现

import { useRedo } from '/@/hooks/web/usePage';
+import { defineComponent } from 'vue';
+export default defineComponent({
+  setup() {
+    const redo = useRedo();
+    // 执行刷新
+    redo();
+    return {};
+  },
+});
+

Redirect

src/views/sys/redirect/index.vue

import { defineComponent, unref } from 'vue';
+import { useRouter } from 'vue-router';
+export default defineComponent({
+  name: 'Redirect',
+  setup() {
+    const { currentRoute, replace } = useRouter();
+    const { params, query } = unref(currentRoute);
+    const { path } = params;
+    const _path = Array.isArray(path) ? path.join('/') : path;
+    replace({
+      path: '/' + _path,
+      query,
+    });
+    return {};
+  },
+});
+

页面跳转

页面跳转建议采用项目提供的 useGo

方式

import { useGo } from '/@/hooks/web/usePage';
+import { defineComponent } from 'vue';
+export default defineComponent({
+  setup() {
+    const go = useGo();
+
+    // 执行刷新
+    go();
+    go(PageEnum.Home);
+    return {};
+  },
+});
+

多标签页

标签页使用的是 keep-aliverouter-view 实现,实现切换 tab 后还能保存切换之前的状态。

如何开启页面缓存

开启缓存有 3 个条件

  1. src/settings/projectSetting.ts 内将openKeepAlive 设置为 true
  2. 路由设置 name,且不能重复
  3. 路由对应的组件加上 name,与路由设置的 name 保持一致
 {
+   ...,
+    // name
+    name: 'Login',
+    // 对应组件组件的name
+    component: () => import('/@/views/sys/login/index.vue'),
+    ...
+  },
+
+  // /@/views/sys/login/index.vue
+  export default defineComponent({
+    // 需要和路由的name一致
+    name:"Login"
+  });
+

注意

keep-alive 生效的前提是:需要将路由的 name 属性及对应的页面的 name 设置成一样。因为:

include - 字符串或正则表达式,只有名称匹配的组件会被缓存

如何让某个页面不缓存

可在 router.meta 下配置

可以将 ignoreKeepAlive 配置成 true 即可关闭缓存。

export interface RouteMeta {
+  // 是否忽略KeepAlive缓存
+  ignoreKeepAlive?: boolean;
+}
+

如何更改首页路由

首页路由指的是应用程序中的默认路由,当不输入其他任何路由时,会自动重定向到该路由下,并且该路由在Tab上是固定的,即使设置affix: false也不允许关闭

例:首页路由配置的是/dashboard/analysis,那么当直接访问 http://localhost:3100/ 会自动跳转到http://localhost:3100/#/dashboard/analysis 上(用户已登录的情况下)

可以将pageEnum.ts中的BASE_HOME更改为需要你想设置的首页即可

export enum PageEnum {
+    // basic home path
+    // 更改此处即可
+    BASE_HOME = '/dashboard',
+}
+
+
+ + + + \ No newline at end of file diff --git a/guide/settings.html b/guide/settings.html new file mode 100644 index 00000000..015ef6f6 --- /dev/null +++ b/guide/settings.html @@ -0,0 +1,400 @@ + + + + + + 项目配置项 | Vben Admin + + + + + + + + + + + + + + + + +

项目配置项

用于修改项目的配色、布局、缓存、多语言、组件默认配置

环境变量配置

项目的环境变量配置位于项目根目录下的 .env.env.development.env.production

具体可以参考 Vite 文档

.env                # 在所有的环境中被载入
+.env.local          # 在所有的环境中被载入,但会被 git 忽略
+.env.[mode]         # 只在指定的模式中被载入
+.env.[mode].local   # 只在指定的模式中被载入,但会被 git 忽略
+
+

温馨提醒

  • 只有以 VITE_ 开头的变量会被嵌入到客户端侧的包中,你可以项目代码中这样访问它们:
console.log(import.meta.env.VITE_PROT);
+
  • VITE_GLOB_* 开头的的变量,在打包的时候,会被加入_app.config.js配置文件当中.

配置项说明

.env

所有环境适用

# 端口号
+VITE_PORT=3100
+# 网站标题
+VITE_GLOB_APP_TITLE=vben admin
+# 简称,用于配置文件名字 不要出现空格、数字开头等特殊字符
+VITE_GLOB_APP_SHORT_NAME=vben_admin
+

.env.development

开发环境适用

# 是否开启mock数据,关闭时需要自行对接后台接口
+VITE_USE_MOCK=true
+# 资源公共路径,需要以 /开头和结尾
+VITE_PUBLIC_PATH=/
+# 是否删除Console.log
+VITE_DROP_CONSOLE=false
+# 本地开发代理,可以解决跨域及多地址代理
+# 如果接口地址匹配到,则会转发到http://localhost:3000,防止本地出现跨域问题
+# 可以有多个,注意多个不能换行,否则代理将会失效
+VITE_PROXY=[["/api","http://localhost:3000"],["api1","http://localhost:3001"],["/upload","http://localhost:3001/upload"]]
+# 接口地址
+# 如果没有跨域问题,直接在这里配置即可
+VITE_GLOB_API_URL=/api
+# 文件上传接口  可选
+VITE_GLOB_UPLOAD_URL=/upload
+# 接口地址前缀,有些系统所有接口地址都有前缀,可以在这里统一加,方便切换
+VITE_GLOB_API_URL_PREFIX=
+

注意

这里配置的 VITE_PROXY 以及 VITE_GLOB_API_URL, /api 需要是唯一的,不要和接口有的名字冲突

如果你的接口是 http://localhost:3000/api 之类的,请考虑将 VITE_GLOB_API_URL=/xxxx 换成别的名字

.env.production

生产环境适用

# 是否开启mock
+VITE_USE_MOCK=true
+# 接口地址 可以由nginx做转发或者直接写实际地址
+VITE_GLOB_API_URL=/api
+# 文件上传地址 可以由nginx做转发或者直接写实际地址
+VITE_GLOB_UPLOAD_URL=/upload
+# 接口地址前缀,有些系统所有接口地址都有前缀,可以在这里统一加,方便切换
+VITE_GLOB_API_URL_PREFIX=
+# 是否删除Console.log
+VITE_DROP_CONSOLE=true
+# 资源公共路径,需要以 / 开头和结尾
+VITE_PUBLIC_PATH=/
+# 打包是否输出gz|br文件
+# 可选: gzip | brotli | none
+# 也可以有多个, 例如 ‘gzip’|'brotli',这样会同时生成 .gz和.br文件
+VITE_BUILD_COMPRESS = 'gzip'
+# 打包是否压缩图片
+VITE_USE_IMAGEMIN = false
+# 打包是否开启pwa功能
+VITE_USE_PWA = false
+# 是否兼容旧版浏览器。开启后打包时间会慢一倍左右。会多打出旧浏览器兼容包,且会根据浏览器兼容性自动使用相应的版本
+VITE_LEGACY = false
+

生产环境动态配置

说明

当执行yarn build构建项目之后,会自动生成 _app.config.js 文件并插入 index.html

注意: 开发环境不会生成

// _app.config.js
+// 变量名命名规则  __PRODUCTION__xxx_CONF__   xxx:为.env配置的VITE_GLOB_APP_SHORT_NAME
+window.__PRODUCTION__VUE_VBEN_ADMIN__CONF__ = {
+  VITE_GLOB_APP_TITLE: 'vben admin',
+  VITE_GLOB_APP_SHORT_NAME: 'vue_vben_admin',
+  VITE_GLOB_API_URL: '/app',
+  VITE_GLOB_API_URL_PREFIX: '/',
+  VITE_GLOB_UPLOAD_URL: '/upload',
+};
+

作用

_app.config.js 用于项目在打包后,需要动态修改配置的需求,如接口地址。不用重新进行打包,可在打包后修改 /dist/_app.config.js 内的变量,刷新即可更新代码内的局部变量。

如何获取全局变量

想要获取 _app.config.js 内的变量,可以使用 src/hooks/setting/index.ts 提供的函数来进行获取

如何新增(新增一个可动态修改的配置项)

  1. 首先在 .env 或者对应的开发环境配置文件内,新增需要可动态配置的变量,需要以 VITE_GLOB_开头

  2. VITE_GLOB_ 开头的变量会自动加入环境变量,通过在 types/config.d.ts 内修改 GlobEnvConfigGlobConfig 两个环境变量的值来定义新添加的类型

  3. useGlobSetting 函数中添加刚新增的返回值即可

const {
+  VITE_GLOB_APP_TITLE,
+  VITE_GLOB_API_URL,
+  VITE_GLOB_APP_SHORT_NAME,
+  VITE_GLOB_API_URL_PREFIX,
+  VITE_GLOB_UPLOAD_URL,
+} = ENV;
+
+export const useGlobSetting = (): SettingWrap => {
+  // Take global configuration
+  const glob: Readonly<GlobConfig> = {
+    title: VITE_GLOB_APP_TITLE,
+    apiUrl: VITE_GLOB_API_URL,
+    shortName: VITE_GLOB_APP_SHORT_NAME,
+    urlPrefix: VITE_GLOB_API_URL_PREFIX,
+    uploadUrl: VITE_GLOB_UPLOAD_URL
+  };
+  return glob as Readonly<GlobConfig>;
+};
+
+

项目配置

WARNING

项目配置文件用于配置项目内展示的内容、布局、文本等效果,存于localStorage中。如果更改了项目配置,需要手动清空 localStorage 缓存,刷新重新登录后方可生效。

配置文件路径

src/settings/projectSetting.ts

说明

// ! 改动后需要清空浏览器缓存
+const setting: ProjectConfig = {
+  // 是否显示SettingButton
+  showSettingButton: true,
+
+  // 是否显示主题切换按钮
+  showDarkModeToggle: true,
+
+  // 设置按钮位置 可选项
+  // SettingButtonPositionEnum.AUTO: 自动选择
+  // SettingButtonPositionEnum.HEADER: 位于头部
+  // SettingButtonPositionEnum.FIXED: 固定在右侧
+  settingButtonPosition: SettingButtonPositionEnum.AUTO,
+
+  // 权限模式,默认前端角色权限模式
+  // ROUTE_MAPPING: 前端模式(菜单由路由生成,默认)
+  // ROLE:前端模式(菜单路由分开)
+  permissionMode: PermissionModeEnum.ROUTE_MAPPING,
+  // 权限缓存存放位置。默认存放于localStorage
+  permissionCacheType: CacheTypeEnum.LOCAL,
+  // 会话超时处理方案
+  // SessionTimeoutProcessingEnum.ROUTE_JUMP: 路由跳转到登录页
+  // SessionTimeoutProcessingEnum.PAGE_COVERAGE: 生成登录弹窗,覆盖当前页面
+  sessionTimeoutProcessing: SessionTimeoutProcessingEnum.ROUTE_JUMP,
+  // 项目主题色
+  themeColor: primaryColor,
+  // 网站灰色模式,用于可能悼念的日期开启
+  grayMode: false,
+  // 色弱模式
+  colorWeak: false,
+  // 是否取消菜单,顶部,多标签页显示, 用于可能内嵌在别的系统内
+  fullContent: false,
+  // 主题内容宽度
+  contentMode: ContentEnum.FULL,
+  // 是否显示logo
+  showLogo: true,
+  // 是否显示底部信息 copyright
+  showFooter: true,
+  // 头部配置
+  headerSetting: {
+    // 背景色
+    bgColor: '#ffffff',
+    // 固定头部
+    fixed: true,
+    // 是否显示顶部
+    show: true,
+    // 主题
+    theme: MenuThemeEnum.LIGHT,
+    // 开启锁屏功能
+    useLockPage: true,
+    // 显示全屏按钮
+    showFullScreen: true,
+    // 显示文档按钮
+    showDoc: true,
+    // 显示消息中心按钮
+    showNotice: true,
+    // 显示菜单搜索按钮
+    showSearch: true,
+  },
+  // 菜单配置
+  menuSetting: {
+    // 背景色
+    bgColor: '#273352',
+    // 是否固定住菜单
+    fixed: true,
+    // 菜单折叠
+    collapsed: false,
+    // 折叠菜单时候是否显示菜单名
+    collapsedShowTitle: false,
+    // 是否可拖拽
+    canDrag: true,
+    // 是否显示
+    show: true,
+    // 菜单宽度
+    menuWidth: 180,
+    // 菜单模式
+    mode: MenuModeEnum.INLINE,
+    // 菜单类型
+    type: MenuTypeEnum.SIDEBAR,
+    // 菜单主题
+    theme: MenuThemeEnum.DARK,
+    // 分割菜单
+    split: false,
+    // 顶部菜单布局
+    topMenuAlign: 'start',
+    // 折叠触发器的位置
+    trigger: TriggerEnum.HEADER,
+    // 手风琴模式,只展示一个菜单
+    accordion: true,
+    // 在路由切换的时候关闭左侧混合菜单展开菜单
+    closeMixSidebarOnChange: false,
+    // 左侧混合菜单模块切换触发方式
+    mixSideTrigger: MixSidebarTriggerEnum.CLICK,
+    // 是否固定左侧混合菜单
+    mixSideFixed: false,
+  },
+  // 多标签
+  multiTabsSetting: {
+    // 刷新后是否保留已经打开的标签页
+    cache: false,
+    // 开启
+    show: true,
+    // 开启快速操作
+    showQuick: true,
+    // 是否可以拖拽
+    canDrag: true,
+    // 是否显示刷新按钮
+    showRedo: true,
+    // 是否显示折叠按钮
+    showFold: true,
+  },
+
+  // 动画配置
+  transitionSetting: {
+    //  是否开启切换动画
+    enable: true,
+    // 动画名
+    basicTransition: RouterTransitionEnum.FADE_SIDE,
+    // 是否打开页面切换loading
+    openPageLoading: true,
+    // 是否打开页面切换顶部进度条
+    openNProgress: false,
+  },
+
+  // 是否开启KeepAlive缓存  开发时候最好关闭,不然每次都需要清除缓存
+  openKeepAlive: true,
+  // 自动锁屏时间,为0不锁屏。 单位分钟 默认1个小时
+  lockTime: 0,
+  // 显示面包屑
+  showBreadCrumb: true,
+  // 显示面包屑图标
+  showBreadCrumbIcon: false,
+  // 是否使用全局错误捕获
+  useErrorHandle: false,
+  // 是否开启回到顶部
+  useOpenBackTop: true,
+  //  是否可以嵌入iframe页面
+  canEmbedIFramePage: true,
+  // 切换界面的时候是否删除未关闭的message及notify
+  closeMessageOnSwitch: true,
+  // 切换界面的时候是否取消已经发送但是未响应的http请求。
+  // 如果开启,想对单独接口覆盖。可以在单独接口设置
+  removeAllHttpPending: true,
+};
+

缓存配置

用于配置缓存内容加密信息,对缓存到浏览器的信息进行 AES 加密

/@/settings/encryptionSetting.ts 内可以配置 localStoragesessionStorage 缓存信息

前提: 使用项目自带的缓存工具类 /@/utils/cache 来进行缓存操作

import { isDevMode } from '/@/utils/env';
+
+// 缓存默认过期时间
+export const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 7;
+
+// 开启缓存加密后,加密密钥。采用aes加密
+export const cacheCipher = {
+  key: '_11111000001111@',
+  iv: '@11111000001111_',
+};
+
+// 是否加密缓存,默认生产环境加密
+export const enableStorageEncryption = !isDevMode();
+

多语言配置

用于配置多语言信息

src/settings/localeSetting.ts 内配置

export const LOCALE: { [key: string]: LocaleType } = {
+  ZH_CN: 'zh_CN',
+  EN_US: 'en',
+};
+
+export const localeSetting: LocaleSetting = {
+  // 是否显示语言选择器
+  showPicker: true,
+  // 当前语言
+  locale: LOCALE.ZH_CN,
+  // 默认语言
+  fallback: LOCALE.ZH_CN,
+  // 允许的语言
+  availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US],
+};
+
+// 语言列表
+export const localeList: DropMenu[] = [
+  {
+    text: '简体中文',
+    event: LOCALE.ZH_CN,
+  },
+  {
+    text: 'English',
+    event: LOCALE.EN_US,
+  },
+];
+

主题色配置

默认全局主题色配置位于 build/config/glob/themeConfig.ts

只需要修改 primaryColor 为您需要的配色,然后重新执行 yarn serve 即可

/**
+ * less global variable
+ */
+export const primaryColor = '#0960bd';
+

样式配置

css 前缀设置

用于修改项目内组件 class 的统一前缀

export const prefixCls = 'vben';
+
@namespace: vben;
+

前缀使用

在 css 内

<style lang="less" scoped>
+  /* namespace已经全局注入,不需要额外再引入 */
+  @prefix-cls: ~'@{namespace}-app-logo';
+
+  .@{prefix-cls} {
+    width: 100%;
+  }
+</style>
+

在 vue/ts 内

import { useDesign } from '/@/hooks/web/useDesign';
+
+const { prefixCls } = useDesign('app-logo');
+
+// prefixCls => vben-app-logo
+

颜色配置

用于预设一些颜色数组

src/settings/designSetting.ts 内配置

//  app主题色预设
+export const APP_PRESET_COLOR_LIST: string[] = [
+  '#0960bd',
+  '#0084f4',
+  '#009688',
+  '#536dfe',
+  '#ff5c93',
+  '#ee4f12',
+  '#0096c7',
+  '#9c27b0',
+  '#ff9800',
+];
+
+// 顶部背景色预设
+export const HEADER_PRESET_BG_COLOR_LIST: string[] = [
+  '#ffffff',
+  '#009688',
+  '#5172DC',
+  '#1E9FFF',
+  '#018ffb',
+  '#409eff',
+  '#4e73df',
+  '#e74c3c',
+  '#24292e',
+  '#394664',
+  '#001529',
+  '#383f45',
+];
+
+// 左侧菜单背景色预设
+export const SIDE_BAR_BG_COLOR_LIST: string[] = [
+  '#001529',
+  '#273352',
+  '#ffffff',
+  '#191b24',
+  '#191a23',
+  '#304156',
+  '#001628',
+  '#28333E',
+  '#344058',
+  '#383f45',
+];
+

组件默认参数配置

src/settings/componentSetting.ts 内配置

// 用于配置某些组件的常规配置,而无需修改组件
+import type { SorterResult } from '../components/Table';
+
+export default {
+  // 表格配置
+  table: {
+    // 表格接口请求通用配置,可在组件prop覆盖
+    // 支持 xxx.xxx.xxx格式
+    fetchSetting: {
+      // 传给后台的当前页字段
+      pageField: 'page',
+      // 传给后台的每页显示多少条的字段
+      sizeField: 'pageSize',
+      // 接口返回表格数据的字段
+      listField: 'items',
+      // 接口返回表格总数的字段
+      totalField: 'total',
+    },
+    // 可选的分页选项
+    pageSizeOptions: ['10', '50', '80', '100'],
+    //默认每页显示多少条
+    defaultPageSize: 10,
+    // 默认排序方法
+    defaultSortFn: (sortInfo: SorterResult) => {
+      const { field, order } = sortInfo;
+      return {
+        // 排序字段
+        field,
+        // 排序方式 asc/desc
+        order,
+      };
+    },
+    // 自定义过滤方法
+    defaultFilterFn: (data: Partial<Recordable<string[]>>) => {
+      return data;
+    },
+  },
+  // 滚动组件配置
+  scrollbar: {
+    // 是否使用原生滚动样式
+    // 开启后,菜单,弹窗,抽屉会使用原生滚动条组件
+    native: false,
+  },
+};
+
+ + + + \ No newline at end of file diff --git a/images/genIcon.png b/images/genIcon.png new file mode 100644 index 00000000..020b0a3b Binary files /dev/null and b/images/genIcon.png differ diff --git a/images/i18n.png b/images/i18n.png new file mode 100644 index 00000000..5cf77fa3 Binary files /dev/null and b/images/i18n.png differ diff --git a/images/outDir.png b/images/outDir.png new file mode 100644 index 00000000..e45c0b2d Binary files /dev/null and b/images/outDir.png differ diff --git a/images/report.png b/images/report.png new file mode 100644 index 00000000..e86860e9 Binary files /dev/null and b/images/report.png differ diff --git a/images/selectIconSet.png b/images/selectIconSet.png new file mode 100644 index 00000000..d5835604 Binary files /dev/null and b/images/selectIconSet.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..a98db606 --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ + + + + + + Vben Admin + + + + + + + + + + + + + + + + +

Vben Admin

一个开箱即用的前端框架

💡 最新技术栈

基于Vue3、Vite、TypeScript等最新技术栈开发

⚡️ 轻量快速的热重载

无论应用程序大小如何,都始终极快的模块热重载(HMR)

🛠️ 丰富的示例

常见的Web端插件示例实现

📦 组件封装

对日常使用频率较高的组件二次封装,满足基础工作需求

🔩 主题配置

丰富的主题配置及黑暗主题适配

🔑 权限管理

完善的前后端权限管理方案

MIT Licensed | Copyright © 2021-present Vben

+ + + + \ No newline at end of file diff --git a/logo.png b/logo.png new file mode 100644 index 00000000..cd4c33d8 Binary files /dev/null and b/logo.png differ diff --git a/other/donate.html b/other/donate.html new file mode 100644 index 00000000..e18a979f --- /dev/null +++ b/other/donate.html @@ -0,0 +1,31 @@ + + + + + + 赞助 | Vben Admin + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/other/doubt.html b/other/doubt.html new file mode 100644 index 00000000..7a56b6e4 --- /dev/null +++ b/other/doubt.html @@ -0,0 +1,53 @@ + + + + + + 常见疑点说明 | Vben Admin + + + + + + + + + + + + + + + + +

常见疑点说明

该分类主要说明一些地方为什么这样做,以及原因是什么

项目别名

/@/vite 内配置的别名

/@/settings 等同于 src/settings

为什么是/@/

因为项目是从 vite1.0 过渡过来的,vite1.0 只能以 / 开头,所以有一部分从 webpack 用户转过来的可能不习惯。

为什么在本地没有按需引入组件库样式,在生产才引入

在 main.ts 内可以看到,本地开发会全量引入 antd.less,vite-plugin-style-import 在本地是没有作用的。

这样做的原因主要是加快本地开发刷新速度。如果在本地开发中也按需按需引入,则在浏览器控制台内可以看到,平均一个页面大概增加了 100 次 http 请求。如果全量引入,只增加了一个请求,所以为了减少请求数量,才这样种。

// src/main.ts
+if (import.meta.env.DEV) {
+  import('ant-design-vue/dist/antd.less');
+}
+
+// build/vite/plugin/styleImport
+import styleImport from 'vite-plugin-style-import';
+export function configStyleImportPlugin(isBuild: boolean) {
+  if (!isBuild) return [];
+  const styleImportPlugin = styleImport({
+    libs: [
+      {
+        libraryName: 'ant-design-vue',
+        esModule: true,
+        resolveStyle: (name) => {
+          return `ant-design-vue/es/${name}/style/index`;
+        },
+      },
+    ],
+  });
+  return styleImportPlugin;
+}
+

为什么单独把 moment 放到 dataUtil 内

src/utils/dataUtil 内,使用的是 moment,其次在页面中对时间的操作也是使用 dateUtil,而不是直接 import moment from 'moment'

这样做主要是方便后续切换到 dayjs,因为 api 一样,所以在后续切换中,只需更改 dataUtil 内的 import 即可,而不用全部更改。

+ + + + \ No newline at end of file diff --git a/other/faq.html b/other/faq.html new file mode 100644 index 00000000..fcf120f5 --- /dev/null +++ b/other/faq.html @@ -0,0 +1,97 @@ + + + + + + 常见问题 | Vben Admin + + + + + + + + + + + + + + + + +

常见问题

TIP

列举了一些常见的问题。有问题可以先来这里寻找,如果没有可以在 issue 提。

前言

遇到问题,可以先从以下几个方面查找

  1. 对应模块的 GitHub 仓库 issue 搜索
  2. google搜索问题
  3. 百度搜索问题
  4. 在下面列表找不到问题可以到 issue 提问 issues
  5. 如果不是问题类型的,需要讨论的,请到 discussions 讨论

关于缓存更新问题

vben-admin 的项目配置默认是缓存在 localStorage 内,所以版本更新后可能有些配置没改变。

解决方式是每次更新代码的时候修改 package.json 内的 version 版本号. 因为 localStorage 的 key 是根据版本号来的。所以更新后版本不同前面的配置会失效。重新登录即可

VUE_VBEN_ADMIN__DEVELOPMENT__2.0.3__COMMON__LOCAL__KEY__ key 的组成是 [项目名]+[开发环境]+[版本号]+[key]

关于修改配置文件的问题

当修改 .env 等环境文件及 vite.config.ts 文件时,vite 会自动重启服务。

自动重启有几率出现问题,请重新运行项目即可解决.

esbuild 模式下开启 LEGACY 打包失败

如果将  build.minify 设置为 'esbuild',且不能启用 LEGACY,否则打包将会报错,两者选其一即可打包。

ant-design-vue 控制台警告

在控制台看到以下警告的原因是 ant-design-vue 会检测是否使用了 babel-plugin-import 来判断是否进行了组件库的按需引入。

但是项目使用的是 vite 的插件 vite-plugin-style-import 来进行按需引入。在 vite 内没必要使用 babel 在转换一次代码了。

所以想关闭这个警告,得等 ant-design-vue 提供可以关闭该警告的配置。

You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size. Not support Vite !!!
+

添加菜单后没显示

菜单必须和路由匹配才会显示在界面上,所以得确保菜单和对应的路由存在即可显示.

imagemin 依赖安装失败

由于 imagemin 在国内安装困难,提供以下几个解决方案:

  1. 使用 yarn 在 package.json 内配置(推荐,项目内已集成,前提是必须使用 yarn)
"resolutions": {
+  "bin-wrapper": "npm:bin-wrapper-china"
+}
+
  1. 使用 npm,在电脑 host 文件加上如下配置即可
199.232.4.133 raw.githubusercontent.com
+

使用 yarn 安装 imagemin 依赖安装失败

如果使用 yarn 还是不能安装依赖,可以将图片压缩功能移除,移除方法如下:

  • package.json 内删除 vite-plugin-imagemin 这个依赖。这会导致图片没有压缩,但是可以手动到在线网站进行压缩。这里推荐tinypng
    1. 注释 vite-plugin-imagemin 插件引用
import { configImageminPlugin } from './imagemin';
+VITE_USE_IMAGEMIN && vitePlugins.push(configImageminPlugin());
+

在 Linux 内依赖安装失败

如果执行 yarn install 会出现以下错误:

gifsicle pre-build test failed
+compiling from source
+

可能是 linux 服务器需要配置下环境,imagemin 这个会导致依赖安装失败。

这里以Centos为例

  • 解决方式 1:
  1. 将以下内容添加到 yum 源
[nasm]
+name=The Netwide Assembler
+baseurl=http://www.nasm.us/pub/nasm/stable/linux/
+enabled=1
+gpgcheck=0
+
+[nasm-testing]
+name=The Netwide Assembler (release candidate builds)
+baseurl=http://www.nasm.us/pub/nasm/testing/linux/
+enabled=0
+gpgcheck=0
+
+[nasm-snapshot]
+name=The Netwide Assembler (daily snapshot builds)
+baseurl=http://www.nasm.us/pub/nasm/snapshots/latest/linux/
+enabled=0
+gpgcheck=0
+

/etc/yum.repos.d/ 下新建 Centos-Nasm.repo,将以上内容复制到这个文件即可

  1. 执行 yum install libtool automake autoconf nasm
  2. 重新执行 yarn install 即可

本地运行报错

由于 vite 在本地没有转换代码,且代码中用到了可选链等比较新的语法。所以本地开发需要使用版本较高的浏览器(Chrome 85+)进行开发

tab 页切换后页面空白

这是由于开启了路由切换动画,且对应的页面组件存在多个根节点导致的,在页面最外层添加<div></div>即可

错误示例

<template>
+  <!-- 注释也算一个节点 -->
+  <h1>text h1</h1>
+  <h2>text h2</h2>
+</template>
+

正确示例

<template>
+  <div>
+    <h1>text h1</h1>
+    <h2>text h2</h2>
+  </div>
+</template>
+

提示

  • 如果想使用多个根标签,可以禁用路由切换动画
  • template 下面的根注释节点也算一个节点

组件命名问题

目前在 vite+vue3.0.5 版本中,如果组件命名携带关键字,则可能会导致内存溢出。例如 ImportExcel excel 导入组件。

我的代码本地开发可以,打包就不行了

目前发现这个原因可能有以下,可以从以下原因来排查,如果还有别的可能,可以提交 pr 来告诉我

  1. 使用了 ctx 这个变量,ctx 本身未暴露出在实例类型内,尤大也是说了不要用这个属性。这个属性只是用于内部使用。
import { getCurrentInstance } from 'vue';
+getCurrentInstance().ctx.xxxx;
+

safari 问题

目前在 safari 上面本地开发运行样式会有问题,还未找到原因,有知道的也可以告诉我。

模版区别

  • Vue-Vben-Admin - 是包含 Demo 示例的,个人建议不要在这上面进行开发。当然,你如果动手能力强的话可以直接改。
  • Vue-Vben-Admin-Thin-Next 精简了代码后的模版项目。适合在这基础上进行二次开发。

环境问题

如果出现依赖安装报错,启动报错等。先检查电脑环境有没有安装齐全。

  • Node 版本必须大于12.0.0不支持 13, 推荐 14 版本。
  • Git
  • Yarn 最新版

依赖安装问题

  • 如果依赖安装不了或者启动报错可以先尝试 删除 yarn.locknode_modules,然后重新运行 yarn install
  • 如果依赖安装不了或者报错,可以尝试切换手机热点来进行依赖安装。
  • 如果还是不行,可以自行配置国内镜像安装。
  • 也可以在项目根目录创建 .npmrc 文件,内容如下
# .npmrc
+registry = https://registry.npm.taobao.org
+

然后重新执行yarn run reinstall等待安装完成即可

如何保证我的代码能更新到最新代码

如果你使用了该项目进行项目开发。开发之中想同步最新的代码。你可以设置多个源的方式

  1. 克隆代码
git clone https://github.com/vbenjs/vben-admin-thin-next.git
+
  1. 添加自己的公司 git 源地址
# up 为源名称,可以随意设置
+# gitUrl为开源最新代码
+git remote add up gitUrl;
+
  1. 提交代码到自己公司 git
# 提交代码到自己公司
+# main为分支名 需要自行根据情况修改
+git push up main
+
+# 同步公司的代码
+# main为分支名 需要自行根据情况修改
+git pull up main
+
  1. 如何同步开源最新代码
git pull origin main
+

TIP

同步代码的时候会出现冲突。只需要把冲突解决即可

打包文件过大

  • 首先,完整版由于引用了比较多的库文件,所以打包会比较大。可以使用精简版来进行开发

  • 其次建议开启 gzip,使用之后体积会只有原先 1/3 左右。

gzip 可以由服务器直接开启。如果是这样,前端不需要构建 .gz 格式的文件

如果前端构建了 .gz 文件,以 nginx 为例,nginx 需要开启 gzip_static: on 这个选项。

  • 开启 gzip 的同时还可以同时开启 brotli,比 gzip 更好的压缩。两者可以共存

注意

  • gzip_static: 这个模块需要 nginx 另外安装,默认的 nginx 没有安装这个模块。

  • 开启 brotli 也需要 nginx 另外安装模块

运行错误

如果出现类似以下错误,请检查项目全路径(包含所有父级路径)不能出现中文、日文、韩文。否则将会出现路径访问 404 导致以下问题

[vite] Failed to resolve module import "ant-design-vue/dist/antd.css-vben-adminode_modulesant-design-vuedistantd.css". (imported by /@/setup/ant-design-vue/index.ts)
+

为什么是 moment.js

很多人问为什么不用dayjs。在项目依赖中可以看到,它是 Ant-Design-Vue 内部自带的。

目前还没有基于 Vite 的 dayjs 替换 momentjs 方案,webpack 已经有了。等以后出现了在进行替换。

控制台路由警告问题

如果看到控制台有如下警告,且页面能正常打开 可以忽略该警告。

后续 vue-router 可能会提供配置项来关闭警告

2.6.1及以上版本已移除此警告

[Vue Router warn]: No match found for location with path "xxxx"
+

启动报错

当出现以下错误信息时,请检查你的 nodejs 版本号是否符合要求

TypeError: str.matchAll is not a function
+at Object.extractor (vue-vben-admin-main\node_modules@purge-icons\core\dist\index.js:146:27)
+at Extract (vue-vben-admin-main\node_modules@purge-icons\core\dist\index.js:173:54)
+
+

页面报错

当页面出现以下报错,是因为 /xxx 对应的路由组件内部出现了错误。

 Uncaught (in promise) Error: Couldn't resolve component "default" at "/xxx"
+
+

可以尝试从以下几点排查

  1. 检查对应组件内部 import 的所有文件是否正确
  2. 检查引入方式是否错误。
// 正确的
+import { cloneDeep } from 'lodash-es';
+
+// 报错
+import _ from 'lodash-es';
+
  1. 检查样式是否使用变量及有没有引入对应的变量文件
  2. 检查代码明显的语法错误

这样就不会是使用的取值忘记 xxx.value 来进行数据获取

跨域问题

参考跨域问题

接口请求问题

proxy 代理不成功,没有代理到实际地址?

代理只是服务请求代理,这个地址是不会变的。 原理可以简单的理解为,在本地启了一个服务,你先请求了本地的服务,本地的服务转发了你的请求到实际服务器。所以你在浏览器上看到的请求地址还是 http://localhost:8000/xxx。以服务端是否收到请求为准。

组件库问题

跟组件库相关的问题可以查看常见问题

+ + + + \ No newline at end of file diff --git a/other/project.html b/other/project.html new file mode 100644 index 00000000..80ebe960 --- /dev/null +++ b/other/project.html @@ -0,0 +1,31 @@ + + + + + + 相关项目 | Vben Admin + + + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/other/server.html b/other/server.html new file mode 100644 index 00000000..de4366cf --- /dev/null +++ b/other/server.html @@ -0,0 +1,40 @@ + + + + + + 测试服务器 | Vben Admin + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file