1つは、Vue3、Vite3、Typescript、Pinia、Unocss、Element-plus、pnpmの中後台モジュールパネルを使用しており、簡単で、配置が可能で、多機能で、優れています。
VSCode + Volar (および Vetur を無効にする) + TypeScript Vue プラグイン (Volar)。
.vue
インポートのタイプのサポートTypeScript はデフォルトでは.vue
インポートの型情報を処理できないため、型チェックのためにtsc
CLI をvue-tsc
に置き換えます。エディターでは、TypeScript 言語サービスに.vue
型を認識させるために、TypeScript Vue プラグイン (Volar) が必要です。
スタンドアロンの TypeScript プラグインでは十分な速度が感じられない場合は、Volar がよりパフォーマンスの高いテイクオーバー モードも実装しています。次の手順で有効にできます。
Extensions: Show Built-in Extensions
TypeScript and JavaScript Language Features
を見つけて右クリックし、 Disable (Workspace)
を選択します。Developer: Reload Window
を実行して、VSCode ウィンドウを再ロードします。 「Vite 設定リファレンス」を参照してください。
pnpm i
pnpm dev
pnpm build
pnpm test:unit
pnpm test:e2e:dev
これにより、Vite 開発サーバーに対してエンドツーエンドのテストが実行されます。実稼働ビルドよりもはるかに高速です。
ただし、(CI 環境などで) デプロイする前に、 test:e2e
を使用して実稼働ビルドをテストすることをお勧めします。
pnpm build
pnpm test:e2e
pnpm lint
docker build -t clover-admin-vue:v0.0.0 -f docker/Dockerfile 。
docker run --name clover -p 80:80 -d clover-admin-vue:v0.0.0
http://localhost
Docker がインストールされていない場合は、以下の手順で Docker をインストールします (Ubuntu20.04 の例):
sudo aptアップデート
sudo apt install apt-transport-https ca-certificatescurl gnupg-agent software-properties-common
カール -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key 追加 -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) 安定版"
sudo aptアップデート
sudo apt install docker-ce docker-ce-clicontainerd.io
sudo aptアップデート
apt list -a docker-ce
5:19.03.9~3-0~ubuntu-focal
)sudo apt install docker-ce= docker-ce-cli=containerd.io
clover-admin
|-- .devcontainer // vscode远程开发配置
| |-- devcontainer.json
| |-- Dockerfile
|-- .husky // git commit提交钩子
|-- .vscode // vscode插件、设置、代码片段
| |-- clover.code-snippets // 代码片段
| |-- extensions.json // 插件
| |-- setting.json // 设置
|-- build // 构建的相关配置和插件
| |-- config
| |-- plugins // vite插件
| | |-- compress.ts // 代码压缩
| | |-- html.ts // html(注入变量、压缩代码)
| | |-- mock.ts // mock插件
| | |-- unplugin.ts // vue宏增强、自动导入、注册注册声明、Icon封装、UI组件
| | |-- visualizer.ts // 打包依赖分析
| |-- utils
|-- cypress // e2e测试框架
|-- doc // 文档相关
|-- docker // docker配置
| |-- .dockerignore
| |-- Dockerfile
| |-- nginx.conf
|-- mock // mock服务
|-- public
|-- src
| |-- assets // 静态资源
| | |-- animation // lottie动画资源
| | |-- svg-icon // 本地svg图标
| |-- components // 全局组件(自动导入)
| | |--business // 业务相关组件
| | |--common // 公共组件(常用组件)
| | |--custom // 自定义组件
| |-- composables // 组合式函数
| |-- config // 全局静态配置
| |-- constants // 全局常量
| |-- directives // vue指令
| |-- enum // TS枚举
| |-- hooks // 组合式的函数hooks(内部状态)
| |-- layout // 布局组件
| |-- plugins // 插件
| |-- router // vue路由
| | |-- guard
| | |-- helper
| | |-- modules
| | |-- routes
| |-- sdk // 三方sdk
| |-- service // 网络请求
| | |-- api
| | |-- request
| |-- stores // pinia状态管理
| |-- styles // 全局样式
| | |-- css
| | |-- less
| | |-- scss
| |-- typings // TS类型声明
| | |-- api.d.ts // 接口相关的类型声明
| | |-- auto-import.d.ts
| | |-- business.d.ts // 业务相关的类型声明
| | |-- components.d.ts
| | |-- env.d.ts // 项目级、vite相关配置
| | |-- expose.d.ts // vue组件导出类型
| | |-- global.d.ts // 全局类型
| | |-- package.d.ts // 包类型
| | |-- route.d.ts // 路由类型
| | |-- router.d.ts // 路由类型
| | |-- system.d.ts // 系统类型
| | |-- vue.d.ts // vue相关类型
| |-- utils // 工具函数
| | |-- auth
| | |-- common
| | |-- crypto
| | |-- filters
| | |-- router
| | |-- service
| | |-- storage
| |-- views // 页面
| |-- App.vue // vue文件入口
| |-- globalProperties.ts // vue全局变量
| |-- main.ts // 项目入口文件
|-- .editorconfig // 统一编辑器配置
|-- .env // 通用环境配置
|-- .env.config.ts // 请求环境的配置
|-- .env.development // 开发环境配置
|-- .env.production // 生产环境配置
|-- .eslintignore // 配置哪些文件忽略eslint检查
|-- .eslintrc-auto-import.json // auto-import插件的eslint生成文件
|-- .eslintrc.cjs // eslint配置文件
|-- .gitattributes // git配置
|-- .gitignore // 配置git记录时哪些文件忽略
|-- .npmignore // 可忽略
|-- .npmrc // npm配置
|-- .prettierrc.json // prettier代码格式化插件配置
|-- commitlint.config.js // commitlint提交规范插件配置
|-- commitlint.config.ts // commitlint提交规范插件配置
|-- cypress.config.ts // e2e测试框架配置
|-- index.html
|-- LICENSE
|-- package.json
|-- pnpm-lock.yaml
|-- README.md
|-- tsconfig.app.json
|-- tsconfig.config.json
|-- tsconfig.json // TS配置
|-- tsconfig.vitest.json
|-- uno.config.ts // unocss配置
|-- vite.config.ts // vite配置
|-- vitest.config.ts // vitest配置
目根目录太を大幅に取得した場合は、根目录の中の多くが構成ファイルであるため、異なるパッケージが提供する構成ファイル格式が不统一(不单)パッケージは json であり、ファイル パッケージはより優れた定義機能を提供するため、配置ファイルの形式は ts、js などに設定されます)、および一部のファイル パッケージは変更された配置ファイル名をサポートしていません。そのため、根目录庞大は本项目ファイル構成の問題ではありません。この問題は、IDE によって解決されます。
推荐插件: antfu.file-nesting
项目期待一致を維持する発行体验、一系列のvscode構成を構成:
./.vscode/extensions.json
./.vscode/settings.json
./.vscode/clover.code-snippets
./.devcontainer
./.vscode/settings.json
自動入力方式を使用して、vue、vue-router、pinia などを使用し、自動入力コンポーネントと vue3 の応答形式を統合します。 以前は、vue を使用していた可能性があります:
< template >
< div >{{ count }}</ div >
< HelloComponent />
</ template >
< script lang='ts' setup>
import HelloComponent from ' @/components '
import { ref , computed } from ' vue '
const count = ref ( 0 )
const doubled = computed (() => count . value * 2 )
</ script >
より厳密な方法を使用します。vue .value
vue-router、pinia を再度手動で入力する必要はなく、 ./src/components
/src/components 項目にあるすべてのコンポーネントが自動的に削除されます。
< template >
< div >{{ count }}</ div >
< HelloComponent />
</ template >
< script lang='ts' setup>
const count = $ref ( 0 )
const doubled = computed (() => count * 2 )
</ script >
请务必須<script lang='ts' setup>
または<script lang='ts'>
、不要な再写JS、当使用TS時、TypeScript可以およびESLint很好地共用提供型检查、しかし当混入纯JS現在のフロントエンド社の解決策はあまりうまく機能していません。
./src/globalProperties.ts
内にあります$filters
例 // globalProperties.ts
export function setupGlobalProperties ( app : App ) {
installGlobalProperties ( filters , "$filters" ) ;
// ...
}
./src/typings/vue.d.ts
内の $filters の種類も必要です
export { } ;
declare module "vue" {
/** 定义在vue实例上自定义的全局属性的类型 */
export interface ComponentCustomProperties {
$filters : typeof import ( "@/utils/filters" ) ;
}
}
// 模板中
< template >
< p >{{ $filters }}</ p >
</ template >
< script lang="ts" setup>
// setup中
const vm = getCurrentInstance () ! ;
const { $filters } = vm . appContext . config . globalProperties ;
</ script >
一部の三方库は、使用時にその css 形式のファイルを入力する必要があります。一般会は main.ts 内に他の导入を行い、これは本项目将その拆分、すべてのソース ファイルは、 ./src/plugins/assets.ts
に配置されて入力されます。
vite の構成は vite.config.ts にありますが、プラグインには非常に長い構成があるため、そのプラグインの構成はビルド項目の下に分割されています。
直接从官网复制来的图标如下:
< el-icon > < Search /> </ el-icon >
リストは自動的に図マークを挿入する方式を使用しているため、次のように変更する必要があります。
< el-icon > < i-ep-Search /> </ el-icon >
element-plus の図标自動导入官方文: https://element-plus.org/zh-CN/component/icon.html#%E8%87%AA%E5%8A%A8%E5%AF%BC% E5%85%A5
このページは https://iconify.design/ からのすべての図をサポートしています。必要なのは、簡単な構成だけです。 element-plus の画像も https://iconify.design/ 内の 1 つの画像セット、现在https://iconify.design/中に挑戦选一新しい画像セット:
./build/plugins/unplugin.ts
にここに書かれている図标セットの前の名前(mdi): Components ( {
dts : "src/typings/components.d.ts" ,
resolvers : [
IconsResolver ( {
// 自动注册图标组件 how to use: <i-ep-location />
enabledCollections : [ "ep" , "mdi" ] , // 'ep'是element图标集在https://iconify.design/ 里的集合名, 如果你引入或使用了其他图标集, 需要在此把其集合名写上
// ...
} ) ,
]
} ) ,
< i-mdi-github class =" text-22px " />
このページでは、ローカル画像の使用もサポートしています。最初に ./src/assets/svg-icon 項目をダウンロードして./src/assets/svg-icon
項目に配置する必要があります。その後、次の項目を使用できます。
// 假设我们有一个名为403.svg的图标在@/src/assets/svg-icon目录下
< i-local-403 />
// 也可以使用el-icon将其包裹
< el-icon :size =" 400 " > < i-local-403 /> </ el-icon >
以下の例を参照してください。
<!-- iconify图标(动态渲染) -->
< svg-icon icon =" mdi-github " />
<!-- 本地图标(动态渲染) -->
< svg-icon local-icon =" link-icon " />
ヒント: svg-icon を使用して本地図标を态渲染した後、アイコンの色が不跟随伴して変更された場合、これは本地図标内の fill 属性造成による覆い、删削除本地図标内の fill プロパティによるものです。
この記事では、unocss を使用しています。css の書き込みが必要な場合は、関連する css 名: https://uno.antfu.me/ を参照するか、tailwindcss および WindiCSS を参照することもできます。 unocss の文書: https://github.com/unocss/unocss 项目默认集成unocss の presetUno プロパティ包、你可继续集成その他のプロパティ包、これは一切構成在uno.config.ts内。
// 一张圆形的图片
< img class =" w-32 h-32 rounded-full " src ="" />
// 等价于
< img style =" width: 32rem; height: 32rem; border-radius: 9999px; " src ="" />
同時に、unocs の無写法 (再写クラス不要) も解放されます。
// 一张圆形的图片
< img w-32 h-32 rounded-full src ="" />
もし有る css 快捷写法が十分でない場合、自動構成は可能です:
// uno.config.ts
export default defineConfig ( {
// ...
shortcuts : {
"wh-full" : "w-full h-full" ,
"flex-center" : "flex justify-center items-center"
}
} )
< div class =" wh-full " > </ div >
// 等价于
< div class =" w-full h-full " > </ div >
上記の書き込み法だけで十分な要件がある場合は、unocss 構成解析を行うこともできます。
export default defineConfig ( {
// ...
rules : [
/ ^wh-(d+)px$ / ,
( [ , d ] ) => ( {
width : ` ${ d } px` ,
height : ` ${ d } px` ,
} ) ,
]
} )
< div class =" wh-20 " > </ div >
// 等价于
< div class =" w-20px h-20px " > </ div >
unocss もサポート構成主题:
export default defineConfig ( {
// ...
// see: https://tailwindcss.com/docs/theme
theme : {
colors : {
dark : "#18181c" ,
} ,
}
} )
< div class =" bg-dark " > </ div >
// 等价于
< div class =" bg-#18181c " > </ div >
// 等价于普通css
< div style =" background-color: #18181c; " > </ div >
unocss暗黑モード:
export default defineConfig ( {
// 开启
presets : [ presetUno ( { dark : "class" } ) ] ,
} )
// bg-dark仅在暗黑模式下生效
< div class =" dark:bg-dark " > </ div >
./src/router/modules
内に路由配置关于
配置します。./src/router/modules
新建about.ts
import Layout from "@/layout/index.vue" ;
const about = [
{
name : "about" ,
path : "/about" ,
component : Layout , // 全局框架
redirect : "/about/index" , // 重定向
meta : { title : "关于" , hidden : true /** 在侧边菜单中隐藏这一级菜单 */ , order : 7 /** 此菜单在侧边菜单中的显示顺序 */ } ,
children : [
{
path : "index" ,
name : "about_index" , // 请遵循此书写规则"about_index", about即父级的name, index即当前的path
component : ( ) => import ( "@/views/about/index.vue" ) , /** 页面组件 */
meta : {
title : "关于" , /** 侧边菜单中显示的label */
icon : "ep-warning" , /** 侧边菜单中显示的icon */
} ,
} ,
] ,
} ,
] ;
export default about ;
icon構成サポートelement-plus内部配置icon、iconify図标(viteでのアンプラグインへの組み込みが必要)および本地図标、次のとおり:
icon: "ep-icon-name"
icon-name
に置き換え、ep を element-plus 内アイコン化の画像集前缀)icon: "mdi-icon-name"
( icon-name
你の画像名に置き換え、mdiを画像表集の前缀)icon: "local-icon-name"
(将icon-name
代替は@/assets/svg-icon
目录下の文書名)./src/views
中在./src/views
新建目录about、在about目录中新建index.vue: < template >
< dark-mode-container class = " h-full " >
< el-card class = " h-full " >关于</ el-card >
</ dark-mode-container >
</ template >
< script lang="ts" setup></ script >
< style lang="less" scoped>
.el-card {
#ep .el-card-rounded ();
}
</ style >
本项目将网络请求统一在./src/service
目录下。 結果の参考例、请见: ./src/views/function/request
。 必要な API、次の手順が必要です:
./src/service/request/index.ts
内でリクエストの例を作成します import { createRequest } from "./request" ;
export const mockRequest = createRequest ( { baseURL : "/mock" } ) ;
./src/service/api
目录下リスクapi // /api/auth.ts
import { mockRequest } from "../request" ;
export function fetchLogin ( username : string , password : string ) {
return mockRequest . post < ApiAuth . Token > ( "/login" , { username , password } ) ;
}
./src/typings/api.d.ts
にある api 関連のデータの種類 declare namespace ApiAuth {
/** token */
interface Token {
token : string ;
}
}
< script lang="ts" setup>
import { fetchLogin } from " @/service " ;
const requestLogin = async () => {
const { data } = await fetchLogin ( " lalala " , " 123456 " );
if ( data ) {
console . log ( " data " , data ); // { token: "这是token" }
}
}
</ script >
./src/service/request
中已经统一做好了処理のため、コード判断は必要ありません:./src/utils/service/error.ts
中の handleAxiosError./src/config/service.ts
内の ERROR_STATUS const response = {
code : 200 ,
message : "成功" ,
data : "SomeObjectOrOther"
}
後端が返すデータ構造が上記と一致しない場合、構築要求時に構成を実行できます。
export const mockRequest = createRequest ( { baseURL : "/mock" } , {
codeField : "statusCode" ,
dataField : "data" ,
msgField : "msg" ,
successCode : 0 ,
} ) ;
mockRequest を使用して要求を発行したときに、後端から返された statusCode が 0 ではない場合、メッセージを出力することを示し、内容が msg フィールドの内容であることを示します。
< script lang="ts" setup>
import { fetchLogin } from " @/service " ;
const requestLogin = async () => {
const { data } = await fetchLogin ( " lalala " , " 123456 " );
if ( data ) {
console . log ( " data " , data ); // { token: "这是token" }
}
}
</ script >
例のように、インターフェイスに返されたデータの内容のみを取得できます。その他の内容を取得できる場合は、API 時に構成を実行できます。
export function fetchLogin ( username : string , password : string ) {
// entries可以配置所有的AxiosResponse的key
return mockRequest . post < ApiAuth . Token > ( "/login" , { username , password } , { entries : [ "data" , "headers" ] } ) ;
}
现在、你可到响应头了
< script lang="ts" setup>
import { fetchLogin } from " @/service " ;
const requestLogin = async () => {
const { data, headers } = await fetchLogin ( " lalala " , " 123456 " );
console . log ( " data " , data ); // { token: "这是token" }
console . log ( " headers " , headers );
}
</ script >
const message = {
code : 200 ,
message : "成功"
}
本项会自动的补充データ:
const message = {
code : 200 ,
message : "成功" ,
data : "success"
}
// .env.config.ts
const serviceEnv : ServiceEnv = {
// 项目默认启动在5574端口
dev : [
/**
* 代理:
* - 将http://127.0.0.1:5574/my-api/xx代理到http://127.0.0.1:5976/backend-api/xx
* - 也可以不写rewritten, 默认情况下将: http://127.0.0.1:5574/my-api/xx代理到http://127.0.0.1:5976/xx
*/
{
url : "http://127.0.0.1:5976" ,
urlPattern : "/my-api" ,
rewritten : "/backend-api"
}
] ,
test : [ ] ,
prod : [ ]
}
项目鼓動はデザインモード解决实际问题を使用します。
注意: 特定の設計モードに属するものは、アセンブリなどの注目すべき角度にも依存し、プロセス モード (最初のパラメータを入力すると、すぐに 1 段階のモデル パネルに取り込むことができます) であると見なすことができます。面面モード (コンポーネント内部で頻繁に実行されるため、使用者が気にする必要がない) であると考えることもできます。
@/utils/common/pattern.ts
// 策略模式会执行所有条件为true的策略
const actions = [
[
true ,
( ) => "执行"
] ,
[
false ,
( ) => "不执行"
]
]
exeStrategyActions ( actions ) ;
@utils/common/responsibilitiesChain.ts
// 示例1: 按照添加顺序, 进行链处理
const canBuyChain = new CustomChain ( ) ;
// 按照添加顺序组成责任链
canBuyChain . append (
new ResponsibilitiesChainNode (
( ) => false , // 条件
( ) => "一号" // 条件匹配时执行的动作
)
) ;
canBuyChain . append (
new ResponsibilitiesChainNode (
( ) => true ,
( ) => "二号"
)
) ;
canBuyChain . append (
new ResponsibilitiesChainNode (
( ) => true ,
( ) => "三号"
)
) ;
// 一旦执行成功就返回
const res = canBuyChain . execute ( ) ; // 二号
// 示例2: 灵活设置链处理顺序
const canBuyChain2 = new CustomChain ( ) ;
const chain1 = new ResponsibilitiesChainNode (
( ) => true ,
( ) => "哦耶1"
) ;
const chain2 = new ResponsibilitiesChainNode (
( ) => true ,
( ) => "哦耶2"
) ;
const chain3 = new ResponsibilitiesChainNode (
( ) => true ,
( ) => "哦耶3" // 在最后一个chain设置的成功函数的返回值会返回给链外
) ;
chain1 . setNext ( chain2 ) ;
chain2 . setNext ( chain3 ) ;
canBuyChain2 . append ( chain1 ) ;
// 执行到底返回最后结果, 遇到失败则结束
const res2 = canBuyChain2 . executeAll ( ) ; // 哦耶3
// 执行到底返回全部结果, 遇到失败则结束
const res22 = canBuyChain2 . executeAllSettled ( ) ; // ["哦耶1", "哦耶2", "哦耶3"]
// 示例3: 支持自定义chainNode类
class MyChainNode1 extends ResponsibilitiesChain {
public canHandle ( ) : boolean {
return false ;
}
public doHandle ( ) {
return "一号节点执行成功" ;
}
public errHandle ( ) {
return ;
}
}
class MyChainNode2 extends ResponsibilitiesChain {
public canHandle ( ) : boolean {
return true ;
}
public doHandle ( ) {
return "二号节点执行成功" ;
}
public errHandle ( ) {
return ;
}
}
const myChainNode1 = new MyChainNode1 ( ) ;
const myChainNode2 = new MyChainNode2 ( ) ;
const myChain = new CustomChain ( ) ;
myChain . append ( myChainNode1 ) ;
myChain . append ( myChainNode2 ) ;
const myRes = myChain . execute ( ) ;
@/views/component/complex-form/components/ResponsibilityValidatorForm.vue
参照することもできます。ここでは、コストの問題を解決するための小さなサービスが提供されています。项目使用了诸多三方库、以下列出其文档
参考自: https://www.lfhacks.com/tech/cypress-download-failure/
ネットワークが不完全で、この资源が大きいため、官方による解決方法: CYPRESS_DOWNLOAD_MIRROR の常量の設定は https://download.cypress.io/desktop ですが、オペレーティング システムの常量の設定方法は異なります。以下に列挙します。
Windowsコマンド行
set CYPRESS_DOWNLOAD_MIRROR=https://download.cypress.io/desktop
WindowsPowerShell
$env :CYPRESS_DOWNLOAD_MIRROR= " https://download.cypress.io/desktop "
Linux、Mac
CYPRESS_DOWNLOAD_MIRROR= " https://download.cypress.io/desktop "
設定が完了したら、すぐに再インストールしてください
AutoImport パッケージを参照するには、最初の実行時にeslintrc: {enabled: true}
を設定する必要があります。eslint ファイルを生成します。その後は false に変更できます。
本项目AutoImport の場所./build/plugins/unplugin.ts
AutoImport ( {
// ...
eslintrc : {
enabled : false , // 自动生成全局声明文件, 不需要eslint检查(在.eslintrc-auto-import.json生成成功之后就可以改为false)
filepath : "./.eslintrc-auto-import.json" ,
globalsPropValue : true ,
} ,
} ) ,
开発行時、遇到项目依赖的库有バグ、等不及库作者修正复、可自行修正打补丁
流れは以下の通り:
pnpm パッチ [email protected]
これで、次のフォルダーを編集できるようになります: C:UsersADMINI~1AppDataLocalTemp482a1b2c5aaad6b4abb4d39bab8ef39cuser
pnpm patch-commit C:UsersADMINI~1AppDataLocalTemp482a1b2c5aaad6b4abb4d39bab8ef39cuser
これにより、 patches/[email protected]
/[email protected] ファイルが生成され、package.json 内で自動的に更新されるように構成されます。
{
"pnpm" : {
"patchedDependencies" : {
"[email protected]" : " patches/[email protected] "
}
}
}
優れた取引条件は、発行者が何を行っているかを明確に把握でき、修正日志の自動生成に役立ちます。
pnpm cz
、対話形式の git インターフェイスです。
feat(components): [ HoverLink ] 增加悬浮链接组件(使用命令式语气)
主体行和主体内容之间用空白行隔开(可以有预期时间)
通过一行或多行描述你的修改信息(大批量更改务必描述修改详情)
每一行的首字母大写
且每一行的总字符数限制在72个以内最优, 超过了将不易于他人理解
- 你也可以通过添加子项列表符号来为内容布局
主题标题の格式は:
[ type ] (scope 域): [ messages ]
一般的な例
git を保持する提交历史简洁
如果你更喜欢中文、项目也对此作好了翻译、点这里浏览