Compare commits
110 Commits
master
...
feature/lo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
813547331d | ||
|
|
6b2c7bad00 | ||
|
|
a64433e57b | ||
|
|
2df2e3cffb | ||
|
|
99b207ec59 | ||
|
|
cf1fab8c58 | ||
|
|
aa6f8cfd62 | ||
|
|
fcd44e49d2 | ||
|
|
799a775a8d | ||
|
|
e201381495 | ||
|
|
0e377eefcc | ||
|
|
fc1975f10e | ||
|
|
7717d86bd9 | ||
|
|
70c7c253eb | ||
|
|
883d359149 | ||
|
|
e33726e74e | ||
|
|
9fb056e8cc | ||
|
|
c199a82457 | ||
|
|
7b23a51134 | ||
|
|
32d5e41f2b | ||
|
|
fb2877ff2c | ||
|
|
5db64525a4 | ||
|
|
9389720895 | ||
|
|
d407dbccee | ||
|
|
6c71ba27bf | ||
|
|
6e10763fdb | ||
|
|
ff02f6372c | ||
|
|
aa9aa1c7e6 | ||
|
|
e765823189 | ||
|
|
278c6b7c81 | ||
|
|
c473ce2b86 | ||
|
|
a43aa79734 | ||
|
|
c92b045c8a | ||
|
|
cc7c632af6 | ||
|
|
3fd26fd1e6 | ||
|
|
bbc19319ee | ||
|
|
1f6f15af9d | ||
|
|
feadd95c4f | ||
|
|
29e31c912b | ||
|
|
cfc925b3e6 | ||
|
|
a70783dd55 | ||
|
|
580468a3e9 | ||
|
|
e6b8146ee0 | ||
|
|
6377c11721 | ||
|
|
69ccd6a48d | ||
|
|
4c59bfeb61 | ||
|
|
828fe45a43 | ||
|
|
b76b9e9013 | ||
|
|
e329f77cb2 | ||
|
|
c3ac1584c3 | ||
|
|
4e584fccf3 | ||
|
|
64b59a06a3 | ||
|
|
22145b3893 | ||
|
|
86dc19193a | ||
|
|
748678d6cd | ||
|
|
9a2f29e3e4 | ||
|
|
a4c5f633cf | ||
|
|
9b39f265d3 | ||
|
|
a2d308bc1a | ||
|
|
6c1c8b87a4 | ||
|
|
d1cbb3f1f7 | ||
|
|
1019afc24c | ||
|
|
2d787ac9f1 | ||
|
|
c39fa45dbd | ||
|
|
b8b8ddc467 | ||
|
|
9f15b89fff | ||
|
|
da4fc5900c | ||
|
|
81347f1f53 | ||
|
|
3861919c4f | ||
|
|
8e208e7468 | ||
|
|
32db9d8175 | ||
|
|
d55ae2e97d | ||
|
|
a28d572879 | ||
|
|
036470cdb7 | ||
|
|
a6e787fd5b | ||
|
|
fb8fbf3294 | ||
|
|
f63b39b818 | ||
|
|
26c08e0974 | ||
|
|
ba6616fe4d | ||
|
|
e135339574 | ||
|
|
946d66e456 | ||
|
|
8f14c9b2df | ||
|
|
1c6ac05f16 | ||
|
|
11591eefcf | ||
|
|
7ca392751b | ||
|
|
50adbbe9fe | ||
|
|
0a3904512d | ||
|
|
f2c9e426e5 | ||
|
|
a15d6ec6c3 | ||
|
|
f0d3380b6c | ||
|
|
ad67d13b5a | ||
|
|
dd885ba651 | ||
|
|
60cdc1f50e | ||
|
|
0345b462b5 | ||
|
|
3a16707e3c | ||
|
|
19941f9f15 | ||
|
|
6016504c94 | ||
|
|
5f8609fc02 | ||
|
|
bcdb4e8c95 | ||
|
|
c86bf9e62e | ||
|
|
e677d4fc9e | ||
|
|
898ab51736 | ||
|
|
c79cd2f4c2 | ||
|
|
089ad69a96 | ||
|
|
f259d54035 | ||
|
|
14d4519d03 | ||
|
|
6be244336e | ||
|
|
b0f2b93bbf | ||
|
|
9438489a11 | ||
|
|
3e1a1b4a66 |
4
.browserslistrc
Normal file
4
.browserslistrc
Normal file
@ -0,0 +1,4 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
not dead
|
||||
not ie 11
|
||||
8
.changeset/README.md
Normal file
8
.changeset/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Changesets
|
||||
|
||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
||||
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
||||
|
||||
We have a quick list of common questions to get you started engaging with this project in
|
||||
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
||||
11
.changeset/config.json
Normal file
11
.changeset/config.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
|
||||
"changelog": "@changesets/cli/changelog",
|
||||
"commit": false,
|
||||
"fixed": [],
|
||||
"linked": [],
|
||||
"access": "restricted",
|
||||
"baseBranch": "master",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": []
|
||||
}
|
||||
1
.commitlintrc.js
Normal file
1
.commitlintrc.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from '@vben/commitlint-config';
|
||||
7
.dockerignore
Normal file
7
.dockerignore
Normal file
@ -0,0 +1,7 @@
|
||||
node_modules
|
||||
.git
|
||||
.gitignore
|
||||
*.md
|
||||
dist
|
||||
.turbo
|
||||
dist.zip
|
||||
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -0,0 +1,18 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset=utf-8
|
||||
end_of_line=lf
|
||||
insert_final_newline=true
|
||||
indent_style=space
|
||||
indent_size=2
|
||||
max_line_length = 100
|
||||
trim_trailing_whitespace = true
|
||||
quote_type = single
|
||||
|
||||
[*.{yml,yaml,json}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# https://docs.github.com/cn/get-started/getting-started-with-git/configuring-git-to-handle-line-endings
|
||||
|
||||
# Automatically normalize line endings (to LF) for all text-based files.
|
||||
* text=auto eol=lf
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.{cmd,[cC][mM][dD]} text eol=crlf
|
||||
*.{bat,[bB][aA][tT]} text eol=crlf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.{ico,png,jpg,jpeg,gif,webp,svg,woff,woff2} binary
|
||||
2
.gitconfig
Normal file
2
.gitconfig
Normal file
@ -0,0 +1,2 @@
|
||||
[core]
|
||||
ignorecase = false
|
||||
55
.gitignore
vendored
55
.gitignore
vendored
@ -1,4 +1,33 @@
|
||||
# Logs
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
dist.zip
|
||||
dist.tar
|
||||
dist.war
|
||||
.nitro
|
||||
.output
|
||||
*-dist.zip
|
||||
*-dist.tar
|
||||
*-dist.war
|
||||
coverage
|
||||
*.local
|
||||
**/.vitepress/cache
|
||||
.cache
|
||||
.turbo
|
||||
.temp
|
||||
dev-dist
|
||||
.stylelintcache
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
.VSCodeCounter
|
||||
**/backend-mock/data
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
.eslintcache
|
||||
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
@ -6,20 +35,26 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
vite.config.mts.*
|
||||
vite.config.mjs.*
|
||||
vite.config.js.*
|
||||
vite.config.ts.*
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
# .vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
localSet.js
|
||||
.history
|
||||
|
||||
# 忽略 docs/src 中 sync-change-log.mjs 获得的 changelog 文件
|
||||
apps/docs/src/renderer/CHANGELOG.md
|
||||
apps/docs/src/designer/CHANGELOG.md
|
||||
apps/docs/src/platform/CHANGELOG.md
|
||||
|
||||
# 忽略 turbo-graph 生成的文件
|
||||
dependencies.html
|
||||
dependencies.png
|
||||
|
||||
6
.gitpod.yml
Normal file
6
.gitpod.yml
Normal file
@ -0,0 +1,6 @@
|
||||
ports:
|
||||
- port: 5555
|
||||
onOpen: open-preview
|
||||
tasks:
|
||||
- init: corepack enable && pnpm install
|
||||
command: pnpm run dev:play
|
||||
6
.husky/commit-msg
Normal file
6
.husky/commit-msg
Normal file
@ -0,0 +1,6 @@
|
||||
echo Start running commit-msg hook...
|
||||
|
||||
# Check whether the git commit information is standardized
|
||||
pnpm exec commitlint --edit "$1"
|
||||
|
||||
echo Run commit-msg hook done.
|
||||
3
.husky/post-merge
Normal file
3
.husky/post-merge
Normal file
@ -0,0 +1,3 @@
|
||||
# 每次 git pull 之后, 安装依赖
|
||||
|
||||
pnpm install
|
||||
7
.husky/pre-commit
Normal file
7
.husky/pre-commit
Normal file
@ -0,0 +1,7 @@
|
||||
# update `.vscode/vben-admin.code-workspace` file
|
||||
pnpm vsh code-workspace --auto-commit
|
||||
|
||||
# Format and submit code according to lintstagedrc.js configuration
|
||||
pnpm exec lint-staged
|
||||
|
||||
echo Run pre-commit hook done.
|
||||
20
.lintstagedrc.mjs
Normal file
20
.lintstagedrc.mjs
Normal file
@ -0,0 +1,20 @@
|
||||
export default {
|
||||
'*.md': ['prettier --cache --ignore-unknown --write'],
|
||||
'*.vue': [
|
||||
'prettier --write',
|
||||
'eslint --cache --fix',
|
||||
'stylelint --fix --allow-empty-input',
|
||||
],
|
||||
'*.{js,jsx,ts,tsx}': [
|
||||
'prettier --cache --ignore-unknown --write',
|
||||
'eslint --cache --fix',
|
||||
],
|
||||
'*.{scss,less,styl,html,vue,css}': [
|
||||
'prettier --cache --ignore-unknown --write',
|
||||
'stylelint --fix --allow-empty-input',
|
||||
],
|
||||
'package.json': ['prettier --cache --write'],
|
||||
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': [
|
||||
'prettier --cache --write--parser json',
|
||||
],
|
||||
};
|
||||
1
.node-version
Normal file
1
.node-version
Normal file
@ -0,0 +1 @@
|
||||
20.14.0
|
||||
16
.npmrc
16
.npmrc
@ -1 +1,15 @@
|
||||
registry=http://sy-registry.shiyue.com
|
||||
registry = https://registry.npmmirror.com
|
||||
@sy:registry=http://sy-registry.shiyue.com
|
||||
public-hoist-pattern[]=husky
|
||||
public-hoist-pattern[]=eslint
|
||||
public-hoist-pattern[]=prettier
|
||||
public-hoist-pattern[]=prettier-plugin-tailwindcss
|
||||
public-hoist-pattern[]=stylelint
|
||||
public-hoist-pattern[]=*postcss*
|
||||
public-hoist-pattern[]=@commitlint/*
|
||||
public-hoist-pattern[]=czg
|
||||
|
||||
strict-peer-dependencies=false
|
||||
auto-install-peers=true
|
||||
dedupe-peer-dependents=true
|
||||
engine-strict=true
|
||||
|
||||
18
.prettierignore
Normal file
18
.prettierignore
Normal file
@ -0,0 +1,18 @@
|
||||
dist
|
||||
dev-dist
|
||||
.local
|
||||
.output.js
|
||||
node_modules
|
||||
.nvmrc
|
||||
coverage
|
||||
CODEOWNERS
|
||||
.nitro
|
||||
.output
|
||||
|
||||
|
||||
**/*.svg
|
||||
**/*.sh
|
||||
|
||||
public
|
||||
.npmrc
|
||||
*-lock.yaml
|
||||
1
.prettierrc.mjs
Normal file
1
.prettierrc.mjs
Normal file
@ -0,0 +1 @@
|
||||
export { default } from '@vben/prettier-config';
|
||||
4
.stylelintignore
Normal file
4
.stylelintignore
Normal file
@ -0,0 +1,4 @@
|
||||
dist
|
||||
public
|
||||
__tests__
|
||||
coverage
|
||||
27
.vscode/extensions.json
vendored
27
.vscode/extensions.json
vendored
@ -1,7 +1,30 @@
|
||||
{
|
||||
"recommendations": [
|
||||
// Vue 3 的语言支持
|
||||
"Vue.volar",
|
||||
"Vue.vscode-typescript-vue-plugin",
|
||||
"dbaeumer.vscode-eslint"
|
||||
// 将 ESLint JavaScript 集成到 VS Code 中。
|
||||
"dbaeumer.vscode-eslint",
|
||||
// Visual Studio Code 的官方 Stylelint 扩展
|
||||
"stylelint.vscode-stylelint",
|
||||
// 使用 Prettier 的代码格式化程序
|
||||
"esbenp.prettier-vscode",
|
||||
// 支持 dotenv 文件语法
|
||||
"mikestead.dotenv",
|
||||
// 源代码的拼写检查器
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
// Tailwind CSS 的官方 VS Code 插件
|
||||
"bradlc.vscode-tailwindcss",
|
||||
// iconify 图标插件
|
||||
"antfu.iconify",
|
||||
// i18n 插件
|
||||
"Lokalise.i18n-ally",
|
||||
// CSS 变量提示
|
||||
"vunguyentuan.vscode-css-variables",
|
||||
// 在 package.json 中显示 PNPM catalog 的版本
|
||||
"antfu.pnpm-catalog-lens"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
// 和 volar 冲突
|
||||
"octref.vetur"
|
||||
]
|
||||
}
|
||||
|
||||
37
.vscode/global.code-snippets
vendored
Normal file
37
.vscode/global.code-snippets
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"import": {
|
||||
"scope": "javascript,typescript",
|
||||
"prefix": "im",
|
||||
"body": ["import { $2 } from '$1';"],
|
||||
"description": "Import a module",
|
||||
},
|
||||
"export-all": {
|
||||
"scope": "javascript,typescript",
|
||||
"prefix": "ex",
|
||||
"body": ["export * from '$1';"],
|
||||
"description": "Export a module",
|
||||
},
|
||||
"vue-script-setup": {
|
||||
"scope": "vue",
|
||||
"prefix": "<sc",
|
||||
"body": [
|
||||
"<script setup lang=\"ts\">",
|
||||
"const props = defineProps<{",
|
||||
" modelValue?: boolean,",
|
||||
"}>()",
|
||||
"$1",
|
||||
"</script>",
|
||||
"",
|
||||
"<template>",
|
||||
" <div>",
|
||||
" <slot/>",
|
||||
" </div>",
|
||||
"</template>",
|
||||
],
|
||||
},
|
||||
"vue-computed": {
|
||||
"scope": "javascript,typescript,vue",
|
||||
"prefix": "com",
|
||||
"body": ["computed(() => { $1 })"],
|
||||
},
|
||||
}
|
||||
24
.vscode/launch.json
vendored
Normal file
24
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "vben admin playground dev",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:5555",
|
||||
"env": { "NODE_ENV": "development" },
|
||||
"sourceMaps": true,
|
||||
"webRoot": "${workspaceFolder}/playground"
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "vben admin ele dev",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:10010",
|
||||
"env": { "NODE_ENV": "development" },
|
||||
"sourceMaps": true,
|
||||
"webRoot": "${workspaceFolder}/apps/web-ele"
|
||||
}
|
||||
]
|
||||
}
|
||||
227
.vscode/settings.json
vendored
Normal file
227
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,227 @@
|
||||
{
|
||||
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts",
|
||||
// workbench
|
||||
"workbench.list.smoothScrolling": true,
|
||||
"workbench.startupEditor": "newUntitledFile",
|
||||
"workbench.tree.indent": 10,
|
||||
"workbench.editor.highlightModifiedTabs": true,
|
||||
"workbench.editor.closeOnFileDelete": true,
|
||||
"workbench.editor.limit.enabled": true,
|
||||
"workbench.editor.limit.perEditorGroup": true,
|
||||
"workbench.editor.limit.value": 5,
|
||||
|
||||
// editor
|
||||
"editor.tabSize": 2,
|
||||
"editor.detectIndentation": false,
|
||||
"editor.cursorBlinking": "expand",
|
||||
"editor.largeFileOptimizations": false,
|
||||
"editor.accessibilitySupport": "off",
|
||||
"editor.cursorSmoothCaretAnimation": "on",
|
||||
"editor.guides.bracketPairs": "active",
|
||||
"editor.inlineSuggest.enabled": true,
|
||||
"editor.suggestSelection": "recentlyUsedByPrefix",
|
||||
"editor.acceptSuggestionOnEnter": "smart",
|
||||
"editor.suggest.snippetsPreventQuickSuggestions": false,
|
||||
"editor.stickyScroll.enabled": true,
|
||||
"editor.hover.sticky": true,
|
||||
"editor.suggest.insertMode": "replace",
|
||||
"editor.bracketPairColorization.enabled": true,
|
||||
"editor.autoClosingBrackets": "beforeWhitespace",
|
||||
"editor.autoClosingDelete": "always",
|
||||
"editor.autoClosingOvertype": "always",
|
||||
"editor.autoClosingQuotes": "beforeWhitespace",
|
||||
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.fixAll.stylelint": "explicit",
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
// extensions
|
||||
"extensions.ignoreRecommendations": true,
|
||||
|
||||
// terminal
|
||||
"terminal.integrated.cursorBlinking": true,
|
||||
"terminal.integrated.persistentSessionReviveProcess": "never",
|
||||
"terminal.integrated.tabs.enabled": true,
|
||||
"terminal.integrated.scrollback": 10000,
|
||||
"terminal.integrated.stickyScroll.enabled": true,
|
||||
|
||||
// files
|
||||
"files.eol": "\n",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.simpleDialog.enable": true,
|
||||
"files.associations": {
|
||||
"*.ejs": "html",
|
||||
"*.art": "html",
|
||||
"**/tsconfig.json": "jsonc",
|
||||
"*.json": "jsonc",
|
||||
"package.json": "json"
|
||||
},
|
||||
|
||||
"files.exclude": {
|
||||
"**/.eslintcache": true,
|
||||
"**/bower_components": true,
|
||||
"**/.turbo": true,
|
||||
"**/.idea": true,
|
||||
"**/tmp": true,
|
||||
"**/.git": true,
|
||||
"**/.svn": true,
|
||||
"**/.hg": true,
|
||||
"**/CVS": true,
|
||||
"**/.stylelintcache": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/vite.config.mts.*": true,
|
||||
"**/tea.yaml": true
|
||||
},
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/.git/subtree-cache/**": true,
|
||||
"**/.vscode/**": true,
|
||||
"**/node_modules/**": true,
|
||||
"**/tmp/**": true,
|
||||
"**/bower_components/**": true,
|
||||
"**/dist/**": true,
|
||||
"**/yarn.lock": true
|
||||
},
|
||||
|
||||
// search
|
||||
"search.searchEditor.singleClickBehaviour": "peekDefinition",
|
||||
"search.followSymlinks": false,
|
||||
// 在使用搜索功能时,将这些文件夹/文件排除在外
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/*.log": true,
|
||||
"**/*.log*": true,
|
||||
"**/bower_components": true,
|
||||
"**/dist": true,
|
||||
"**/elehukouben": true,
|
||||
"**/.git": true,
|
||||
"**/.github": true,
|
||||
"**/.gitignore": true,
|
||||
"**/.svn": true,
|
||||
"**/.DS_Store": true,
|
||||
"**/.vitepress/cache": true,
|
||||
"**/.idea": true,
|
||||
"**/.vscode": false,
|
||||
"**/.yarn": true,
|
||||
"**/tmp": true,
|
||||
"*.xml": true,
|
||||
"out": true,
|
||||
"dist": true,
|
||||
"node_modules": true,
|
||||
"CHANGELOG.md": true,
|
||||
"**/pnpm-lock.yaml": true,
|
||||
"**/yarn.lock": true
|
||||
},
|
||||
|
||||
"debug.onTaskErrors": "debugAnyway",
|
||||
"diffEditor.ignoreTrimWhitespace": false,
|
||||
"npm.packageManager": "pnpm",
|
||||
|
||||
"css.validate": false,
|
||||
"less.validate": false,
|
||||
"scss.validate": false,
|
||||
|
||||
// extension
|
||||
"emmet.showSuggestionsAsSnippets": true,
|
||||
"emmet.triggerExpansionOnTab": false,
|
||||
|
||||
"errorLens.enabledDiagnosticLevels": ["warning", "error"],
|
||||
"errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"],
|
||||
|
||||
"stylelint.enable": true,
|
||||
"stylelint.packageManager": "pnpm",
|
||||
"stylelint.validate": ["css", "less", "postcss", "scss", "vue"],
|
||||
"stylelint.customSyntax": "postcss-html",
|
||||
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
|
||||
|
||||
"typescript.inlayHints.enumMemberValues.enabled": true,
|
||||
"typescript.preferences.preferTypeOnlyAutoImports": true,
|
||||
"typescript.preferences.includePackageJsonAutoImports": "on",
|
||||
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"typescript",
|
||||
"javascriptreact",
|
||||
"typescriptreact",
|
||||
"vue",
|
||||
"html",
|
||||
"markdown",
|
||||
"json",
|
||||
"jsonc",
|
||||
"json5"
|
||||
],
|
||||
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
|
||||
],
|
||||
|
||||
"github.copilot.enable": {
|
||||
"*": true,
|
||||
"markdown": true,
|
||||
"plaintext": false,
|
||||
"yaml": false
|
||||
},
|
||||
|
||||
"cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"],
|
||||
|
||||
"i18n-ally.localesPaths": [
|
||||
"packages/locales/src/langs",
|
||||
"playground/src/locales/langs",
|
||||
"apps/*/src/locales/langs"
|
||||
],
|
||||
"i18n-ally.pathMatcher": "{locale}/{namespace}.{ext}",
|
||||
"i18n-ally.enabledParsers": ["json"],
|
||||
"i18n-ally.sourceLanguage": "en",
|
||||
"i18n-ally.displayLanguage": "zh-CN",
|
||||
"i18n-ally.enabledFrameworks": ["vue", "react"],
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.sortKeys": true,
|
||||
"i18n-ally.namespace": true,
|
||||
|
||||
// 控制相关文件嵌套展示
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.expand": false,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"*.ts": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx, $(capture).d.ts",
|
||||
"*.tsx": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx,$(capture).d.ts",
|
||||
"*.env": "$(capture).env.*",
|
||||
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
|
||||
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
|
||||
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json",
|
||||
"tailwind.config.mjs": "postcss.*"
|
||||
},
|
||||
"commentTranslate.hover.enabled": false,
|
||||
"commentTranslate.multiLineMerge": true,
|
||||
"vue.server.hybridMode": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"oxc.enable": false
|
||||
}
|
||||
152
README.md
152
README.md
@ -0,0 +1,152 @@
|
||||
<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="215" src="https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp"> </a> <br> <br>
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
<h1>Vue Vben Admin</h1>
|
||||
</div>
|
||||
|
||||
[](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin)    
|
||||
|
||||
**English** | [中文](./README.zh-CN.md) | [日本語](./README.ja-JP.md)
|
||||
|
||||
## Introduction
|
||||
|
||||
Vue Vben Admin is a free and open source middle and back-end template. Using the latest `vue3`, `vite`, `TypeScript` and other mainstream technology development, the out-of-the-box middle and back-end front-end solutions can also be used for learning reference.
|
||||
|
||||
## Upgrade Notice
|
||||
|
||||
This is the latest version, 5.0, and it is not compatible with previous versions. If you are starting a new project, it is recommended to use the latest version. If you wish to view the old version, please use the [v2 branch](https://github.com/vbenjs/vue-vben-admin/tree/v2).
|
||||
|
||||
## Feature
|
||||
|
||||
- **Latest Technology Stack**: Developed with cutting-edge front-end technologies like Vue 3 and Vite
|
||||
- **TypeScript**: A language for application-scale JavaScript
|
||||
- **Themes**: Multiple theme colors available with customizable options
|
||||
- **Internationalization**: Comprehensive built-in internationalization support
|
||||
- **Permissions**: Built-in solution for dynamic route-based permission generation
|
||||
|
||||
## Preview
|
||||
|
||||
- [Vben Admin](https://vben.pro/) - Full version Chinese site
|
||||
|
||||
Test Account: vben/123456
|
||||
|
||||
<p align="center">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
|
||||
<img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
|
||||
</p>
|
||||
|
||||
### Use Gitpod
|
||||
|
||||
Open the project in Gitpod (free online dev environment for GitHub) and start coding immediately.
|
||||
|
||||
[](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
|
||||
|
||||
## Documentation
|
||||
|
||||
[Document](https://doc.vben.pro/)
|
||||
|
||||
## Install and use
|
||||
|
||||
- Get the project code
|
||||
|
||||
```bash
|
||||
git clone https://github.com/vbenjs/vue-vben-admin.git
|
||||
```
|
||||
|
||||
- Installation dependencies
|
||||
|
||||
```bash
|
||||
cd vue-vben-admin
|
||||
|
||||
corepack enable
|
||||
|
||||
pnpm install
|
||||
```
|
||||
|
||||
- run
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
- build
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## Change Log
|
||||
|
||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
||||
|
||||
## How to contribute
|
||||
|
||||
You are very welcome to join Or submit a Pull Request。
|
||||
|
||||
**Pull Request:**
|
||||
|
||||
1. Fork code!
|
||||
2. Create your own branch: `git checkout -b feat/xxxx`
|
||||
3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
|
||||
4. Push your branch: `git push origin feat/xxxx`
|
||||
5. submit`pull request`
|
||||
|
||||
## Git Contribution submission specification
|
||||
|
||||
- reference [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) specification ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
||||
|
||||
- `feat` Add new features
|
||||
- `fix` Fix the problem/BUG
|
||||
- `style` The code style is related and does not affect the running result
|
||||
- `perf` Optimization/performance improvement
|
||||
- `refactor` Refactor
|
||||
- `revert` Undo edit
|
||||
- `test` Test related
|
||||
- `docs` Documentation/notes
|
||||
- `chore` Dependency update/scaffolding configuration modification etc.
|
||||
- `ci` Continuous integration
|
||||
- `types` Type definition file changes
|
||||
- `wip` In development
|
||||
|
||||
## Browser support
|
||||
|
||||
The `Chrome 80+` browser is recommended for local development
|
||||
|
||||
Support modern browsers, not IE
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| :-: | :-: | :-: | :-: | :-: |
|
||||
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
|
||||
## Maintainer
|
||||
|
||||
[@Vben](https://github.com/anncwb)
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
|
||||
|
||||
## Donate
|
||||
|
||||
If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support!
|
||||
|
||||

|
||||
|
||||
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aee;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
|
||||
|
||||
## Contributor
|
||||
|
||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
||||
<img alt="Contributors"
|
||||
src="https://opencollective.com/vbenjs/contributors.svg?button=false" />
|
||||
</a>
|
||||
|
||||
## Discord
|
||||
|
||||
- [Github Discussions](https://github.com/anncwb/vue-vben-admin/discussions)
|
||||
|
||||
## License
|
||||
|
||||
[MIT © Vben-2020](./LICENSE)
|
||||
52
README.zh-CN.md
Normal file
52
README.zh-CN.md
Normal file
@ -0,0 +1,52 @@
|
||||
## 文档
|
||||
|
||||
[文档地址](https://y-code-docs.shiyuegame.com)
|
||||
|
||||
```bash
|
||||
corepack enable
|
||||
|
||||
pnpm install
|
||||
```
|
||||
|
||||
- 运行
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
- 打包
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
## 更新日志
|
||||
|
||||
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
||||
|
||||
## Git 贡献提交规范
|
||||
|
||||
- 参考 [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) 规范 ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
|
||||
|
||||
- `feat` 增加新功能
|
||||
- `fix` 修复问题/BUG
|
||||
- `style` 代码风格相关无影响运行结果的
|
||||
- `perf` 优化/性能提升
|
||||
- `refactor` 重构
|
||||
- `revert` 撤销修改
|
||||
- `test` 测试相关
|
||||
- `docs` 文档/注释
|
||||
- `chore` 依赖更新/脚手架配置修改等
|
||||
- `ci` 持续集成
|
||||
- `types` 类型定义文件更改
|
||||
- `wip` 开发中
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
本地开发推荐使用`Chrome 80+` 浏览器
|
||||
|
||||
支持现代浏览器, 不支持 IE
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| :-: | :-: | :-: | :-: | :-: |
|
||||
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
8
apps/designer/.env
Normal file
8
apps/designer/.env
Normal file
@ -0,0 +1,8 @@
|
||||
# 通用环境配置
|
||||
ENV = 'development'
|
||||
|
||||
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
|
||||
VITE_BASE_URL = /
|
||||
|
||||
# base api url
|
||||
VITE_BASE_API_URL = ''
|
||||
15
apps/designer/.env.dev-production
Normal file
15
apps/designer/.env.dev-production
Normal file
@ -0,0 +1,15 @@
|
||||
# 只在生产模式中被载入
|
||||
VITE_NODE_ENV = 'development'
|
||||
|
||||
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
|
||||
VITE_BASE_URL = /
|
||||
|
||||
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
|
||||
|
||||
VITE_PORT = 10011
|
||||
|
||||
VITE_DEBUG_MODE = true
|
||||
|
||||
VITE_PLATFORM_URL = 'https://localhost:10010'
|
||||
VITE_DESIGNER_URL = 'https://localhost:10011'
|
||||
VITE_RENDERER_URL = 'https://localhost:10012'
|
||||
16
apps/designer/.env.dev-staging
Normal file
16
apps/designer/.env.dev-staging
Normal file
@ -0,0 +1,16 @@
|
||||
# 只在预发布模式中被载入
|
||||
VITE_NODE_ENV = 'development'
|
||||
|
||||
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
|
||||
VITE_BASE_URL = /
|
||||
|
||||
# base api url
|
||||
VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
|
||||
|
||||
VITE_PORT = 10011
|
||||
|
||||
VITE_DEBUG_MODE = true
|
||||
|
||||
VITE_PLATFORM_URL = 'https://localhost:10010'
|
||||
VITE_DESIGNER_URL = 'https://localhost:10011'
|
||||
VITE_RENDERER_URL = 'https://localhost:10012'
|
||||
15
apps/designer/.env.development
Normal file
15
apps/designer/.env.development
Normal file
@ -0,0 +1,15 @@
|
||||
# 只在开发模式中被载入
|
||||
VITE_NODE_ENV = 'development'
|
||||
|
||||
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
|
||||
VITE_BASE_URL = /
|
||||
|
||||
VITE_PORT = 10011
|
||||
# VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
|
||||
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
|
||||
|
||||
VITE_DEBUG_MODE = true
|
||||
|
||||
VITE_PLATFORM_URL = 'https://localhost:10010'
|
||||
VITE_DESIGNER_URL = 'https://localhost:10011'
|
||||
VITE_RENDERER_URL = 'https://localhost:10012'
|
||||
12
apps/designer/.env.production
Normal file
12
apps/designer/.env.production
Normal file
@ -0,0 +1,12 @@
|
||||
# 只在生产模式中被载入
|
||||
VITE_NODE_ENV = 'production'
|
||||
|
||||
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
|
||||
VITE_BASE_URL = /
|
||||
|
||||
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
|
||||
|
||||
|
||||
VITE_PLATFORM_URL = 'https://y-code.shiyue.com/'
|
||||
VITE_DESIGNER_URL = 'https://y-code-designer.shiyue.com/'
|
||||
VITE_RENDERER_URL = 'https://y-code-renderer.shiyue.com/'
|
||||
12
apps/designer/.env.staging
Normal file
12
apps/designer/.env.staging
Normal file
@ -0,0 +1,12 @@
|
||||
# 只在预发布模式中被载入
|
||||
VITE_NODE_ENV = 'staging'
|
||||
|
||||
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
|
||||
VITE_BASE_URL = /
|
||||
|
||||
# base api url
|
||||
VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
|
||||
|
||||
VITE_PLATFORM_URL = 'https://y-code-pre.shiyue.com/'
|
||||
VITE_DESIGNER_URL = 'https://y-code-designer-pre.shiyue.com/'
|
||||
VITE_RENDERER_URL = 'https://y-code-renderer-pre.shiyue.com/'
|
||||
91
apps/designer/.eslintrc-auto-import.json
Normal file
91
apps/designer/.eslintrc-auto-import.json
Normal file
@ -0,0 +1,91 @@
|
||||
{
|
||||
"globals": {
|
||||
"Component": true,
|
||||
"ComponentPublicInstance": true,
|
||||
"ComputedRef": true,
|
||||
"DirectiveBinding": true,
|
||||
"EffectScope": true,
|
||||
"ExtractDefaultPropTypes": true,
|
||||
"ExtractPropTypes": true,
|
||||
"ExtractPublicPropTypes": true,
|
||||
"InjectionKey": true,
|
||||
"MaybeRef": true,
|
||||
"MaybeRefOrGetter": true,
|
||||
"PropType": true,
|
||||
"Ref": true,
|
||||
"VNode": true,
|
||||
"WritableComputedRef": true,
|
||||
"acceptHMRUpdate": true,
|
||||
"computed": true,
|
||||
"createApp": true,
|
||||
"createPinia": true,
|
||||
"customRef": true,
|
||||
"defineAsyncComponent": true,
|
||||
"defineComponent": true,
|
||||
"defineStore": true,
|
||||
"effectScope": true,
|
||||
"getActivePinia": true,
|
||||
"getCurrentInstance": true,
|
||||
"getCurrentScope": true,
|
||||
"h": true,
|
||||
"inject": true,
|
||||
"isProxy": true,
|
||||
"isReactive": true,
|
||||
"isReadonly": true,
|
||||
"isRef": true,
|
||||
"mapActions": true,
|
||||
"mapGetters": true,
|
||||
"mapState": true,
|
||||
"mapStores": true,
|
||||
"mapWritableState": true,
|
||||
"markRaw": true,
|
||||
"nextTick": true,
|
||||
"onActivated": true,
|
||||
"onBeforeMount": true,
|
||||
"onBeforeRouteLeave": true,
|
||||
"onBeforeRouteUpdate": true,
|
||||
"onBeforeUnmount": true,
|
||||
"onBeforeUpdate": true,
|
||||
"onDeactivated": true,
|
||||
"onErrorCaptured": true,
|
||||
"onMounted": true,
|
||||
"onRenderTracked": true,
|
||||
"onRenderTriggered": true,
|
||||
"onScopeDispose": true,
|
||||
"onServerPrefetch": true,
|
||||
"onUnmounted": true,
|
||||
"onUpdated": true,
|
||||
"onWatcherCleanup": true,
|
||||
"provide": true,
|
||||
"reactive": true,
|
||||
"readonly": true,
|
||||
"ref": true,
|
||||
"resolveComponent": true,
|
||||
"setActivePinia": true,
|
||||
"setMapStoreSuffix": true,
|
||||
"shallowReactive": true,
|
||||
"shallowReadonly": true,
|
||||
"shallowRef": true,
|
||||
"storeToRefs": true,
|
||||
"toRaw": true,
|
||||
"toRef": true,
|
||||
"toRefs": true,
|
||||
"toValue": true,
|
||||
"triggerRef": true,
|
||||
"unref": true,
|
||||
"useAttrs": true,
|
||||
"useCssModule": true,
|
||||
"useCssVars": true,
|
||||
"useId": true,
|
||||
"useLink": true,
|
||||
"useModel": true,
|
||||
"useRoute": true,
|
||||
"useRouter": true,
|
||||
"useSlots": true,
|
||||
"useTemplateRef": true,
|
||||
"watch": true,
|
||||
"watchEffect": true,
|
||||
"watchPostEffect": true,
|
||||
"watchSyncEffect": true
|
||||
}
|
||||
}
|
||||
33
apps/designer/.gitignore
vendored
Normal file
33
apps/designer/.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
.history
|
||||
|
||||
# Project
|
||||
package-lock.json
|
||||
yarn-lock.json
|
||||
pnpm-lock.yaml
|
||||
tsconfig.tsbuildinfo
|
||||
node_modules
|
||||
coverage
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
.vtj/logs
|
||||
.vtj/histories
|
||||
22
apps/designer/.npmrc
Normal file
22
apps/designer/.npmrc
Normal file
@ -0,0 +1,22 @@
|
||||
# 使用淘宝镜像源
|
||||
registry = https://registry.npmmirror.com
|
||||
@sy:registry=http://sy-registry.shiyue.com
|
||||
|
||||
|
||||
# 根据需要提升含有以下的依赖包到根 node_modules 目录下
|
||||
# public-hoist-pattern[]=husky
|
||||
# public-hoist-pattern[]=*eslint*
|
||||
# public-hoist-pattern[]=@eslint*
|
||||
# public-hoist-pattern[]=*prettier*
|
||||
# public-hoist-pattern[]=lint-staged
|
||||
# public-hoist-pattern[]=*stylelint*
|
||||
# public-hoist-pattern[]=@commitlint*
|
||||
# public-hoist-pattern[]=core-js
|
||||
|
||||
# 提升所有依赖到根 node_modules 目录下,相当于 public-hoist-pattern[]=*,与上面一种方式一般二选一使用
|
||||
# 极不推荐用这样的方式解决依赖问题,这样没有充分利用 pnpm 依赖访问安全性的优势,又走回了 npm / yarn 的老路。
|
||||
# shamefully-hoist=true
|
||||
|
||||
enable-pre-post-scripts=true
|
||||
engine-strict=true
|
||||
package-manager-strict=false
|
||||
20
apps/designer/.prettierrc
Normal file
20
apps/designer/.prettierrc
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"arrowParens": "always",
|
||||
"bracketSpacing": true,
|
||||
"bracketSameLine": true,
|
||||
"endOfLine": "lf",
|
||||
"htmlWhitespaceSensitivity": "css",
|
||||
"insertPragma": false,
|
||||
"jsxBracketSameLine": true,
|
||||
"jsxSingleQuote": true,
|
||||
"printWidth": 80,
|
||||
"proseWrap": "preserve",
|
||||
"quoteProps": "as-needed",
|
||||
"requirePragma": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "none",
|
||||
"useTabs": false,
|
||||
"vueIndentScriptAndStyle": false
|
||||
}
|
||||
3
apps/designer/.vscode/extensions.json
vendored
Normal file
3
apps/designer/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["vue.volar"]
|
||||
}
|
||||
7
apps/designer/CHANGELOG.md
Normal file
7
apps/designer/CHANGELOG.md
Normal file
@ -0,0 +1,7 @@
|
||||
# @sy/y-code-designer
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- project changeset init
|
||||
18
apps/designer/index.html
Normal file
18
apps/designer/index.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="shortcut icon" href="/logo.svg" type="image/x-icon" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta
|
||||
http-equiv="Cache-Control"
|
||||
content="no-cache, no-store, must-revalidate" />
|
||||
<meta http-equiv="Pragma" content="no-cache" />
|
||||
<meta http-equiv="Expires" content="0" />
|
||||
<title>VTJ Web Project Template</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
47
apps/designer/package.json
Normal file
47
apps/designer/package.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "@sy/y-code-designer",
|
||||
"version": "1.0.0",
|
||||
"description": "低代码设计器",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --mode development",
|
||||
"dev:staging": "vite --mode dev-staging",
|
||||
"dev:prod": "vite --mode dev-production",
|
||||
"build": "vite build --mode production",
|
||||
"build:staging": "vite build --mode staging",
|
||||
"build:dev": "vite build --mode development",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "vue-tsc --noEmit --skipLibCheck"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vtj/core": "^0.11.12",
|
||||
"@vtj/designer": "0.11.12",
|
||||
"@vtj/icons": "0.11.12",
|
||||
"@vtj/local": "^0.11.12",
|
||||
"@vtj/materials": "^0.11.12",
|
||||
"@vtj/node": "0.11.2",
|
||||
"@vtj/pro": "^0.11.12",
|
||||
"@vtj/renderer": "^0.11.12",
|
||||
"@vtj/ui": "^0.11.12",
|
||||
"@vtj/utils": "0.11.12",
|
||||
"@vtj/web": "^0.11.12",
|
||||
"axios": "^1.8.1",
|
||||
"element-plus": "^2.9.4",
|
||||
"licia-es": "^1.46.0",
|
||||
"pinia": "^3.0.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"postmate": "^1.5.2",
|
||||
"unplugin-auto-import": "^19.1.1",
|
||||
"vue": "catalog:",
|
||||
"vue-router": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/postmate": "catalog:",
|
||||
"@vtj/cli": "^0.11.2",
|
||||
"vite": "catalog:",
|
||||
"vite-plugin-mkcert": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
},
|
||||
"packageManager": "pnpm@10.6.2"
|
||||
}
|
||||
BIN
apps/designer/public/favicon.ico
Normal file
BIN
apps/designer/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
apps/designer/public/logo.png
Normal file
BIN
apps/designer/public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
1
apps/designer/public/logo.svg
Normal file
1
apps/designer/public/logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1711803009570" class="icon" viewBox="0 0 1280 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1500" width="320" height="256" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M557.85 1023l-122-35.4c-12.8-3.6-20-17-16.4-29.8L692.45 17.4c3.6-12.8 17-20 29.8-16.4l122 35.4c12.8 3.6 20 17 16.4 29.8L587.65 1006.6c-3.8 12.8-17 20.2-29.8 16.4z m-228-224.4l87-92.8c9.2-9.8 8.6-25.4-1.6-34.4L234.05 512l181.2-159.4c10.2-9 11-24.6 1.6-34.4l-87-92.8c-9-9.6-24.2-10.2-34-1L7.65 494.4c-10.2 9.4-10.2 25.6 0 35l288.2 270.2c9.8 9.2 25 8.8 34-1z m654.4 1.2l288.2-270.2c10.2-9.4 10.2-25.6 0-35L984.25 224.2c-9.6-9-24.8-8.6-34 1L863.25 318c-9.2 9.8-8.6 25.4 1.6 34.4L1046.05 512l-181.2 159.4c-10.2 9-11 24.6-1.6 34.4l87 92.8c9 9.8 24.2 10.2 34 1.2z" fill="#0157fe" p-id="1501"></path></svg>
|
||||
|
After Width: | Height: | Size: 931 B |
8
apps/designer/scripts/clean.mjs
Normal file
8
apps/designer/scripts/clean.mjs
Normal file
@ -0,0 +1,8 @@
|
||||
import { rm } from 'node:fs/promises';
|
||||
|
||||
console.log('开始清理...');
|
||||
await rm('node_modules', { recursive: true, force: true });
|
||||
await rm('dist', { recursive: true, force: true });
|
||||
await rm('package-lock.json', { recursive: true, force: true });
|
||||
await rm('pnpm-lock.yaml', { recursive: true, force: true });
|
||||
console.log('开始完成!');
|
||||
12
apps/designer/src/App.vue
Normal file
12
apps/designer/src/App.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<script lang="ts" setup>
|
||||
import { ElConfigProvider } from 'element-plus';
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElConfigProvider :locale="zhCn">
|
||||
<Suspense>
|
||||
<router-view />
|
||||
</Suspense>
|
||||
</ElConfigProvider>
|
||||
</template>
|
||||
BIN
apps/designer/src/assets/logo.png
Normal file
BIN
apps/designer/src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
1
apps/designer/src/assets/logo.svg
Normal file
1
apps/designer/src/assets/logo.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1711803009570" class="icon" viewBox="0 0 1280 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1500" width="320" height="256" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M557.85 1023l-122-35.4c-12.8-3.6-20-17-16.4-29.8L692.45 17.4c3.6-12.8 17-20 29.8-16.4l122 35.4c12.8 3.6 20 17 16.4 29.8L587.65 1006.6c-3.8 12.8-17 20.2-29.8 16.4z m-228-224.4l87-92.8c9.2-9.8 8.6-25.4-1.6-34.4L234.05 512l181.2-159.4c10.2-9 11-24.6 1.6-34.4l-87-92.8c-9-9.6-24.2-10.2-34-1L7.65 494.4c-10.2 9.4-10.2 25.6 0 35l288.2 270.2c9.8 9.2 25 8.8 34-1z m654.4 1.2l288.2-270.2c10.2-9.4 10.2-25.6 0-35L984.25 224.2c-9.6-9-24.8-8.6-34 1L863.25 318c-9.2 9.8-8.6 25.4 1.6 34.4L1046.05 512l-181.2 159.4c-10.2 9-11 24.6-1.6 34.4l87 92.8c9 9.8 24.2 10.2 34 1.2z" fill="#0157fe" p-id="1501"></path></svg>
|
||||
|
After Width: | Height: | Size: 931 B |
88
apps/designer/src/auto-imports.d.ts
vendored
Normal file
88
apps/designer/src/auto-imports.d.ts
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const createPinia: typeof import('pinia')['createPinia']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const defineStore: typeof import('pinia')['defineStore']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getActivePinia: typeof import('pinia')['getActivePinia']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const mapActions: typeof import('pinia')['mapActions']
|
||||
const mapGetters: typeof import('pinia')['mapGetters']
|
||||
const mapState: typeof import('pinia')['mapState']
|
||||
const mapStores: typeof import('pinia')['mapStores']
|
||||
const mapWritableState: typeof import('pinia')['mapWritableState']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const setActivePinia: typeof import('pinia')['setActivePinia']
|
||||
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const storeToRefs: typeof import('pinia')['storeToRefs']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useId: typeof import('vue')['useId']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useModel: typeof import('vue')['useModel']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const useTemplateRef: typeof import('vue')['useTemplateRef']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
1
apps/designer/src/constants/env.ts
Normal file
1
apps/designer/src/constants/env.ts
Normal file
@ -0,0 +1 @@
|
||||
export const currentEnv = import.meta.env;
|
||||
1
apps/designer/src/constants/index.ts
Normal file
1
apps/designer/src/constants/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './env';
|
||||
1
apps/designer/src/contants.ts
Normal file
1
apps/designer/src/contants.ts
Normal file
@ -0,0 +1 @@
|
||||
export const ACCESS_STORAGE_KEY = 'RRO_IDE_ACCESS_STORAGE__';
|
||||
30
apps/designer/src/env.d.ts
vendored
Normal file
30
apps/designer/src/env.d.ts
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// / <reference types="vite/client" />
|
||||
|
||||
declare module '*.vue' {
|
||||
import type { DefineComponent } from 'vue';
|
||||
|
||||
const component: DefineComponent<object, object, any>;
|
||||
export default component;
|
||||
}
|
||||
|
||||
declare namespace _NodeJS {
|
||||
interface ProcessEnv {
|
||||
[key: string]: any;
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace global {
|
||||
interface Window {}
|
||||
}
|
||||
|
||||
declare module 'vue' {
|
||||
interface ComponentCustomProperties {
|
||||
$uploader: any;
|
||||
// cspell:disable-next-line
|
||||
$reqeust: any;
|
||||
$apis: any;
|
||||
$libs: any;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
21
apps/designer/src/io/api.ts
Normal file
21
apps/designer/src/io/api.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import instance from './instance';
|
||||
|
||||
export const getApiList = async () => {
|
||||
const response = await instance.get('/api/v1/api');
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const createApi = async (data: any) => {
|
||||
const response = await instance.post('/api/v1/api', data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const updateApi = async (id: string, data: any) => {
|
||||
const response = await instance.put(`/api/v1/api/${id}`, data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const deleteApi = async (id: string) => {
|
||||
const response = await instance.delete(`/api/v1/api/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
21
apps/designer/src/io/application.ts
Normal file
21
apps/designer/src/io/application.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import instance from './instance';
|
||||
|
||||
export const getApplicationList = async () => {
|
||||
const response = await instance.get('/api/v1/applications');
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const createApplication = async (data: any) => {
|
||||
const response = await instance.post('/api/v1/applications', data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const updateApplication = async (id: string, data: any) => {
|
||||
const response = await instance.put(`/api/v1/applications/${id}`, data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const deleteApplication = async (id: string) => {
|
||||
const response = await instance.delete(`/api/v1/applications/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
21
apps/designer/src/io/block.ts
Normal file
21
apps/designer/src/io/block.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import instance from './instance';
|
||||
|
||||
export const getBlockList = async () => {
|
||||
const response = await instance.get('/api/v1/blocks');
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const createBlock = async (data: any) => {
|
||||
const response = await instance.post('/api/v1/blocks', data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const updateBlock = async (id: string, data: any) => {
|
||||
const response = await instance.put(`/api/v1/blocks/${id}`, data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const deleteBlock = async (id: string) => {
|
||||
const response = await instance.delete(`/api/v1/blocks/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
89
apps/designer/src/io/file.ts
Normal file
89
apps/designer/src/io/file.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import type { BlockSchema } from '@vtj/core';
|
||||
|
||||
import instance from './instance';
|
||||
|
||||
export type LowCodeFileSchema = {
|
||||
active: boolean;
|
||||
dsl: BlockSchema;
|
||||
file_id?: string;
|
||||
file_path?: string;
|
||||
project_id: number;
|
||||
publish: boolean;
|
||||
published_dsl: BlockSchema;
|
||||
};
|
||||
|
||||
function transformFile(file: LowCodeFileSchema): LowCodeFileSchema {
|
||||
return {
|
||||
project_id: file.project_id,
|
||||
publish: file.publish,
|
||||
active: file.active,
|
||||
// @ts-ignore
|
||||
dsl: JSON.stringify(file.dsl),
|
||||
file_path: file.file_path,
|
||||
file_id: file.file_id
|
||||
};
|
||||
}
|
||||
|
||||
export const getFileList = async () => {
|
||||
const response = await instance.get('/api/v1/files');
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getFile = async (id: string) => {
|
||||
const response = await instance.get(`/api/v1/files/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const createFile = async (data: LowCodeFileSchema) => {
|
||||
const response = await instance.post('/api/v1/files', transformFile(data));
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const updateFile = async (id: string, data: LowCodeFileSchema) => {
|
||||
const response = await instance.put(
|
||||
`/api/v1/files/${id}`,
|
||||
transformFile(data)
|
||||
);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
type PublishResponse = {
|
||||
code: string;
|
||||
data: object;
|
||||
id?: string;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export const deleteFile = async (id: string) => {
|
||||
const response = await instance.delete(`/api/v1/files/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* 发布指定项目的所有文件
|
||||
* @param {number} projectId - 需要发布的项目ID
|
||||
* @returns {Promise<any>} 包含发布操作结果的Promise对象
|
||||
* @example
|
||||
* // 发布项目ID为123的所有文件
|
||||
* await publishAllFile(123)
|
||||
*/
|
||||
export const publishAllFile = async (
|
||||
projectId: number
|
||||
): Promise<PublishResponse> => {
|
||||
const response = await instance.post('/api/v1/files/publish', {
|
||||
project_id: projectId
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* 发布单个文件
|
||||
* @param {string} fileId - 需要发布的文件ID
|
||||
* @returns {Promise<any>} 包含发布操作结果的Promise对象
|
||||
*/
|
||||
export const publishFile = async (fileId: string): Promise<PublishResponse> => {
|
||||
const response = await instance.post('/api/v1/files/publish-file', {
|
||||
file_id: fileId
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
77
apps/designer/src/io/history.ts
Normal file
77
apps/designer/src/io/history.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import type { HistorySchema } from '@vtj/core';
|
||||
|
||||
import instance from './instance';
|
||||
|
||||
export type LowCodeHistorySchema = {
|
||||
dsl?: HistorySchema;
|
||||
file_id: string;
|
||||
history_id: string;
|
||||
id?: string;
|
||||
project_id: number;
|
||||
};
|
||||
|
||||
function transformHistoryData(data: LowCodeHistorySchema) {
|
||||
return {
|
||||
...data,
|
||||
dsl: JSON.stringify(data.dsl || {})
|
||||
};
|
||||
}
|
||||
|
||||
export type HistoriesResponse = {
|
||||
code: number;
|
||||
data: {
|
||||
list: Array<{
|
||||
created_at: string;
|
||||
dsl: Record<string, any>;
|
||||
file_id: string;
|
||||
history_id: string;
|
||||
id: number;
|
||||
project_id: number;
|
||||
updated_at: string;
|
||||
}>;
|
||||
total: number;
|
||||
};
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type GetHistoriesParams = {
|
||||
file_id: string;
|
||||
page?: number;
|
||||
per_page?: number;
|
||||
project_id: number;
|
||||
};
|
||||
|
||||
export const getHistories = async (params: GetHistoriesParams) => {
|
||||
const response = await instance.get<HistoriesResponse>('/api/v1/histories', {
|
||||
params: {
|
||||
project_id: params.project_id,
|
||||
file_id: params.file_id,
|
||||
...(params.page && { page: params.page }),
|
||||
...(params.per_page && { per_page: params.per_page })
|
||||
}
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getHistory = async (id: string) => {
|
||||
const response = await instance.get(`/api/v1/histories/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const createHistory = async (data: LowCodeHistorySchema) => {
|
||||
const response = await instance.post(
|
||||
'/api/v1/histories',
|
||||
transformHistoryData(data)
|
||||
);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const updateHistory = async (id: string, data: any) => {
|
||||
const response = await instance.put(`/api/v1/histories/${id}`, data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const deleteHistory = async (id: string) => {
|
||||
const response = await instance.delete(`/api/v1/histories/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
7
apps/designer/src/io/index.ts
Normal file
7
apps/designer/src/io/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export * from './api';
|
||||
export * from './application';
|
||||
export * from './block';
|
||||
export * from './file';
|
||||
export * from './history';
|
||||
export * from './materials';
|
||||
export * from './project';
|
||||
31
apps/designer/src/io/instance.ts
Normal file
31
apps/designer/src/io/instance.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const apiBase = import.meta.env.VITE_BASE_API_URL;
|
||||
|
||||
// 创建独立实例
|
||||
const instance = axios.create({
|
||||
baseURL: apiBase // 基础URL直接放在实例配置中
|
||||
});
|
||||
|
||||
// 请求拦截器改为使用实例
|
||||
instance.interceptors.request.use(
|
||||
(config) => {
|
||||
// 可在此处添加统一请求头等配置
|
||||
config.headers.Authorization = `Bearer ${localStorage.getItem('y-code-access-token')}`;
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
instance.interceptors.response.use(
|
||||
(response) => {
|
||||
return response.data;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
// 导出实例
|
||||
export default instance;
|
||||
112
apps/designer/src/io/materials.ts
Normal file
112
apps/designer/src/io/materials.ts
Normal file
@ -0,0 +1,112 @@
|
||||
import type { MaterialDescription } from '@vtj/core';
|
||||
|
||||
import instance from './instance';
|
||||
|
||||
type MaterialData = {
|
||||
created_at?: string;
|
||||
// 从原interface合并的字段
|
||||
id?: number;
|
||||
name?: string;
|
||||
project_id: number;
|
||||
updated_at?: string;
|
||||
value: Record<string, MaterialDescription>;
|
||||
};
|
||||
|
||||
// 定义响应类型
|
||||
interface MaterialResponse {
|
||||
code: number;
|
||||
data: MaterialData | MaterialData[];
|
||||
message: string;
|
||||
}
|
||||
|
||||
/** 创建物料请求参数 */
|
||||
interface CreateMaterialRequest {
|
||||
project_id: number;
|
||||
value: string;
|
||||
}
|
||||
|
||||
/** 创建物料响应类型 */
|
||||
interface CreateMaterialResponse {
|
||||
code: number;
|
||||
data: { id: string };
|
||||
message: string;
|
||||
}
|
||||
|
||||
/** 删除物料响应类型 */
|
||||
interface DeleteMaterialResponse {
|
||||
code: number;
|
||||
data: { id: string };
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取物料列表
|
||||
* @param params 查询参数
|
||||
* @returns 物料列表
|
||||
*/
|
||||
export const getMaterialsList = async (
|
||||
params?: Record<string, any>
|
||||
): Promise<MaterialResponse> => {
|
||||
const response = await instance.get('/api/v1/materials', { params });
|
||||
return response.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据ID获取单个物料
|
||||
* @param id 物料ID
|
||||
* @returns 物料详情
|
||||
*/
|
||||
export const getMaterials = async (id: number): Promise<MaterialResponse> => {
|
||||
const response = await instance.get(`/api/v1/materials/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
function transformMaterialData(data: MaterialData) {
|
||||
return {
|
||||
...data,
|
||||
value: JSON.stringify(data.value)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新物料
|
||||
* @param data 物料数据(注意 value 需要是 JSON 字符串)
|
||||
* @example
|
||||
* postMaterials({ project_id: 1, value: '{"Authorization": "Bearer token"}' })
|
||||
*/
|
||||
export const postMaterials = async (
|
||||
data: MaterialData
|
||||
): Promise<CreateMaterialResponse> => {
|
||||
const response = await instance.post(
|
||||
'/api/v1/materials',
|
||||
transformMaterialData(data)
|
||||
);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新物料
|
||||
* @param data 物料数据
|
||||
* @returns 更新操作结果
|
||||
*/
|
||||
export const updateMaterials = async (data: MaterialData): Promise<any> => {
|
||||
const response = await instance.put(
|
||||
'/api/v1/materials',
|
||||
transformMaterialData(data)
|
||||
);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除指定物料
|
||||
* @param project_id 要删除的物料所属项目ID
|
||||
* @returns 删除操作结果
|
||||
* @example
|
||||
* deleteMaterial('123').then(() => console.log('删除成功'))
|
||||
*/
|
||||
export const deleteMaterials = async (
|
||||
project_id: number
|
||||
): Promise<DeleteMaterialResponse> => {
|
||||
const response = await instance.delete(`/api/v1/materials/${project_id}`);
|
||||
return response.data;
|
||||
};
|
||||
28
apps/designer/src/io/project.ts
Normal file
28
apps/designer/src/io/project.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import instance from './instance';
|
||||
|
||||
export const getProjectList = async (data?: Record<string, any>) => {
|
||||
const response = await instance.get('/api/v1/projects', {
|
||||
params: data
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getProject = async (id: string) => {
|
||||
const response = await instance.get(`/api/v1/projects/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const createProject = async (data: any) => {
|
||||
const response = await instance.post('/api/v1/projects', data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const updateProject = async (id: string, data: any) => {
|
||||
const response = await instance.put(`/api/v1/projects/${id}`, data);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const deleteProject = async (id: string) => {
|
||||
const response = await instance.delete(`/api/v1/projects/${id}`);
|
||||
return response.data;
|
||||
};
|
||||
23
apps/designer/src/main.ts
Normal file
23
apps/designer/src/main.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { createApp } from 'vue';
|
||||
|
||||
import { createPersistedState } from 'pinia-plugin-persistedstate';
|
||||
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
import { pinia } from './store';
|
||||
|
||||
import './style/index.scss';
|
||||
|
||||
// 添加持久化插件
|
||||
pinia.use(
|
||||
createPersistedState({
|
||||
auto: true, // 自动持久化所有 store
|
||||
storage: localStorage
|
||||
})
|
||||
);
|
||||
const app = createApp(App);
|
||||
// 关闭警告
|
||||
app.config.warnHandler = () => null;
|
||||
app.use(router);
|
||||
app.use(pinia);
|
||||
app.mount('#app');
|
||||
31
apps/designer/src/router.ts
Normal file
31
apps/designer/src/router.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: () => import('@/views/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/preview/:id',
|
||||
name: 'preview',
|
||||
component: () => import('@/views/preview.vue')
|
||||
},
|
||||
{
|
||||
path: '/unauthorized',
|
||||
name: 'Unauthorized',
|
||||
component: () => import('@/views/unauthorized.vue')
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'NotFound',
|
||||
component: () => import('@/views/not-found.vue')
|
||||
}
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes
|
||||
});
|
||||
|
||||
export default router;
|
||||
241
apps/designer/src/service/index.ts
Normal file
241
apps/designer/src/service/index.ts
Normal file
@ -0,0 +1,241 @@
|
||||
// @ts-nocheck 忽略所有类型检查
|
||||
|
||||
import type {
|
||||
BlockFile,
|
||||
BlockSchema,
|
||||
ExtensionConfig,
|
||||
HistoryItem,
|
||||
HistorySchema,
|
||||
MaterialDescription,
|
||||
NodeFromPlugin,
|
||||
ProjectSchema as OriginalProjectSchema,
|
||||
PageFile
|
||||
} from '@vtj/core';
|
||||
|
||||
import {
|
||||
createFile,
|
||||
createHistory as createLowCodeHistory,
|
||||
deleteFile as deleteLowCodeFile,
|
||||
deleteHistory as deleteLowCodeHistory,
|
||||
getFile as getLowCodeFile,
|
||||
getHistories as getLowCodeHistories,
|
||||
getHistory as getLowCodeHistory,
|
||||
getMaterials as getLowCodeMaterials,
|
||||
getProject,
|
||||
postMaterials as postLowCodeMaterials,
|
||||
publishAllFile as publishLowCodeAllFile,
|
||||
publishFile as publishLowCodeFile,
|
||||
updateFile as updateLowCodeFile,
|
||||
updateMaterials as updateLowCodeMaterials,
|
||||
updateProject
|
||||
} from '@/io';
|
||||
// @ts-nocheck
|
||||
import { HistoryModel, ProjectModel } from '@vtj/core';
|
||||
import { BaseService } from '@vtj/renderer';
|
||||
import { mapToObject, Storage } from '@vtj/utils';
|
||||
import { isEmpty } from 'licia-es';
|
||||
|
||||
const storage = new Storage({
|
||||
type: 'local',
|
||||
expired: 0
|
||||
});
|
||||
|
||||
const stringifyFields = new Set([
|
||||
'apis',
|
||||
'blocks',
|
||||
'config',
|
||||
'dependencies',
|
||||
'meta',
|
||||
'pages'
|
||||
]);
|
||||
|
||||
// 扩展原始类型
|
||||
type ProjectSchema = Omit<OriginalProjectSchema, 'projectId'> & {
|
||||
projectId: number | string;
|
||||
};
|
||||
|
||||
let initProject: ProjectSchema;
|
||||
|
||||
export class LowCodeService extends BaseService {
|
||||
public api = (_type: string, _data: any): Promise<any> => {
|
||||
// console.log('api', type, data);
|
||||
return Promise.resolve(true);
|
||||
};
|
||||
|
||||
public getExtension(): Promise<ExtensionConfig | undefined> {
|
||||
const extension = storage.get('extension');
|
||||
// console.log('ExtensionConfig', extension);
|
||||
return Promise.resolve(extension as ExtensionConfig | undefined);
|
||||
}
|
||||
|
||||
public async getFile(id: string): Promise<BlockSchema> {
|
||||
return getLowCodeFile(id).then((lowCodeFile) => {
|
||||
return lowCodeFile.dsl
|
||||
? Promise.resolve(lowCodeFile.dsl as BlockSchema)
|
||||
: Promise.reject(new Error('文件不存在'));
|
||||
});
|
||||
}
|
||||
public async getHistory(fileId: string): Promise<HistorySchema> {
|
||||
const histories = await getLowCodeHistories({
|
||||
project_id: initProject.id,
|
||||
file_id: fileId,
|
||||
per_page: 50
|
||||
});
|
||||
const formatDsl = {
|
||||
id: histories.list[0].file_id,
|
||||
items: histories.list.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
id: item.history_id,
|
||||
label: item.created_at
|
||||
};
|
||||
})
|
||||
};
|
||||
const history = new HistoryModel(formatDsl);
|
||||
return history.toDsl();
|
||||
}
|
||||
|
||||
public async getHistoryItem(fId: string, id: string): Promise<HistoryItem> {
|
||||
const history = await getLowCodeHistory(id);
|
||||
return history;
|
||||
}
|
||||
|
||||
public getPluginMaterial(
|
||||
_from: NodeFromPlugin
|
||||
): Promise<MaterialDescription | null> {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
public async init(project: ProjectSchema): Promise<ProjectSchema> {
|
||||
initProject = project;
|
||||
const remoteProject = await getProject(initProject.id);
|
||||
const arrayFields = ['pages', 'blocks', 'apis', 'meta', 'dependencies'];
|
||||
arrayFields.forEach((field) => {
|
||||
if (isEmpty(remoteProject[field])) {
|
||||
remoteProject[field] = [];
|
||||
}
|
||||
});
|
||||
const model = new ProjectModel(remoteProject);
|
||||
const dsl = model.toDsl();
|
||||
return dsl;
|
||||
}
|
||||
|
||||
public publish(project: ProjectSchema): Promise<boolean> {
|
||||
return publishLowCodeAllFile(Number(project.id)).then((res) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public publishFile(
|
||||
project: ProjectSchema,
|
||||
file: BlockFile | PageFile
|
||||
): Promise<boolean> {
|
||||
return publishLowCodeFile(file.id).then((res) => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public async removeFile(id: string): Promise<boolean> {
|
||||
return deleteLowCodeFile(id).then(() => true);
|
||||
}
|
||||
|
||||
// TODO: 做成数据库存储后没啥用,保留就行
|
||||
public removeHistory(id: string): Promise<boolean> {
|
||||
// console.log('removeHistory', id);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
public async removeHistoryItem(fId: string, ids: string[]): Promise<boolean> {
|
||||
await Promise.all(ids.map((id) => deleteLowCodeHistory(id)));
|
||||
return true;
|
||||
}
|
||||
|
||||
public async saveFile(file: BlockSchema): Promise<boolean> {
|
||||
if (file.id) {
|
||||
const existFile = await getLowCodeFile(file.id);
|
||||
return existFile.file_id
|
||||
? updateLowCodeFile(file.id, {
|
||||
...existFile,
|
||||
dsl: file
|
||||
})
|
||||
.then(() => {
|
||||
return true;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
})
|
||||
: createFile({
|
||||
project_id: Number(initProject.id),
|
||||
publish: false,
|
||||
active: true,
|
||||
dsl: file,
|
||||
file_id: file.id
|
||||
})
|
||||
.then(() => {
|
||||
return true;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public async saveHistory(_history: HistorySchema): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
public async saveHistoryItem(
|
||||
fileId: string,
|
||||
historyItem: HistoryItem
|
||||
): Promise<boolean> {
|
||||
await createLowCodeHistory({
|
||||
project_id: initProject.id,
|
||||
file_id: fileId,
|
||||
history_id: historyItem.id,
|
||||
dsl: historyItem.dsl as HistorySchema
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: 物料存储只有在发布为其他端 (比如 uinapp) 时才有用,当前版本时不需要的,暂且保留
|
||||
public async saveMaterials(
|
||||
project: ProjectSchema,
|
||||
materials: Map<string, MaterialDescription>
|
||||
): Promise<boolean> {
|
||||
const materialData = mapToObject(materials);
|
||||
const existMaterials = await getLowCodeMaterials(project?.id);
|
||||
|
||||
// 根据是否存在物料决定更新或创建
|
||||
existMaterials
|
||||
? await updateLowCodeMaterials({
|
||||
project_id: project?.id,
|
||||
value: materialData
|
||||
})
|
||||
: await postLowCodeMaterials({
|
||||
project_id: project?.id,
|
||||
value: materialData
|
||||
});
|
||||
|
||||
// @ts-ignore - 暂时禁用此行代码,保留以备后续可能需要删除物料的操作
|
||||
// await deleteLowCodeMaterials(project.id);
|
||||
return true;
|
||||
}
|
||||
public async saveProject(project: ProjectSchema): Promise<boolean> {
|
||||
const newProject = {
|
||||
...project,
|
||||
...Object.fromEntries(
|
||||
Object.entries(project)
|
||||
.filter(([key]) => stringifyFields.has(key))
|
||||
.map(([key, value]) => [key, JSON.stringify(value)])
|
||||
)
|
||||
};
|
||||
// 剔除引擎自行添加的 id,避免接口更新冲突报错
|
||||
Reflect.deleteProperty(newProject, 'id');
|
||||
await updateProject(initProject.id, newProject);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected uploader = (_file: File, _projectId: string): Promise<any> => {
|
||||
return Promise.resolve(true);
|
||||
};
|
||||
}
|
||||
60
apps/designer/src/store/index.ts
Normal file
60
apps/designer/src/store/index.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { computed, ref } from 'vue';
|
||||
|
||||
import { createPinia, defineStore } from 'pinia';
|
||||
|
||||
// 创建 pinia 实例
|
||||
export const pinia = createPinia();
|
||||
|
||||
// 用户模块 store
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
// 状态定义
|
||||
const token = ref<string>(localStorage.getItem('y-code-access-token') || '');
|
||||
const userProfile = ref<null>(null);
|
||||
|
||||
// getter 计算属性
|
||||
const isLoggedIn = computed(() => !!token.value);
|
||||
|
||||
// 同步 action
|
||||
const setToken = (newToken: string) => {
|
||||
token.value = newToken;
|
||||
localStorage.setItem('y-code-access-token', newToken);
|
||||
};
|
||||
|
||||
// 清理方法
|
||||
const logout = () => {
|
||||
token.value = '';
|
||||
userProfile.value = null;
|
||||
localStorage.removeItem('y-code-access-token');
|
||||
};
|
||||
|
||||
return {
|
||||
token,
|
||||
userProfile,
|
||||
isLoggedIn,
|
||||
setToken,
|
||||
logout
|
||||
};
|
||||
});
|
||||
|
||||
// 应用配置 store
|
||||
export const useAppStore = defineStore('app', () => {
|
||||
const theme = ref<'dark' | 'light'>('light');
|
||||
const sidebarCollapsed = ref(false);
|
||||
|
||||
// 持久化配置
|
||||
const persist = {
|
||||
paths: ['theme', 'sidebarCollapsed'],
|
||||
storage: localStorage
|
||||
};
|
||||
|
||||
const toggleTheme = () => {
|
||||
theme.value = theme.value === 'light' ? 'dark' : 'light';
|
||||
};
|
||||
|
||||
return {
|
||||
theme,
|
||||
sidebarCollapsed,
|
||||
toggleTheme,
|
||||
persist
|
||||
};
|
||||
});
|
||||
15
apps/designer/src/style/index.scss
Normal file
15
apps/designer/src/style/index.scss
Normal file
@ -0,0 +1,15 @@
|
||||
@use '@vtj/web/src/index';
|
||||
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#vtjLink {
|
||||
display: none;
|
||||
}
|
||||
82
apps/designer/src/views/extension.ts
Normal file
82
apps/designer/src/views/extension.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import type { ExtensionConfig } from '@vtj/core';
|
||||
import type { EngineOptions } from '@vtj/designer';
|
||||
|
||||
import * as Vue from 'vue';
|
||||
|
||||
import * as core from '@vtj/core';
|
||||
import * as designer from '@vtj/designer';
|
||||
import * as VtjIcons from '@vtj/icons';
|
||||
import * as renderer from '@vtj/renderer';
|
||||
import * as VtjUI from '@vtj/ui';
|
||||
import * as VtjUtils from '@vtj/utils';
|
||||
import * as ElementPlus from 'element-plus';
|
||||
|
||||
export type ExtensionOptions = ExtensionConfig;
|
||||
export type ExtensionFactory = (
|
||||
config: ExtensionConfig
|
||||
) => Partial<EngineOptions> | void;
|
||||
|
||||
export interface ExtensionOutput {
|
||||
options: Partial<EngineOptions>;
|
||||
adapters: Record<string, any>;
|
||||
}
|
||||
|
||||
export class Extension {
|
||||
private __adapters__: Record<string, any> = {};
|
||||
private __BASE_PATH__: string = '/';
|
||||
private library: string = '';
|
||||
private params: any[] = [];
|
||||
private urls: string[] = [];
|
||||
constructor(private options: ExtensionOptions) {
|
||||
const __VTJ_PRO__ = {
|
||||
...core,
|
||||
...designer,
|
||||
...renderer
|
||||
};
|
||||
|
||||
(window as any).Vue = Vue;
|
||||
(window as any).__VTJ_PRO__ = __VTJ_PRO__;
|
||||
(window as any).VtjUtils = VtjUtils;
|
||||
(window as any).VtjIcons = VtjIcons;
|
||||
(window as any).VtjUI = VtjUI;
|
||||
(window as any).ElementPlus = ElementPlus;
|
||||
const {
|
||||
urls = [],
|
||||
library,
|
||||
params = [],
|
||||
__BASE_PATH__ = '/',
|
||||
__adapters__ = {}
|
||||
} = options || {};
|
||||
this.urls = urls;
|
||||
this.library = library;
|
||||
this.params = params;
|
||||
this.__BASE_PATH__ = __BASE_PATH__;
|
||||
this.__adapters__ = __adapters__;
|
||||
}
|
||||
async load(): Promise<ExtensionOutput> {
|
||||
let options: Partial<EngineOptions> = {};
|
||||
if (this.library) {
|
||||
const base = this.__BASE_PATH__;
|
||||
const css = this.urls
|
||||
.filter((n) => renderer.isCSSUrl(n))
|
||||
.map((n) => `${base}${n}`);
|
||||
const scripts: string[] = this.urls
|
||||
.filter((n) => renderer.isJSUrl(n))
|
||||
.map((n) => `${base}${n}`);
|
||||
renderer.loadCssUrl(css);
|
||||
if (scripts.length > 0) {
|
||||
const output = await renderer
|
||||
.loadScriptUrl(scripts, this.library)
|
||||
.catch(() => null);
|
||||
options =
|
||||
output && typeof output === 'function'
|
||||
? output.call(output, this.options, this.params)
|
||||
: output || {};
|
||||
}
|
||||
}
|
||||
return {
|
||||
options,
|
||||
adapters: this.__adapters__
|
||||
};
|
||||
}
|
||||
}
|
||||
10
apps/designer/src/views/index.ts
Normal file
10
apps/designer/src/views/index.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import 'element-plus/theme-chalk/dark/css-vars.css';
|
||||
import 'element-plus/theme-chalk/index.css';
|
||||
// import 'vxe-table/es/style.min.css';
|
||||
import '@vtj/ui/dist/style.css';
|
||||
import '@vtj/icons/dist/style.css';
|
||||
|
||||
export * from './extension';
|
||||
export * from '@vtj/core';
|
||||
export * from '@vtj/designer';
|
||||
export * from '@vtj/renderer';
|
||||
87
apps/designer/src/views/index.vue
Normal file
87
apps/designer/src/views/index.vue
Normal file
@ -0,0 +1,87 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { LowCodeService } from '@/service';
|
||||
import { useUserStore } from '@/store';
|
||||
import { Engine, widgetManager } from '@vtj/pro';
|
||||
import { jsonp, request } from '@vtj/utils';
|
||||
import Postmate from 'postmate';
|
||||
|
||||
const container = ref();
|
||||
const service = new LowCodeService();
|
||||
const userStore = useUserStore();
|
||||
|
||||
onMounted(async () => {
|
||||
// 数据模型
|
||||
const model = {
|
||||
name: '',
|
||||
url: '',
|
||||
applicationId: -1,
|
||||
projectId: -1,
|
||||
accessToken: ''
|
||||
};
|
||||
|
||||
const handshake = new Postmate.Model({});
|
||||
await handshake.then((parent) => {
|
||||
parent.emit('sync-context', 'y-code-designer is ready');
|
||||
Object.assign(model, parent.model);
|
||||
console.log('get parent model', model);
|
||||
userStore.setToken(model.accessToken);
|
||||
localStorage.setItem('y-code-access-token', model.accessToken);
|
||||
request.useRequest((req) => {
|
||||
req.headers.set('Authorization', `Bearer ${model.accessToken}`);
|
||||
return req;
|
||||
});
|
||||
sessionStorage.setItem('projectId', model.projectId);
|
||||
const _engine = new Engine({
|
||||
container,
|
||||
service,
|
||||
window,
|
||||
project: {
|
||||
// @ts-ignore
|
||||
id: model.projectId,
|
||||
name: model.name
|
||||
},
|
||||
adapter: {
|
||||
request,
|
||||
jsonp
|
||||
}
|
||||
});
|
||||
widgetManager.set('Previewer', {
|
||||
props: {
|
||||
path: (block: any) => {
|
||||
const pathname = location.pathname;
|
||||
return `${pathname}#/preview/${block.id}`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
widgetManager.set('Templates', {
|
||||
invisible: true
|
||||
});
|
||||
|
||||
widgetManager.set('About', {
|
||||
invisible: true
|
||||
});
|
||||
|
||||
widgetManager.set('History', {
|
||||
// 有 bug,先隐藏
|
||||
// invisible: true
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="designer-container"
|
||||
ref="container"
|
||||
:token="userStore.token"></div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.designer-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
10
apps/designer/src/views/not-found.vue
Normal file
10
apps/designer/src/views/not-found.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { XContainer } from '@vtj/web';
|
||||
import { ElEmpty } from 'element-plus';
|
||||
</script>
|
||||
<template>
|
||||
<XContainer class="not-found" fit justify="center">
|
||||
<ElEmpty description="找不到页面【404】" />
|
||||
</XContainer>
|
||||
</template>
|
||||
<style lang="scss" scoped></style>
|
||||
46
apps/designer/src/views/preview.vue
Normal file
46
apps/designer/src/views/preview.vue
Normal file
@ -0,0 +1,46 @@
|
||||
<script lang="ts" setup>
|
||||
import { getCurrentInstance, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import { LowCodeService } from '@/service';
|
||||
import { useUserStore } from '@/store';
|
||||
import { ContextMode, createProvider } from '@vtj/pro';
|
||||
import { jsonp, request } from '@vtj/utils';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const service = new LowCodeService();
|
||||
request.useRequest((req) => {
|
||||
req.headers.set('Authorization', `Bearer ${userStore.token}`);
|
||||
return req;
|
||||
});
|
||||
const { provider, onReady } = createProvider({
|
||||
mode: ContextMode.Runtime,
|
||||
service,
|
||||
project: {
|
||||
// @ts-ignore
|
||||
id: sessionStorage.getItem('projectId')
|
||||
},
|
||||
adapter: {
|
||||
request,
|
||||
jsonp
|
||||
},
|
||||
dependencies: {
|
||||
Vue: () => import('vue'),
|
||||
VueRouter: () => import('vue-router'),
|
||||
ElementPlus: () => import('element-plus')
|
||||
}
|
||||
});
|
||||
const route = useRoute();
|
||||
const renderer = ref();
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
onReady(async () => {
|
||||
instance?.appContext.app.use(provider);
|
||||
renderer.value = await provider.getRenderComponent(
|
||||
route.params.id.toString()
|
||||
);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<component v-if="renderer" :is="renderer" v-bind="$attrs" />
|
||||
</template>
|
||||
10
apps/designer/src/views/unauthorized.vue
Normal file
10
apps/designer/src/views/unauthorized.vue
Normal file
@ -0,0 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
import { XContainer } from '@vtj/ui';
|
||||
import { ElEmpty } from 'element-plus';
|
||||
</script>
|
||||
<template>
|
||||
<XContainer class="unauthorized" fit justify="center">
|
||||
<ElEmpty description="无权限访问该页面" />
|
||||
</XContainer>
|
||||
</template>
|
||||
<style lang="scss" scoped></style>
|
||||
19
apps/designer/tsconfig.json
Normal file
19
apps/designer/tsconfig.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "./node_modules/@vtj/cli/config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"],
|
||||
"$vtj/*": [".vtj/*"]
|
||||
},
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
],
|
||||
"include": ["src"],
|
||||
"exclude": [".vtj"]
|
||||
}
|
||||
10
apps/designer/tsconfig.node.json
Normal file
10
apps/designer/tsconfig.node.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["vite.config.ts", "proxy.config.ts"]
|
||||
}
|
||||
48
apps/designer/vite.config.ts
Normal file
48
apps/designer/vite.config.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { createViteConfig } from '@vtj/cli';
|
||||
import { createDevTools } from '@vtj/local';
|
||||
import AutoImport from 'unplugin-auto-import/vite';
|
||||
import { defineConfig, loadEnv } from 'vite';
|
||||
import mkcert from 'vite-plugin-mkcert';
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
console.log('mode', mode);
|
||||
const env = loadEnv(mode, process.cwd(), ['VITE_']);
|
||||
const isDev = env.VITE_NODE_ENV === 'development';
|
||||
|
||||
const config = createViteConfig({
|
||||
// proxy,
|
||||
plugins: [
|
||||
createDevTools(),
|
||||
isDev && mkcert(),
|
||||
AutoImport({
|
||||
imports: [
|
||||
'vue',
|
||||
'pinia',
|
||||
'vue-router',
|
||||
{
|
||||
from: 'pinia',
|
||||
imports: ['storeToRefs', 'defineStore'],
|
||||
type: true
|
||||
}
|
||||
],
|
||||
dts: 'src/auto-imports.d.ts', // 生成类型声明文件
|
||||
eslintrc: {
|
||||
enabled: true // 生成 eslint 配置
|
||||
}
|
||||
})
|
||||
]
|
||||
});
|
||||
return {
|
||||
...config,
|
||||
server: {
|
||||
cors: true,
|
||||
https: true,
|
||||
port: isDev ? Number(env.VITE_PORT) : undefined,
|
||||
host: true
|
||||
},
|
||||
define: {
|
||||
// 注入环境变量到客户端
|
||||
__APP_ENV__: JSON.stringify(env)
|
||||
}
|
||||
};
|
||||
});
|
||||
45
apps/docs/.vitepress/components/demo-preview.vue
Normal file
45
apps/docs/.vitepress/components/demo-preview.vue
Normal file
@ -0,0 +1,45 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
import PreviewGroup from './preview-group.vue';
|
||||
|
||||
interface Props {
|
||||
files?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), { files: '() => []' });
|
||||
|
||||
const parsedFiles = computed(() => {
|
||||
try {
|
||||
return JSON.parse(decodeURIComponent(props.files ?? ''));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="border-border shadow-float relative rounded-xl border">
|
||||
<div
|
||||
class="not-prose relative w-full overflow-x-auto rounded-t-lg px-4 py-6"
|
||||
>
|
||||
<div class="flex w-full max-w-[700px] px-2">
|
||||
<ClientOnly>
|
||||
<slot v-if="parsedFiles.length > 0"></slot>
|
||||
<div v-else class="text-destructive text-sm">
|
||||
<span class="bg-destructive text-foreground rounded-sm px-1 py-1">
|
||||
ERROR:
|
||||
</span>
|
||||
The preview directory does not exist. Please check the 'dir'
|
||||
parameter.
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</div>
|
||||
<PreviewGroup v-if="parsedFiles.length > 0" :files="parsedFiles">
|
||||
<template v-for="file in parsedFiles" #[file]>
|
||||
<slot :name="file"></slot>
|
||||
</template>
|
||||
</PreviewGroup>
|
||||
</div>
|
||||
</template>
|
||||
1
apps/docs/.vitepress/components/index.ts
Normal file
1
apps/docs/.vitepress/components/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as DemoPreview } from './demo-preview.vue';
|
||||
110
apps/docs/.vitepress/components/preview-group.vue
Normal file
110
apps/docs/.vitepress/components/preview-group.vue
Normal file
@ -0,0 +1,110 @@
|
||||
<script setup lang="ts">
|
||||
import type { SetupContext } from 'vue';
|
||||
|
||||
import { computed, ref, useSlots } from 'vue';
|
||||
|
||||
import { VbenTooltip } from '@vben-core/shadcn-ui';
|
||||
|
||||
import { Code } from 'lucide-vue-next';
|
||||
import {
|
||||
TabsContent,
|
||||
TabsIndicator,
|
||||
TabsList,
|
||||
TabsRoot,
|
||||
TabsTrigger,
|
||||
} from 'radix-vue';
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
files?: string[];
|
||||
}>(),
|
||||
{ files: () => [] },
|
||||
);
|
||||
|
||||
const open = ref(false);
|
||||
|
||||
const slots: SetupContext['slots'] = useSlots();
|
||||
|
||||
const tabs = computed(() => {
|
||||
return props.files.map((file) => {
|
||||
return {
|
||||
component: slots[file],
|
||||
label: file,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const currentTab = ref('index.vue');
|
||||
|
||||
const toggleOpen = () => {
|
||||
open.value = !open.value;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TabsRoot
|
||||
v-model="currentTab"
|
||||
class="bg-background-deep border-border overflow-hidden rounded-b-xl border-t"
|
||||
@update:model-value="open = true"
|
||||
>
|
||||
<div class="border-border bg-background flex border-b-2 pr-2">
|
||||
<div class="flex w-full items-center justify-between text-[13px]">
|
||||
<TabsList class="relative flex">
|
||||
<template v-if="open">
|
||||
<TabsIndicator
|
||||
class="absolute bottom-0 left-0 h-[2px] w-[--radix-tabs-indicator-size] translate-x-[--radix-tabs-indicator-position] rounded-full transition-[width,transform] duration-300"
|
||||
>
|
||||
<div class="size-full bg-[var(--vp-c-indigo-1)]"></div>
|
||||
</TabsIndicator>
|
||||
<TabsTrigger
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:value="tab.label"
|
||||
class="border-box text-foreground px-4 py-3 data-[state=active]:text-[var(--vp-c-indigo-1)]"
|
||||
tabindex="-1"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</TabsTrigger>
|
||||
</template>
|
||||
</TabsList>
|
||||
|
||||
<div
|
||||
:class="{
|
||||
'py-2': !open,
|
||||
}"
|
||||
class="flex items-center"
|
||||
>
|
||||
<VbenTooltip side="top">
|
||||
<template #trigger>
|
||||
<Code
|
||||
class="hover:bg-accent size-7 cursor-pointer rounded-full p-1.5"
|
||||
@click="toggleOpen"
|
||||
/>
|
||||
</template>
|
||||
{{ open ? 'Collapse code' : 'Expand code' }}
|
||||
</VbenTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:class="`${open ? 'h-[unset] max-h-[80vh]' : 'h-0'}`"
|
||||
class="block overflow-y-scroll bg-[var(--vp-code-block-bg)] transition-all duration-300"
|
||||
>
|
||||
<TabsContent
|
||||
v-for="tab in tabs"
|
||||
:key="tab.label"
|
||||
:value="tab.label"
|
||||
as-child
|
||||
class="rounded-xl"
|
||||
>
|
||||
<div class="text-foreground relative rounded-xl">
|
||||
<component :is="tab.component" class="border-0" />
|
||||
</div>
|
||||
</TabsContent>
|
||||
</div>
|
||||
</TabsRoot>
|
||||
</template>
|
||||
231
apps/docs/.vitepress/config/en.mts
Normal file
231
apps/docs/.vitepress/config/en.mts
Normal file
@ -0,0 +1,231 @@
|
||||
import type { DefaultTheme } from 'vitepress';
|
||||
|
||||
import { defineConfig } from 'vitepress';
|
||||
|
||||
import { version } from '../../../../package.json';
|
||||
|
||||
export const en = defineConfig({
|
||||
description: 'y-code-platform & Enterprise level management system framework',
|
||||
lang: 'en-US',
|
||||
themeConfig: {
|
||||
darkModeSwitchLabel: 'Theme',
|
||||
darkModeSwitchTitle: 'Switch to Dark Mode',
|
||||
docFooter: {
|
||||
next: 'Next Page',
|
||||
prev: 'Previous Page',
|
||||
},
|
||||
editLink: {
|
||||
pattern:
|
||||
'https://github.com/vbenjs/vue-vben-admin/edit/main/docs/src/:path',
|
||||
text: 'Edit this page on GitHub',
|
||||
},
|
||||
footer: {
|
||||
copyright: `Copyright © 2020-${new Date().getFullYear()} Vben`,
|
||||
message: 'Released under the MIT License.',
|
||||
},
|
||||
langMenuLabel: 'Language',
|
||||
lastUpdated: {
|
||||
formatOptions: {
|
||||
dateStyle: 'short',
|
||||
timeStyle: 'medium',
|
||||
},
|
||||
text: 'Last updated on',
|
||||
},
|
||||
lightModeSwitchTitle: 'Switch to Light Mode',
|
||||
nav: nav(),
|
||||
outline: {
|
||||
label: 'Navigate',
|
||||
},
|
||||
returnToTopLabel: 'Back to top',
|
||||
sidebar: {
|
||||
'/en/commercial/': {
|
||||
base: '/en/commercial/',
|
||||
items: sidebarCommercial(),
|
||||
},
|
||||
'/en/guide/': { base: '/en/guide/', items: sidebarGuide() },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function sidebarGuide(): DefaultTheme.SidebarItem[] {
|
||||
return [
|
||||
{
|
||||
collapsed: false,
|
||||
text: 'Introduction',
|
||||
items: [
|
||||
{
|
||||
link: 'introduction/vben',
|
||||
text: 'About y-code-platform',
|
||||
},
|
||||
{
|
||||
link: 'introduction/why',
|
||||
text: 'Why Choose Us?',
|
||||
},
|
||||
{ link: 'introduction/quick-start', text: 'Quick Start' },
|
||||
{ link: 'introduction/thin', text: 'Lite Version' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Basics',
|
||||
items: [
|
||||
{ link: 'essentials/concept', text: 'Basic Concepts' },
|
||||
{ link: 'essentials/development', text: 'Local Development' },
|
||||
{ link: 'essentials/route', text: 'Routing and Menu' },
|
||||
{ link: 'essentials/settings', text: 'Configuration' },
|
||||
{ link: 'essentials/icons', text: 'Icons' },
|
||||
{ link: 'essentials/styles', text: 'Styles' },
|
||||
{ link: 'essentials/external-module', text: 'External Modules' },
|
||||
{ link: 'essentials/build', text: 'Build and Deployment' },
|
||||
{ link: 'essentials/server', text: 'Server Interaction and Data Mock' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Advanced',
|
||||
items: [
|
||||
{ link: 'in-depth/login', text: 'Login' },
|
||||
{ link: 'in-depth/theme', text: 'Theme' },
|
||||
{ link: 'in-depth/access', text: 'Access Control' },
|
||||
{ link: 'in-depth/locale', text: 'Internationalization' },
|
||||
{ link: 'in-depth/features', text: 'Common Features' },
|
||||
{ link: 'in-depth/check-updates', text: 'Check Updates' },
|
||||
{ link: 'in-depth/loading', text: 'Global Loading' },
|
||||
{ link: 'in-depth/ui-framework', text: 'UI Framework Switching' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Engineering',
|
||||
items: [
|
||||
{ link: 'project/standard', text: 'Standards' },
|
||||
{ link: 'project/cli', text: 'CLI' },
|
||||
{ link: 'project/dir', text: 'Directory Explanation' },
|
||||
{ link: 'project/test', text: 'Unit Testing' },
|
||||
{ link: 'project/tailwindcss', text: 'Tailwind CSS' },
|
||||
{ link: 'project/changeset', text: 'Changeset' },
|
||||
{ link: 'project/vite', text: 'Vite Config' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Others',
|
||||
items: [
|
||||
{ link: 'other/project-update', text: 'Project Update' },
|
||||
{ link: 'other/remove-code', text: 'Remove Code' },
|
||||
{ link: 'other/faq', text: 'FAQ' },
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function sidebarCommercial(): DefaultTheme.SidebarItem[] {
|
||||
return [
|
||||
{
|
||||
link: 'community',
|
||||
text: 'Community',
|
||||
},
|
||||
{
|
||||
link: 'technical-support',
|
||||
text: 'Technical-support',
|
||||
},
|
||||
{
|
||||
link: 'customized',
|
||||
text: 'Customized',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function nav(): DefaultTheme.NavItem[] {
|
||||
return [
|
||||
{
|
||||
activeMatch: '^/en/(guide|components)/',
|
||||
text: 'Doc',
|
||||
items: [
|
||||
{
|
||||
activeMatch: '^/en/guide/',
|
||||
link: '/en/guide/introduction/vben',
|
||||
text: 'Guide',
|
||||
},
|
||||
// {
|
||||
// activeMatch: '^/en/components/',
|
||||
// link: '/en/components/introduction',
|
||||
// text: 'Components',
|
||||
// },
|
||||
{
|
||||
text: 'Historical Versions',
|
||||
items: [
|
||||
{
|
||||
link: 'https://doc.vvbin.cn',
|
||||
text: '2.x Version Documentation',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Demo',
|
||||
items: [
|
||||
{
|
||||
text: 'y-code-platform',
|
||||
items: [
|
||||
{
|
||||
link: 'https://y-code.shiyue.com',
|
||||
text: 'Demo Version',
|
||||
},
|
||||
{
|
||||
link: 'https://ant.vben.pro',
|
||||
text: 'Ant Design Vue Version',
|
||||
},
|
||||
{
|
||||
link: 'https://naive.vben.pro',
|
||||
text: 'Naive Version',
|
||||
},
|
||||
{
|
||||
link: 'https://ele.vben.pro',
|
||||
text: 'Element Plus Version',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Others',
|
||||
items: [
|
||||
{
|
||||
link: 'https://vben.vvbin.cn',
|
||||
text: 'y-code-platform 2.x',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: version,
|
||||
items: [
|
||||
{
|
||||
link: 'https://github.com/vbenjs/vue-vben-admin/releases',
|
||||
text: 'Changelog',
|
||||
},
|
||||
{
|
||||
link: 'https://github.com/orgs/vbenjs/projects/5',
|
||||
text: 'Roadmap',
|
||||
},
|
||||
{
|
||||
link: 'https://github.com/vbenjs/vue-vben-admin/blob/main/.github/contributing.md',
|
||||
text: 'Contribution',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
link: '/commercial/technical-support',
|
||||
text: '🦄 Tech Support',
|
||||
},
|
||||
{
|
||||
link: '/sponsor/personal',
|
||||
text: '✨ Sponsor',
|
||||
},
|
||||
{
|
||||
link: '/commercial/community',
|
||||
text: '👨👦👦 Community',
|
||||
},
|
||||
// {
|
||||
// link: '/friend-links/',
|
||||
// text: '🤝 Friend Links',
|
||||
// },
|
||||
];
|
||||
}
|
||||
24
apps/docs/.vitepress/config/index.mts
Normal file
24
apps/docs/.vitepress/config/index.mts
Normal file
@ -0,0 +1,24 @@
|
||||
import { withPwa } from '@vite-pwa/vitepress';
|
||||
import { defineConfigWithTheme } from 'vitepress';
|
||||
|
||||
import { shared } from './shared.mts';
|
||||
import { zh } from './zh.mts';
|
||||
|
||||
export default withPwa(
|
||||
defineConfigWithTheme({
|
||||
...shared,
|
||||
locales: {
|
||||
// en: {
|
||||
// label: 'English',
|
||||
// lang: 'en',
|
||||
// link: '/en/',
|
||||
// ...en,
|
||||
// },
|
||||
root: {
|
||||
label: '简体中文',
|
||||
lang: 'zh-CN',
|
||||
...zh,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
143
apps/docs/.vitepress/config/plugins/demo-preview.ts
Normal file
143
apps/docs/.vitepress/config/plugins/demo-preview.ts
Normal file
@ -0,0 +1,143 @@
|
||||
import type { MarkdownEnv, MarkdownRenderer } from 'vitepress';
|
||||
|
||||
import crypto from 'node:crypto';
|
||||
import { readdirSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
export const rawPathRegexp =
|
||||
// eslint-disable-next-line regexp/no-super-linear-backtracking, regexp/strict
|
||||
/^(.+?(?:\.([\da-z]+))?)(#[\w-]+)?(?: ?{(\d+(?:[,-]\d+)*)? ?(\S+)?})? ?(?:\[(.+)])?$/;
|
||||
|
||||
function rawPathToToken(rawPath: string) {
|
||||
const [
|
||||
filepath = '',
|
||||
extension = '',
|
||||
region = '',
|
||||
lines = '',
|
||||
lang = '',
|
||||
rawTitle = '',
|
||||
] = (rawPathRegexp.exec(rawPath) || []).slice(1);
|
||||
|
||||
const title = rawTitle || filepath.split('/').pop() || '';
|
||||
|
||||
return { extension, filepath, lang, lines, region, title };
|
||||
}
|
||||
|
||||
export const demoPreviewPlugin = (md: MarkdownRenderer) => {
|
||||
md.core.ruler.after('inline', 'demo-preview', (state) => {
|
||||
const insertComponentImport = (importString: string) => {
|
||||
const index = state.tokens.findIndex(
|
||||
(i) => i.type === 'html_block' && i.content.match(/<script setup>/g),
|
||||
);
|
||||
if (index === -1) {
|
||||
const importComponent = new state.Token('html_block', '', 0);
|
||||
importComponent.content = `<script setup>\n${importString}\n</script>\n`;
|
||||
state.tokens.splice(0, 0, importComponent);
|
||||
} else {
|
||||
if (state.tokens[index]) {
|
||||
const content = state.tokens[index].content;
|
||||
state.tokens[index].content = content.replace(
|
||||
'</script>',
|
||||
`${importString}\n</script>`,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
// Define the regular expression to match the desired pattern
|
||||
const regex = /<DemoPreview[^>]*\sdir="([^"]*)"/g;
|
||||
// Iterate through the Markdown content and replace the pattern
|
||||
state.src = state.src.replaceAll(regex, (_match, dir) => {
|
||||
const componentDir = join(process.cwd(), 'src', dir).replaceAll(
|
||||
'\\',
|
||||
'/',
|
||||
);
|
||||
|
||||
let childFiles: string[] = [];
|
||||
let dirExists = true;
|
||||
|
||||
try {
|
||||
childFiles =
|
||||
readdirSync(componentDir, {
|
||||
encoding: 'utf8',
|
||||
recursive: false,
|
||||
withFileTypes: false,
|
||||
}) || [];
|
||||
} catch {
|
||||
dirExists = false;
|
||||
}
|
||||
|
||||
if (!dirExists) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const uniqueWord = generateContentHash(componentDir);
|
||||
|
||||
const ComponentName = `DemoComponent_${uniqueWord}`;
|
||||
insertComponentImport(
|
||||
`import ${ComponentName} from '${componentDir}/index.vue'`,
|
||||
);
|
||||
const { path: _path } = state.env as MarkdownEnv;
|
||||
|
||||
const index = state.tokens.findIndex((i) => i.content.match(regex));
|
||||
|
||||
if (!state.tokens[index]) {
|
||||
return '';
|
||||
}
|
||||
const firstString = 'index.vue';
|
||||
childFiles = childFiles.sort((a, b) => {
|
||||
if (a === firstString) return -1;
|
||||
if (b === firstString) return 1;
|
||||
return a.localeCompare(b, 'en', { sensitivity: 'base' });
|
||||
});
|
||||
state.tokens[index].content =
|
||||
`<DemoPreview files="${encodeURIComponent(JSON.stringify(childFiles))}" ><${ComponentName}/>
|
||||
`;
|
||||
|
||||
const _dummyToken = new state.Token('', '', 0);
|
||||
const tokenArray: Array<typeof _dummyToken> = [];
|
||||
childFiles.forEach((filename) => {
|
||||
// const slotName = filename.replace(extname(filename), '');
|
||||
|
||||
const templateStart = new state.Token('html_inline', '', 0);
|
||||
templateStart.content = `<template #${filename}>`;
|
||||
tokenArray.push(templateStart);
|
||||
|
||||
const resolvedPath = join(componentDir, filename);
|
||||
|
||||
const { extension, filepath, lang, lines, title } =
|
||||
rawPathToToken(resolvedPath);
|
||||
// Add code tokens for each line
|
||||
const token = new state.Token('fence', 'code', 0);
|
||||
token.info = `${lang || extension}${lines ? `{${lines}}` : ''}${
|
||||
title ? `[${title}]` : ''
|
||||
}`;
|
||||
|
||||
token.content = `<<< ${filepath}`;
|
||||
(token as any).src = [resolvedPath];
|
||||
tokenArray.push(token);
|
||||
|
||||
const templateEnd = new state.Token('html_inline', '', 0);
|
||||
templateEnd.content = '</template>';
|
||||
tokenArray.push(templateEnd);
|
||||
});
|
||||
const endTag = new state.Token('html_inline', '', 0);
|
||||
endTag.content = '</DemoPreview>';
|
||||
tokenArray.push(endTag);
|
||||
|
||||
state.tokens.splice(index + 1, 0, ...tokenArray);
|
||||
|
||||
// console.log(
|
||||
// state.md.renderer.render(state.tokens, state?.options ?? [], state.env),
|
||||
// );
|
||||
return '';
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function generateContentHash(input: string, length: number = 10): string {
|
||||
// 使用 SHA-256 生成哈希值
|
||||
const hash = crypto.createHash('sha256').update(input).digest('hex');
|
||||
|
||||
// 将哈希值转换为 Base36 编码,并取指定长度的字符作为结果
|
||||
return Number.parseInt(hash, 16).toString(36).slice(0, length);
|
||||
}
|
||||
164
apps/docs/.vitepress/config/shared.mts
Normal file
164
apps/docs/.vitepress/config/shared.mts
Normal file
@ -0,0 +1,164 @@
|
||||
import type { PwaOptions } from '@vite-pwa/vitepress';
|
||||
import type { HeadConfig } from 'vitepress';
|
||||
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
import {
|
||||
viteArchiverPlugin,
|
||||
viteVxeTableImportsPlugin,
|
||||
} from '@vben/vite-config';
|
||||
|
||||
import {
|
||||
GitChangelog,
|
||||
GitChangelogMarkdownSection,
|
||||
} from '@nolebase/vitepress-plugin-git-changelog/vite';
|
||||
import tailwind from 'tailwindcss';
|
||||
import { defineConfig, postcssIsolateStyles } from 'vitepress';
|
||||
import {
|
||||
groupIconMdPlugin,
|
||||
groupIconVitePlugin,
|
||||
} from 'vitepress-plugin-group-icons';
|
||||
|
||||
import { demoPreviewPlugin } from './plugins/demo-preview';
|
||||
import { search as zhSearch } from './zh.mts';
|
||||
|
||||
export const shared = defineConfig({
|
||||
appearance: 'dark',
|
||||
head: head(),
|
||||
markdown: {
|
||||
preConfig(md) {
|
||||
md.use(demoPreviewPlugin);
|
||||
md.use(groupIconMdPlugin);
|
||||
},
|
||||
},
|
||||
pwa: pwa(),
|
||||
srcDir: 'src',
|
||||
themeConfig: {
|
||||
i18nRouting: true,
|
||||
logo: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp',
|
||||
search: {
|
||||
options: {
|
||||
locales: {
|
||||
...zhSearch,
|
||||
},
|
||||
},
|
||||
provider: 'local',
|
||||
},
|
||||
siteTitle: '悦码',
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://ptdata-gitlab.shiyue.com/sy3570' },
|
||||
],
|
||||
},
|
||||
title: '悦码',
|
||||
vite: {
|
||||
build: {
|
||||
chunkSizeWarningLimit: Infinity,
|
||||
minify: 'terser',
|
||||
},
|
||||
css: {
|
||||
postcss: {
|
||||
plugins: [
|
||||
tailwind(),
|
||||
postcssIsolateStyles({ includeFiles: [/vp-doc\.css/] }),
|
||||
],
|
||||
},
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
api: 'modern',
|
||||
},
|
||||
},
|
||||
},
|
||||
json: {
|
||||
stringify: true,
|
||||
},
|
||||
plugins: [
|
||||
GitChangelog({
|
||||
mapAuthors: [
|
||||
{
|
||||
mapByNameAliases: ['王雪峰'],
|
||||
name: 'wangxuefeng',
|
||||
username: 'wangxuefeng',
|
||||
},
|
||||
],
|
||||
repoURL: () => 'https://ptdata-gitlab.shiyue.com/workbench/y-code',
|
||||
}),
|
||||
GitChangelogMarkdownSection(),
|
||||
viteArchiverPlugin({ outputDir: '.vitepress' }),
|
||||
groupIconVitePlugin(),
|
||||
await viteVxeTableImportsPlugin(),
|
||||
],
|
||||
server: {
|
||||
fs: {
|
||||
allow: ['../..'],
|
||||
},
|
||||
host: true,
|
||||
port: 6173,
|
||||
},
|
||||
|
||||
ssr: {
|
||||
external: ['@vue/repl'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function head(): HeadConfig[] {
|
||||
return [
|
||||
['meta', { content: 'wangxuefeng', name: 'author' }],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
content: 'vben, vitejs, vite, shacdn-ui, vue',
|
||||
name: 'keywords',
|
||||
},
|
||||
],
|
||||
['link', { href: '/favicon.ico', rel: 'icon', type: 'image/svg+xml' }],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
content:
|
||||
'width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no',
|
||||
name: 'viewport',
|
||||
},
|
||||
],
|
||||
['meta', { content: 'vben admin docs', name: 'keywords' }],
|
||||
['link', { href: '/favicon.ico', rel: 'icon' }],
|
||||
// [
|
||||
// 'script',
|
||||
// {
|
||||
// src: 'https://cdn.tailwindcss.com',
|
||||
// },
|
||||
// ],
|
||||
];
|
||||
}
|
||||
|
||||
function pwa(): PwaOptions {
|
||||
return {
|
||||
includeManifestIcons: false,
|
||||
manifest: {
|
||||
description:
|
||||
'y-code-platform is a low-code management platform based on Vue 3 & vtj.pro ',
|
||||
icons: [
|
||||
{
|
||||
sizes: '192x192',
|
||||
src: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/pwa-icon-192.png',
|
||||
type: 'image/png',
|
||||
},
|
||||
{
|
||||
sizes: '512x512',
|
||||
src: 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/pwa-icon-512.png',
|
||||
type: 'image/png',
|
||||
},
|
||||
],
|
||||
id: '/',
|
||||
name: 'y-code-platform Doc',
|
||||
short_name: 'y-code-platform_doc',
|
||||
theme_color: '#ffffff',
|
||||
},
|
||||
outDir: resolve(process.cwd(), '.vitepress/dist'),
|
||||
registerType: 'autoUpdate',
|
||||
workbox: {
|
||||
globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'],
|
||||
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
|
||||
},
|
||||
};
|
||||
}
|
||||
300
apps/docs/.vitepress/config/zh.mts
Normal file
300
apps/docs/.vitepress/config/zh.mts
Normal file
@ -0,0 +1,300 @@
|
||||
import type { DefaultTheme } from 'vitepress';
|
||||
|
||||
import { defineConfig } from 'vitepress';
|
||||
|
||||
import { version } from '../../../../package.json';
|
||||
|
||||
export const zh = defineConfig({
|
||||
description: '悦码 & 低代码管理系统',
|
||||
lang: 'zh-Hans',
|
||||
themeConfig: {
|
||||
darkModeSwitchLabel: '主题',
|
||||
darkModeSwitchTitle: '切换到深色模式',
|
||||
docFooter: {
|
||||
next: '下一页',
|
||||
prev: '上一页',
|
||||
},
|
||||
// editLink: {
|
||||
// pattern:
|
||||
// 'https://github.com/vbenjs/vue-vben-admin/edit/main/docs/src/:path',
|
||||
// text: '在 GitHub 上编辑此页面',
|
||||
// },
|
||||
// footer: {
|
||||
// copyright: `Copyright © 2020-${new Date().getFullYear()} Vben`,
|
||||
// message: '基于 MIT 许可发布.',
|
||||
// },
|
||||
// langMenuLabel: '多语言',
|
||||
lastUpdated: {
|
||||
formatOptions: {
|
||||
dateStyle: 'short',
|
||||
timeStyle: 'medium',
|
||||
},
|
||||
text: '最后更新于',
|
||||
},
|
||||
lightModeSwitchTitle: '切换到浅色模式',
|
||||
nav: nav(),
|
||||
|
||||
outline: {
|
||||
label: '页面导航',
|
||||
},
|
||||
returnToTopLabel: '回到顶部',
|
||||
|
||||
sidebar: {
|
||||
'/commercial/': { base: '/commercial/', items: sidebarCommercial() },
|
||||
'/components/': { base: '/components/', items: sidebarComponents() },
|
||||
'/guide/': { base: '/guide/', items: sidebarGuide() },
|
||||
},
|
||||
sidebarMenuLabel: '菜单',
|
||||
},
|
||||
});
|
||||
|
||||
function sidebarGuide(): DefaultTheme.SidebarItem[] {
|
||||
return [
|
||||
{
|
||||
collapsed: false,
|
||||
text: '简介',
|
||||
items: [
|
||||
{
|
||||
link: 'introduction/platform',
|
||||
text: '关于悦码',
|
||||
},
|
||||
{ link: 'introduction/quick-start', text: '快速开始' },
|
||||
{
|
||||
base: '/',
|
||||
link: 'components/index',
|
||||
text: '组件文档',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '基础',
|
||||
items: [
|
||||
{ link: 'essentials/concept', text: '基础概念' },
|
||||
{ link: 'essentials/icons', text: '图标' },
|
||||
{ link: 'essentials/styles', text: '样式' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '深入',
|
||||
items: [{ link: 'in-depth/materials', text: '物料' }],
|
||||
},
|
||||
{
|
||||
text: '其他',
|
||||
items: [
|
||||
// { link: 'other/project-update', text: '项目更新' },
|
||||
// { link: 'other/remove-code', text: '移除代码' },
|
||||
// { link: 'other/faq', text: '常见问题' },
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function sidebarCommercial(): DefaultTheme.SidebarItem[] {
|
||||
return [
|
||||
{
|
||||
link: 'community',
|
||||
text: '交流群',
|
||||
},
|
||||
{
|
||||
link: 'technical-support',
|
||||
text: '技术支持',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function sidebarComponents(): DefaultTheme.SidebarItem[] {
|
||||
return [
|
||||
{
|
||||
text: '组件',
|
||||
items: [
|
||||
{
|
||||
link: 'introduction',
|
||||
text: '介绍',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
collapsed: false,
|
||||
text: '布局组件',
|
||||
items: [
|
||||
{
|
||||
link: 'layout-ui/page',
|
||||
text: 'Page 页面',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
collapsed: false,
|
||||
text: '通用组件',
|
||||
items: [
|
||||
{
|
||||
link: 'common-ui/vben-api-component',
|
||||
text: 'ApiComponent Api组件包装器',
|
||||
},
|
||||
{
|
||||
link: 'common-ui/vben-modal',
|
||||
text: 'Modal 模态框',
|
||||
},
|
||||
{
|
||||
link: 'common-ui/vben-drawer',
|
||||
text: 'Drawer 抽屉',
|
||||
},
|
||||
{
|
||||
link: 'common-ui/vben-form',
|
||||
text: 'Form 表单',
|
||||
},
|
||||
{
|
||||
link: 'common-ui/vben-vxe-table',
|
||||
text: 'Vxe Table 表格',
|
||||
},
|
||||
{
|
||||
link: 'common-ui/vben-count-to-animator',
|
||||
text: 'CountToAnimator 数字动画',
|
||||
},
|
||||
{
|
||||
link: 'common-ui/vben-ellipsis-text',
|
||||
text: 'EllipsisText 省略文本',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function nav(): DefaultTheme.NavItem[] {
|
||||
return [
|
||||
{
|
||||
activeMatch: '^/(guide|components)/',
|
||||
text: '文档',
|
||||
items: [
|
||||
{
|
||||
activeMatch: '^/guide/',
|
||||
link: '/guide/introduction/platform',
|
||||
text: '低代码管理平台',
|
||||
},
|
||||
{
|
||||
activeMatch: '^/renderer/',
|
||||
link: '/renderer/index',
|
||||
text: '渲染器',
|
||||
},
|
||||
{
|
||||
activeMatch: '^/designer/',
|
||||
link: '/designer/index',
|
||||
text: '设计器',
|
||||
},
|
||||
{
|
||||
activeMatch: '^/materials/',
|
||||
link: '/materials/index',
|
||||
text: '物料',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '低代码管理平台',
|
||||
items: [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
link: 'https://y-code.shiyue.com',
|
||||
text: '生产版本',
|
||||
},
|
||||
{
|
||||
link: 'https://y-code-pre.shiyue.com',
|
||||
text: '预发布版本',
|
||||
},
|
||||
{
|
||||
link: 'https://y-code.shiyue.com',
|
||||
text: '演示版本',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '其他',
|
||||
items: [
|
||||
{
|
||||
link: 'https://custom-chart.shiyuegame.com/',
|
||||
text: '旧版本-y-code-chart(已废弃,不再更新功能)',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: version,
|
||||
items: [
|
||||
{
|
||||
link: '/guide/introduction/changelog',
|
||||
text: '更新日志',
|
||||
},
|
||||
// {
|
||||
// link: '/renderer/CHANGELOG',
|
||||
// text: '渲染器更新日志',
|
||||
// },
|
||||
// {
|
||||
// link: '/designer/CHANGELOG',
|
||||
// text: '设计器更新日志',
|
||||
// },
|
||||
// {
|
||||
// link: '/platform/CHANGELOG',
|
||||
// text: '悦码平台更新日志',
|
||||
// },
|
||||
{
|
||||
link: 'https://doc.weixin.qq.com/smartsheet/s3_Aa0ASwZ0AOEr2TbPuaMRoCvs1yzjA?scode=AOwAYgeoAAkoT6VFa0Aa0ASwZ0AOE&tab=q979lj&viewId=vpDUFs',
|
||||
text: '更新路线图',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '👨👦👦 问题反馈',
|
||||
items: [
|
||||
{
|
||||
link: 'https://qun.qq.com/qqweb/qunpro/share?_wv=3&_wwv=128&appChannel=share&inviteCode=22ySzj7pKiw&businessType=9&from=246610&biz=ka&mainSourceId=share&subSourceId=others&jumpsource=shorturl#/pc',
|
||||
text: '热心大姐',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export const search: DefaultTheme.AlgoliaSearchOptions['locales'] = {
|
||||
root: {
|
||||
placeholder: '搜索文档',
|
||||
translations: {
|
||||
button: {
|
||||
buttonAriaLabel: '搜索文档',
|
||||
buttonText: '搜索文档',
|
||||
},
|
||||
modal: {
|
||||
errorScreen: {
|
||||
helpText: '你可能需要检查你的网络连接',
|
||||
titleText: '无法获取结果',
|
||||
},
|
||||
footer: {
|
||||
closeText: '关闭',
|
||||
navigateText: '切换',
|
||||
searchByText: '搜索提供者',
|
||||
selectText: '选择',
|
||||
},
|
||||
noResultsScreen: {
|
||||
noResultsText: '无法找到相关结果',
|
||||
reportMissingResultsLinkText: '点击反馈',
|
||||
reportMissingResultsText: '你认为该查询应该有结果?',
|
||||
suggestedQueryText: '你可以尝试查询',
|
||||
},
|
||||
searchBox: {
|
||||
cancelButtonAriaLabel: '取消',
|
||||
cancelButtonText: '取消',
|
||||
resetButtonAriaLabel: '清除查询条件',
|
||||
resetButtonTitle: '清除查询条件',
|
||||
},
|
||||
startScreen: {
|
||||
favoriteSearchesTitle: '收藏',
|
||||
noRecentSearchesText: '没有搜索历史',
|
||||
recentSearchesTitle: '搜索历史',
|
||||
removeFavoriteSearchButtonTitle: '从收藏中移除',
|
||||
removeRecentSearchButtonTitle: '从搜索历史中移除',
|
||||
saveRecentSearchButtonTitle: '保存至搜索历史',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
96
apps/docs/.vitepress/theme/components/site-layout.vue
Normal file
96
apps/docs/.vitepress/theme/components/site-layout.vue
Normal file
@ -0,0 +1,96 @@
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
ref,
|
||||
watch,
|
||||
} from 'vue';
|
||||
|
||||
// import { useAntdDesignTokens } from '@vben/hooks';
|
||||
// import { initPreferences } from '@vben/preferences';
|
||||
import { ConfigProvider, theme } from 'ant-design-vue';
|
||||
import mediumZoom from 'medium-zoom';
|
||||
import { useRoute } from 'vitepress';
|
||||
import DefaultTheme from 'vitepress/theme';
|
||||
|
||||
const { Layout } = DefaultTheme;
|
||||
const route = useRoute();
|
||||
// const { tokens } = useAntdDesignTokens();
|
||||
|
||||
const initZoom = () => {
|
||||
// mediumZoom('[data-zoomable]', { background: 'var(--vp-c-bg)' });
|
||||
mediumZoom('.VPContent img', { background: 'var(--vp-c-bg)' });
|
||||
};
|
||||
|
||||
const isDark = ref(true);
|
||||
|
||||
watch(
|
||||
() => route.path,
|
||||
() => nextTick(() => initZoom()),
|
||||
);
|
||||
|
||||
// initPreferences({
|
||||
// namespace: 'docs',
|
||||
// });
|
||||
|
||||
onMounted(() => {
|
||||
initZoom();
|
||||
});
|
||||
|
||||
// 使用该函数
|
||||
const observer = watchDarkModeChange((dark) => {
|
||||
isDark.value = dark;
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
observer?.disconnect();
|
||||
});
|
||||
|
||||
function watchDarkModeChange(callback: (isDark: boolean) => void) {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const htmlElement = document.documentElement;
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
const isDark = htmlElement.classList.contains('dark');
|
||||
callback(isDark);
|
||||
});
|
||||
|
||||
observer.observe(htmlElement, {
|
||||
attributeFilter: ['class'],
|
||||
attributes: true,
|
||||
});
|
||||
|
||||
const initialIsDark = htmlElement.classList.contains('dark');
|
||||
callback(initialIsDark);
|
||||
|
||||
return observer;
|
||||
}
|
||||
|
||||
const tokenTheme = computed(() => {
|
||||
const algorithm = isDark.value
|
||||
? [theme.darkAlgorithm]
|
||||
: [theme.defaultAlgorithm];
|
||||
|
||||
return {
|
||||
algorithm,
|
||||
// token: tokens,
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ConfigProvider :theme="tokenTheme">
|
||||
<Layout />
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.medium-zoom-overlay,
|
||||
.medium-zoom-image--opened {
|
||||
z-index: 2147483647;
|
||||
}
|
||||
</style>
|
||||
29
apps/docs/.vitepress/theme/components/vben-contributors.vue
Normal file
29
apps/docs/.vitepress/theme/components/vben-contributors.vue
Normal file
@ -0,0 +1,29 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div class="vp-doc vben-contributors">
|
||||
<p>Contributors</p>
|
||||
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
|
||||
<img
|
||||
alt="Contributors"
|
||||
src="https://opencollective.com/vbenjs/contributors.svg?button=false"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.vben-contributors {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 60px;
|
||||
|
||||
p {
|
||||
margin-bottom: 50px;
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
29
apps/docs/.vitepress/theme/index.ts
Normal file
29
apps/docs/.vitepress/theme/index.ts
Normal file
@ -0,0 +1,29 @@
|
||||
// https://vitepress.dev/guide/custom-theme
|
||||
import type { EnhanceAppContext, Theme } from 'vitepress';
|
||||
|
||||
import { NolebaseGitChangelogPlugin } from '@nolebase/vitepress-plugin-git-changelog/client';
|
||||
import DefaultTheme from 'vitepress/theme';
|
||||
|
||||
import { DemoPreview } from '../components';
|
||||
import SiteLayout from './components/site-layout.vue';
|
||||
import VbenContributors from './components/vben-contributors.vue';
|
||||
import { initHmPlugin } from './plugins/hm';
|
||||
|
||||
import './styles';
|
||||
|
||||
import 'virtual:group-icons.css';
|
||||
import '@nolebase/vitepress-plugin-git-changelog/client/style.css';
|
||||
|
||||
export default {
|
||||
async enhanceApp(ctx: EnhanceAppContext) {
|
||||
const { app } = ctx;
|
||||
app.component('VbenContributors', VbenContributors);
|
||||
app.component('DemoPreview', DemoPreview);
|
||||
app.use(NolebaseGitChangelogPlugin);
|
||||
|
||||
// 百度统计
|
||||
initHmPlugin();
|
||||
},
|
||||
extends: DefaultTheme,
|
||||
Layout: SiteLayout,
|
||||
} satisfies Theme;
|
||||
28
apps/docs/.vitepress/theme/plugins/hm.ts
Normal file
28
apps/docs/.vitepress/theme/plugins/hm.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { inBrowser } from 'vitepress';
|
||||
|
||||
const SITE_ID = '2e443a834727c065877c01d89921545e';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
_hmt: any;
|
||||
}
|
||||
}
|
||||
|
||||
function registerAnalytics() {
|
||||
window._hmt = window._hmt || [];
|
||||
const script = document.createElement('script');
|
||||
script.innerHTML = `var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?${SITE_ID}";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})()`;
|
||||
document.querySelector('head')?.append(script);
|
||||
}
|
||||
|
||||
export function initHmPlugin() {
|
||||
if (inBrowser && import.meta.env.PROD) {
|
||||
registerAnalytics();
|
||||
}
|
||||
}
|
||||
22
apps/docs/.vitepress/theme/styles/base.css
Normal file
22
apps/docs/.vitepress/theme/styles/base.css
Normal file
@ -0,0 +1,22 @@
|
||||
html.dark {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
.dark .VPContent {
|
||||
/* background-color: #14161a; */
|
||||
}
|
||||
|
||||
.form-valid-error p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* 顶部导航栏选中项样式 */
|
||||
.VPNavBarMenuLink,
|
||||
.VPNavBarMenuGroup {
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
.VPNavBarMenuLink.active,
|
||||
.VPNavBarMenuGroup.active {
|
||||
border-bottom-color: var(--vp-c-brand-1);
|
||||
}
|
||||
4
apps/docs/.vitepress/theme/styles/index.ts
Normal file
4
apps/docs/.vitepress/theme/styles/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import '@vben/styles';
|
||||
|
||||
import './variables.css';
|
||||
import './base.css';
|
||||
127
apps/docs/.vitepress/theme/styles/variables.css
Normal file
127
apps/docs/.vitepress/theme/styles/variables.css
Normal file
@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Customize default theme styling by overriding CSS variables:
|
||||
* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
|
||||
*/
|
||||
|
||||
/**
|
||||
* Colors
|
||||
*
|
||||
* Each colors have exact same color scale system with 3 levels of solid
|
||||
* colors with different brightness, and 1 soft color.
|
||||
*
|
||||
* - `XXX-1`: The most solid color used mainly for colored text. It must
|
||||
* satisfy the contrast ratio against when used on top of `XXX-soft`.
|
||||
*
|
||||
* - `XXX-2`: The color used mainly for hover state of the button.
|
||||
*
|
||||
* - `XXX-3`: The color for solid background, such as bg color of the button.
|
||||
* It must satisfy the contrast ratio with pure white (#ffffff) text on
|
||||
* top of it.
|
||||
*
|
||||
* - `XXX-soft`: The color used for subtle background such as custom container
|
||||
* or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
|
||||
* on top of it.
|
||||
*
|
||||
* The soft color must be semi transparent alpha channel. This is crucial
|
||||
* because it allows adding multiple "soft" colors on top of each other
|
||||
* to create a accent, such as when having inline code block inside
|
||||
* custom containers.
|
||||
*
|
||||
* - `default`: The color used purely for subtle indication without any
|
||||
* special meanings attched to it such as bg color for menu hover state.
|
||||
*
|
||||
* - `brand`: Used for primary brand colors, such as link text, button with
|
||||
* brand theme, etc.
|
||||
*
|
||||
* - `tip`: Used to indicate useful information. The default theme uses the
|
||||
* brand color for this by default.
|
||||
*
|
||||
* - `warning`: Used to indicate warning to the users. Used in custom
|
||||
* container, badges, etc.
|
||||
*
|
||||
* - `danger`: Used to show error, or dangerous message to the users. Used
|
||||
* in custom container, badges, etc.
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
/* --vp-c-indigo-1: #4f69fd; */
|
||||
--vp-c-default-1: var(--vp-c-gray-1);
|
||||
--vp-c-default-2: var(--vp-c-gray-2);
|
||||
--vp-c-default-3: var(--vp-c-gray-3);
|
||||
--vp-c-default-soft: var(--vp-c-gray-soft);
|
||||
--vp-c-brand-1: var(--vp-c-indigo-1);
|
||||
--vp-c-brand-2: var(--vp-c-indigo-2);
|
||||
--vp-c-brand-3: var(--vp-c-indigo-3);
|
||||
--vp-c-brand-soft: var(--vp-c-indigo-soft);
|
||||
--vp-c-tip-1: var(--vp-c-brand-1);
|
||||
--vp-c-tip-2: var(--vp-c-brand-2);
|
||||
--vp-c-tip-3: var(--vp-c-brand-3);
|
||||
--vp-c-tip-soft: var(--vp-c-brand-soft);
|
||||
--vp-c-warning-1: var(--vp-c-yellow-1);
|
||||
--vp-c-warning-2: var(--vp-c-yellow-2);
|
||||
--vp-c-warning-3: var(--vp-c-yellow-3);
|
||||
--vp-c-warning-soft: var(--vp-c-yellow-soft);
|
||||
--vp-c-danger-1: var(--vp-c-red-1);
|
||||
--vp-c-danger-2: var(--vp-c-red-2);
|
||||
--vp-c-danger-3: var(--vp-c-red-3);
|
||||
--vp-c-danger-soft: var(--vp-c-red-soft);
|
||||
|
||||
/**
|
||||
* Component: Button
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
--vp-button-brand-border: transparent;
|
||||
--vp-button-brand-text: var(--vp-c-white);
|
||||
--vp-button-brand-bg: var(--vp-c-brand-3);
|
||||
--vp-button-brand-hover-border: transparent;
|
||||
--vp-button-brand-hover-text: var(--vp-c-white);
|
||||
--vp-button-brand-hover-bg: var(--vp-c-brand-2);
|
||||
--vp-button-brand-active-border: transparent;
|
||||
--vp-button-brand-active-text: var(--vp-c-white);
|
||||
--vp-button-brand-active-bg: var(--vp-c-brand-1);
|
||||
|
||||
/**
|
||||
* Component: Home
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: linear-gradient(
|
||||
120deg,
|
||||
var(--vp-c-indigo-1) 30%,
|
||||
#18cefe
|
||||
);
|
||||
--vp-home-hero-image-background-image: linear-gradient(
|
||||
-45deg,
|
||||
#18cefe 50%,
|
||||
#c279ed 50%
|
||||
);
|
||||
--vp-home-hero-image-filter: blur(44px);
|
||||
|
||||
/**
|
||||
* Component: Custom Block
|
||||
* -------------------------------------------------------------------------- */
|
||||
--vp-custom-block-tip-border: transparent;
|
||||
--vp-custom-block-tip-text: var(--vp-c-text-1);
|
||||
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
|
||||
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(56px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(68px);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Algolia
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
.DocSearch {
|
||||
--docsearch-primary-color: var(--vp-c-brand-1) !important;
|
||||
}
|
||||
7
apps/docs/CHANGELOG.md
Normal file
7
apps/docs/CHANGELOG.md
Normal file
@ -0,0 +1,7 @@
|
||||
# @sy/y-code-docs
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- project changeset init
|
||||
41
apps/docs/package.json
Normal file
41
apps/docs/package.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "@sy/y-code-docs",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm sync-changelog && vitepress build && node scripts/after-build.mjs",
|
||||
"build:staging": "pnpm build",
|
||||
"preview": "vitepress preview",
|
||||
"dev": "pnpm sync-changelog && vitepress dev",
|
||||
"dev:staging": "vitepress dev --mode dev-staging",
|
||||
"dev:prod": "vitepress dev --mode dev-production",
|
||||
"docs:preview": "vitepress preview",
|
||||
"sync-changelog": "node scripts/sync-change-log.mjs"
|
||||
},
|
||||
"imports": {
|
||||
"#/*": {
|
||||
"node": "./src/_env/node/*",
|
||||
"default": "./src/_env/*"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@vben-core/shadcn-ui": "workspace:*",
|
||||
"@vben/common-ui": "workspace:*",
|
||||
"@vben/locales": "workspace:*",
|
||||
"@vben/plugins": "workspace:*",
|
||||
"@vben/styles": "workspace:*",
|
||||
"ant-design-vue": "catalog:",
|
||||
"lucide-vue-next": "catalog:",
|
||||
"medium-zoom": "catalog:",
|
||||
"radix-vue": "catalog:",
|
||||
"vitepress-plugin-group-icons": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nolebase/vitepress-plugin-git-changelog": "catalog:",
|
||||
"@vben/vite-config": "workspace:*",
|
||||
"@vite-pwa/vitepress": "catalog:",
|
||||
"vitepress": "catalog:",
|
||||
"vue": "catalog:"
|
||||
}
|
||||
}
|
||||
58
apps/docs/scripts/after-build.mjs
Normal file
58
apps/docs/scripts/after-build.mjs
Normal file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
// 获取当前脚本的目录
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// 源目录和目标目录
|
||||
const sourceDir = path.resolve(__dirname, '../.vitepress/dist');
|
||||
const targetDir = path.resolve(process.cwd(), 'dist');
|
||||
|
||||
// 检查源目录是否存在
|
||||
if (!fs.existsSync(sourceDir)) {
|
||||
console.error(`错误:源目录 "${sourceDir}" 不存在!`);
|
||||
console.error('请确保已经运行了 vitepress build 命令');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 如果目标目录已存在,则先删除
|
||||
if (fs.existsSync(targetDir)) {
|
||||
console.log(`目标目录 "${targetDir}" 已存在,正在删除...`);
|
||||
fs.rmSync(targetDir, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
// 递归复制目录函数
|
||||
function copyDirRecursive(src, dest) {
|
||||
// 创建目标目录
|
||||
fs.mkdirSync(dest, { recursive: true });
|
||||
|
||||
// 读取源目录中的所有文件/目录
|
||||
const entries = fs.readdirSync(src, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const srcPath = path.join(src, entry.name);
|
||||
const destPath = path.join(dest, entry.name);
|
||||
|
||||
// 根据文件类型进行不同处理
|
||||
if (entry.isDirectory()) {
|
||||
// 递归复制子目录
|
||||
copyDirRecursive(srcPath, destPath);
|
||||
} else {
|
||||
// 复制文件
|
||||
fs.copyFileSync(srcPath, destPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// 复制目录
|
||||
copyDirRecursive(sourceDir, targetDir);
|
||||
console.log(`✅ 成功将 ".vitepress/dist" 复制到 "${targetDir}"`);
|
||||
} catch (error) {
|
||||
console.error(`❌ 复制过程中发生错误:${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
61
apps/docs/scripts/sync-change-log.mjs
Normal file
61
apps/docs/scripts/sync-change-log.mjs
Normal file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
// 获取当前脚本的目录
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// 需要处理的应用列表
|
||||
const appsToProcess = ['renderer', 'designer', 'platform'];
|
||||
|
||||
// 复制CHANGELOG.md文件
|
||||
function copyChangelogFile(appName) {
|
||||
const changelogSrcPath = path.resolve(
|
||||
process.cwd(),
|
||||
`../${appName}/CHANGELOG.md`,
|
||||
);
|
||||
const changelogDestDir = path.resolve(__dirname, `../src/${appName}`);
|
||||
const changelogDestPath = path.resolve(changelogDestDir, 'CHANGELOG.md');
|
||||
|
||||
console.log(`正在复制${appName}的CHANGELOG.md文件...`);
|
||||
|
||||
// 检查源文件是否存在
|
||||
if (!fs.existsSync(changelogSrcPath)) {
|
||||
console.warn(
|
||||
`⚠️ 警告:${appName}的CHANGELOG文件 "${changelogSrcPath}" 不存在!`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保目标目录存在
|
||||
if (!fs.existsSync(changelogDestDir)) {
|
||||
console.log(`创建目标目录 "${changelogDestDir}"...`);
|
||||
fs.mkdirSync(changelogDestDir, { recursive: true });
|
||||
}
|
||||
|
||||
// 复制文件
|
||||
try {
|
||||
fs.copyFileSync(changelogSrcPath, changelogDestPath);
|
||||
console.log(
|
||||
`✅ 成功将${appName}的CHANGELOG.md复制到 "${changelogDestPath}"`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`❌ 复制${appName}的CHANGELOG.md时发生错误:${error.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// 复制各个应用的CHANGELOG.md文件
|
||||
for (const app of appsToProcess) {
|
||||
copyChangelogFile(app);
|
||||
}
|
||||
console.log(`✅ 所有CHANGELOG.md文件复制完成`);
|
||||
} catch (error) {
|
||||
console.error(`❌ 复制过程中发生错误:${error.message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
128
apps/docs/src/_env/adapter/component.ts
Normal file
128
apps/docs/src/_env/adapter/component.ts
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用
|
||||
* 可用于 vben-form、vben-modal、vben-drawer 等组件使用,
|
||||
*/
|
||||
|
||||
import type { Component, SetupContext } from 'vue';
|
||||
|
||||
import type { BaseFormComponentType } from '@vben/common-ui';
|
||||
|
||||
import { h } from 'vue';
|
||||
|
||||
import { globalShareState } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import {
|
||||
AutoComplete,
|
||||
Button,
|
||||
Checkbox,
|
||||
CheckboxGroup,
|
||||
DatePicker,
|
||||
Divider,
|
||||
Input,
|
||||
InputNumber,
|
||||
InputPassword,
|
||||
Mentions,
|
||||
notification,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
RangePicker,
|
||||
Rate,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Textarea,
|
||||
TimePicker,
|
||||
TreeSelect,
|
||||
Upload,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
type: 'input' | 'select',
|
||||
) => {
|
||||
return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => {
|
||||
const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`);
|
||||
return h(component, { ...props, ...attrs, placeholder }, slots);
|
||||
};
|
||||
};
|
||||
|
||||
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
|
||||
export type ComponentType =
|
||||
| 'AutoComplete'
|
||||
| 'Checkbox'
|
||||
| 'CheckboxGroup'
|
||||
| 'DatePicker'
|
||||
| 'DefaultButton'
|
||||
| 'Divider'
|
||||
| 'Input'
|
||||
| 'InputNumber'
|
||||
| 'InputPassword'
|
||||
| 'Mentions'
|
||||
| 'PrimaryButton'
|
||||
| 'Radio'
|
||||
| 'RadioGroup'
|
||||
| 'RangePicker'
|
||||
| 'Rate'
|
||||
| 'Select'
|
||||
| 'Space'
|
||||
| 'Switch'
|
||||
| 'Textarea'
|
||||
| 'TimePicker'
|
||||
| 'TreeSelect'
|
||||
| 'Upload'
|
||||
| BaseFormComponentType;
|
||||
|
||||
async function initComponentAdapter() {
|
||||
const components: Partial<Record<ComponentType, Component>> = {
|
||||
// 如果你的组件体积比较大,可以使用异步加载
|
||||
// Button: () =>
|
||||
// import('xxx').then((res) => res.Button),
|
||||
|
||||
AutoComplete,
|
||||
Checkbox,
|
||||
CheckboxGroup,
|
||||
DatePicker,
|
||||
// 自定义默认按钮
|
||||
DefaultButton: (props, { attrs, slots }) => {
|
||||
return h(Button, { ...props, attrs, type: 'default' }, slots);
|
||||
},
|
||||
Divider,
|
||||
Input: withDefaultPlaceholder(Input, 'input'),
|
||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||
// 自定义主要按钮
|
||||
PrimaryButton: (props, { attrs, slots }) => {
|
||||
return h(Button, { ...props, attrs, type: 'primary' }, slots);
|
||||
},
|
||||
Radio,
|
||||
RadioGroup,
|
||||
RangePicker,
|
||||
Rate,
|
||||
Select: withDefaultPlaceholder(Select, 'select'),
|
||||
Space,
|
||||
Switch,
|
||||
Textarea: withDefaultPlaceholder(Textarea, 'input'),
|
||||
TimePicker,
|
||||
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
|
||||
Upload,
|
||||
};
|
||||
|
||||
// 将组件注册到全局共享状态中
|
||||
globalShareState.setComponents(components);
|
||||
|
||||
// 定义全局共享状态中的消息提示
|
||||
globalShareState.defineMessage({
|
||||
// 复制成功消息提示
|
||||
copyPreferencesSuccess: (title, content) => {
|
||||
notification.success({
|
||||
description: content,
|
||||
message: title,
|
||||
placement: 'bottomRight',
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export { initComponentAdapter };
|
||||
47
apps/docs/src/_env/adapter/form.ts
Normal file
47
apps/docs/src/_env/adapter/form.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import type {
|
||||
VbenFormSchema as FormSchema,
|
||||
VbenFormProps,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { initComponentAdapter } from './component';
|
||||
|
||||
initComponentAdapter();
|
||||
setupVbenForm<ComponentType>({
|
||||
config: {
|
||||
baseModelPropName: 'value',
|
||||
// naive-ui组件的空值为null,不能是undefined,否则重置表单时不生效
|
||||
emptyStateValue: null,
|
||||
modelPropNameMap: {
|
||||
Checkbox: 'checked',
|
||||
Radio: 'checked',
|
||||
Switch: 'checked',
|
||||
Upload: 'fileList',
|
||||
},
|
||||
},
|
||||
defineRules: {
|
||||
required: (value, _params, ctx) => {
|
||||
if (value === undefined || value === null || value.length === 0) {
|
||||
return $t('ui.formRules.required', [ctx.label]);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
selectRequired: (value, _params, ctx) => {
|
||||
if (value === undefined || value === null) {
|
||||
return $t('ui.formRules.selectRequired', [ctx.label]);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const useVbenForm = useForm<ComponentType>;
|
||||
|
||||
export { useVbenForm, z };
|
||||
|
||||
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||
export type { VbenFormProps };
|
||||
70
apps/docs/src/_env/adapter/vxe-table.ts
Normal file
70
apps/docs/src/_env/adapter/vxe-table.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { h } from 'vue';
|
||||
|
||||
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||
|
||||
import { Button, Image } from 'ant-design-vue';
|
||||
|
||||
import { useVbenForm } from './form';
|
||||
|
||||
if (!import.meta.env.SSR) {
|
||||
setupVbenVxeTable({
|
||||
configVxeTable: (vxeUI) => {
|
||||
vxeUI.setConfig({
|
||||
grid: {
|
||||
align: 'center',
|
||||
border: false,
|
||||
columnConfig: {
|
||||
resizable: true,
|
||||
},
|
||||
|
||||
formConfig: {
|
||||
// 全局禁用vxe-table的表单配置,使用formOptions
|
||||
enabled: false,
|
||||
},
|
||||
minHeight: 180,
|
||||
proxyConfig: {
|
||||
autoLoad: true,
|
||||
response: {
|
||||
result: 'items',
|
||||
total: 'total',
|
||||
list: 'items',
|
||||
},
|
||||
showActiveMsg: true,
|
||||
showResponseMsg: false,
|
||||
},
|
||||
round: true,
|
||||
showOverflow: true,
|
||||
size: 'small',
|
||||
},
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellImage' },
|
||||
vxeUI.renderer.add('CellImage', {
|
||||
renderTableDefault(_renderOpts, params) {
|
||||
const { column, row } = params;
|
||||
return h(Image, { src: row[column.field] });
|
||||
},
|
||||
});
|
||||
|
||||
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||
vxeUI.renderer.add('CellLink', {
|
||||
renderTableDefault(renderOpts) {
|
||||
const { props } = renderOpts;
|
||||
return h(
|
||||
Button,
|
||||
{ size: 'small', type: 'link' },
|
||||
{ default: () => props?.text },
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
||||
// vxeUI.formats.add
|
||||
},
|
||||
useVbenForm,
|
||||
});
|
||||
}
|
||||
|
||||
export { useVbenVxeGrid };
|
||||
|
||||
export type * from '@vben/plugins/vxe-table';
|
||||
4
apps/docs/src/_env/node/adapter/form.ts
Normal file
4
apps/docs/src/_env/node/adapter/form.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export const useVbenForm = () => {};
|
||||
export const z = {};
|
||||
export type VbenFormSchema = any;
|
||||
export type VbenFormProps = any;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user