Merge branch 'feature/low-code-platform' into release
# Conflicts: # package.json
This commit is contained in:
commit
b2ac996df2
4
.browserslistrc
Normal file
4
.browserslistrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
> 1%
|
||||||
|
last 2 versions
|
||||||
|
not dead
|
||||||
|
not ie 11
|
5
.changeset/README.md
Normal file
5
.changeset/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# 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)
|
18
.changeset/config.json
Normal file
18
.changeset/config.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
|
||||||
|
"changelog": [
|
||||||
|
"@changesets/changelog-github",
|
||||||
|
{ "repo": "vbenjs/vue-vben-admin" }
|
||||||
|
],
|
||||||
|
"commit": false,
|
||||||
|
"fixed": [["@vben-core/*", "@vben/*"]],
|
||||||
|
"snapshot": {
|
||||||
|
"prereleaseTemplate": "{tag}-{datetime}"
|
||||||
|
},
|
||||||
|
"privatePackages": { "version": true, "tag": true },
|
||||||
|
"linked": [],
|
||||||
|
"access": "public",
|
||||||
|
"baseBranch": "main",
|
||||||
|
"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
|
46
.gitignore
vendored
46
.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
|
logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
@ -6,20 +35,17 @@ yarn-debug.log*
|
|||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
pnpm-debug.log*
|
pnpm-debug.log*
|
||||||
lerna-debug.log*
|
lerna-debug.log*
|
||||||
|
vite.config.mts.*
|
||||||
node_modules
|
vite.config.mjs.*
|
||||||
dist
|
vite.config.js.*
|
||||||
dist-ssr
|
vite.config.ts.*
|
||||||
*.local
|
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
.idea
|
||||||
.DS_Store
|
# .vscode
|
||||||
*.suo
|
*.suo
|
||||||
*.ntvs*
|
*.ntvs*
|
||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
localSet.js
|
.history
|
||||||
|
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
|
15
.npmrc
15
.npmrc
@ -1 +1,14 @@
|
|||||||
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
|
||||||
|
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": [
|
"recommendations": [
|
||||||
|
// Vue 3 的语言支持
|
||||||
"Vue.volar",
|
"Vue.volar",
|
||||||
"Vue.vscode-typescript-vue-plugin",
|
// 将 ESLint JavaScript 集成到 VS Code 中。
|
||||||
"dbaeumer.vscode-eslint"
|
"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
|
||||||
|
}
|
9
LICENSE
Normal file
9
LICENSE
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024-present, Vben
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
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)
|
152
README.zh-CN.md
Normal file
152
README.zh-CN.md
Normal file
@ -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.md) | [日本語](./README.ja-JP.md)
|
||||||
|
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
Vue Vben Admin 是 Vue Vben Admin 的升级版本。作为一个免费开源的中后台模板,它采用了最新的 Vue 3、Vite、TypeScript 等主流技术开发,开箱即用,可用于中后台前端开发,也适合学习参考。
|
||||||
|
|
||||||
|
## 升级提示
|
||||||
|
|
||||||
|
该版本为最新版本`5.0`, 与其他版本不兼容,如果你是新项目,建议使用最新版本。如果你想查看旧版本,请使用 [v2 分支](https://github.com/vbenjs/vue-vben-admin/tree/v2)
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
|
||||||
|
- **最新技术栈**:使用 Vue3/vite 等前端前沿技术开发
|
||||||
|
- **TypeScript**: 应用程序级 JavaScript 的语言
|
||||||
|
- **主题**:提供多套主题色彩,可配置自定义主题
|
||||||
|
- **国际化**:内置完善的国际化方案
|
||||||
|
- **权限** 内置完善的动态路由权限生成方案
|
||||||
|
|
||||||
|
## 预览
|
||||||
|
|
||||||
|
- [Vben Admin](https://vben.pro/) - 完整版中文站点
|
||||||
|
|
||||||
|
测试账号: 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>
|
||||||
|
|
||||||
|
### 使用 Gitpod
|
||||||
|
|
||||||
|
在 Gitpod(适用于 GitHub 的免费在线开发环境)中打开项目,并立即开始编码.
|
||||||
|
|
||||||
|
[](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
[文档地址](https://doc.vben.pro/)
|
||||||
|
|
||||||
|
## 安装使用
|
||||||
|
|
||||||
|
- 获取项目代码
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/vbenjs/vue-vben-admin.git
|
||||||
|
```
|
||||||
|
|
||||||
|
- 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd vue-vben-admin
|
||||||
|
|
||||||
|
corepack enable
|
||||||
|
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
- 运行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
- 打包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm build
|
||||||
|
```
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
|
||||||
|
|
||||||
|
## 如何贡献
|
||||||
|
|
||||||
|
非常欢迎你的加入 或者提交一个 Pull Request。
|
||||||
|
|
||||||
|
**Pull Request:**
|
||||||
|
|
||||||
|
1. Fork 代码!
|
||||||
|
2. 创建自己的分支: `git checkout -b feature/xxxx`
|
||||||
|
3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'`
|
||||||
|
4. 推送您的分支: `git push origin feature/xxxx`
|
||||||
|
5. 提交`pull request`
|
||||||
|
|
||||||
|
## 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 |
|
||||||
|
|
||||||
|
## 维护者
|
||||||
|
|
||||||
|
[@Vben](https://github.com/anncwb)
|
||||||
|
|
||||||
|
## Star History
|
||||||
|
|
||||||
|
[](https://star-history.com/#vbenjs/vue-vben-admin&Date)
|
||||||
|
|
||||||
|
## 捐赠
|
||||||
|
|
||||||
|
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</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)
|
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 = ''
|
17
apps/designer/.env.development
Normal file
17
apps/designer/.env.development
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# 只在开发模式中被载入
|
||||||
|
VITE_NODE_ENV = 'development'
|
||||||
|
|
||||||
|
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
|
||||||
|
VITE_BASE_URL = /
|
||||||
|
|
||||||
|
# 前端可见变量(必须以 VITE_ 开头)
|
||||||
|
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-platform.shiyuegame.com/'
|
||||||
|
VITE_DESIGNER_URL = 'https://y-code-designer.shiyuegame.com/'
|
||||||
|
VITE_RENDERER_URL = 'https://y-code-renderer.shiyuegame.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-platform-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
|
||||||
|
}
|
5
apps/designer/.vscode/extensions.json
vendored
Normal file
5
apps/designer/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"vue.volar"
|
||||||
|
]
|
||||||
|
}
|
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>
|
44
apps/designer/package.json
Normal file
44
apps/designer/package.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "@sy/y-code-designer",
|
||||||
|
"version": "1.0.0-1",
|
||||||
|
"description": "低代码编辑器",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"setup": "npm install --unsafe-perm --registry=https://registry.npmmirror.com",
|
||||||
|
"dev": "cross-env vite --mode development",
|
||||||
|
"build": "vite build --mode production",
|
||||||
|
"build:staging": "vite build --mode staging",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"clean": "rimraf node_modules"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vtj/core": "^0.10.10",
|
||||||
|
"@vtj/designer": "0.10.10",
|
||||||
|
"@vtj/icons": "0.10.10",
|
||||||
|
"@vtj/local": "^0.10.10",
|
||||||
|
"@vtj/materials": "^0.10.10",
|
||||||
|
"@vtj/node": "0.10.2",
|
||||||
|
"@vtj/pro": "^0.10.10",
|
||||||
|
"@vtj/renderer": "^0.10.10",
|
||||||
|
"@vtj/ui": "^0.10.10",
|
||||||
|
"@vtj/utils": "0.10.10",
|
||||||
|
"@vtj/web": "^0.10.10",
|
||||||
|
"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": {
|
||||||
|
"@vtj/cli": "^0.10.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 |
7
apps/designer/scripts/clean.mjs
Normal file
7
apps/designer/scripts/clean.mjs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { rm } from '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 |
103
apps/designer/src/auto-imports.d.ts
vendored
Normal file
103
apps/designer/src/auto-imports.d.ts
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* 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');
|
||||||
|
}
|
2
apps/designer/src/constants/env.ts
Normal file
2
apps/designer/src/constants/env.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// @ts-ignore
|
||||||
|
export const currentEnv = __APP_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__';
|
29
apps/designer/src/env.d.ts
vendored
Normal file
29
apps/designer/src/env.d.ts
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// / <reference types="vite/client" />
|
||||||
|
|
||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue';
|
||||||
|
|
||||||
|
const component: DefineComponent<{}, {}, any>;
|
||||||
|
export default component;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare namespace NodeJS {
|
||||||
|
interface ProcessEnv {
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare namespace global {
|
||||||
|
interface Window {}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'vue' {
|
||||||
|
interface ComponentCustomProperties {
|
||||||
|
$uploader: any;
|
||||||
|
$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;
|
||||||
|
};
|
91
apps/designer/src/io/file.ts
Normal file
91
apps/designer/src/io/file.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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对象
|
||||||
|
* @example
|
||||||
|
* // 发布文件ID为45tnbgeme的文件
|
||||||
|
* await publishFile('45tnbgeme')
|
||||||
|
*/
|
||||||
|
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';
|
30
apps/designer/src/io/instance.ts
Normal file
30
apps/designer/src/io/instance.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
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) => {
|
||||||
|
// 可在此处添加统一请求头等配置
|
||||||
|
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';
|
||||||
|
|
||||||
|
// 定义响应类型
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MaterialData = {
|
||||||
|
created_at?: string;
|
||||||
|
// 从原interface合并的字段
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
project_id: number;
|
||||||
|
updated_at?: string;
|
||||||
|
value: Record<string, MaterialDescription>;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
22
apps/designer/src/main.ts
Normal file
22
apps/designer/src/main.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
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.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;
|
245
apps/designer/src/service/index.ts
Normal file
245
apps/designer/src/service/index.ts
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
import type {
|
||||||
|
BlockFile,
|
||||||
|
BlockSchema,
|
||||||
|
ExtensionConfig,
|
||||||
|
HistoryItem,
|
||||||
|
HistorySchema,
|
||||||
|
MaterialDescription,
|
||||||
|
NodeFromPlugin,
|
||||||
|
PageFile,
|
||||||
|
ProjectSchema
|
||||||
|
} 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'
|
||||||
|
]);
|
||||||
|
|
||||||
|
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(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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> {
|
||||||
|
console.log('init', project);
|
||||||
|
initProject = project;
|
||||||
|
const remoteProject = await getProject(initProject.id);
|
||||||
|
const arrayFields = ['pages', 'blocks', 'apis', 'meta', 'dependencies'];
|
||||||
|
arrayFields.forEach((field) => {
|
||||||
|
if (isEmpty(remoteProject[field])) {
|
||||||
|
remoteProject[field] = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('remoteProject', remoteProject);
|
||||||
|
const model = new ProjectModel(remoteProject);
|
||||||
|
console.log('model', model || { id: initProject.id });
|
||||||
|
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> {
|
||||||
|
console.log('saveFile', file);
|
||||||
|
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: 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);
|
||||||
|
// storage.save(`materials_${project.id}`, materialData);
|
||||||
|
// console.log('saveMaterials', materialData);
|
||||||
|
// @ts-ignore
|
||||||
|
const existMaterials = await getLowCodeMaterials(project?.id);
|
||||||
|
if (existMaterials) {
|
||||||
|
// 更新物料
|
||||||
|
await updateLowCodeMaterials({
|
||||||
|
project_id: project?.id,
|
||||||
|
value: materialData
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 创建物料
|
||||||
|
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> => {
|
||||||
|
// console.log('uploader', file, projectId);
|
||||||
|
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';
|
75
apps/designer/src/views/index.vue
Normal file
75
apps/designer/src/views/index.vue
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<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);
|
||||||
|
request.useRequest((req) => {
|
||||||
|
req.headers.set('Authorization', `Bearer ${model.accessToken}`);
|
||||||
|
return req;
|
||||||
|
});
|
||||||
|
const engine = new Engine({
|
||||||
|
container,
|
||||||
|
service,
|
||||||
|
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
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</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: 4
|
||||||
|
},
|
||||||
|
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>
|
27
apps/designer/tsconfig.json
Normal file
27
apps/designer/tsconfig.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"extends": "./node_modules/@vtj/cli/config/tsconfig.web.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
],
|
||||||
|
"$vtj/*": [
|
||||||
|
".vtj/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
".vtj",
|
||||||
|
],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.node.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
apps/designer/tsconfig.node.json
Normal file
13
apps/designer/tsconfig.node.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"vite.config.ts",
|
||||||
|
"proxy.config.ts"
|
||||||
|
]
|
||||||
|
}
|
52
apps/designer/vite.config.ts
Normal file
52
apps/designer/vite.config.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
const config = createViteConfig({
|
||||||
|
// proxy,
|
||||||
|
plugins: [
|
||||||
|
createDevTools(),
|
||||||
|
mkcert(),
|
||||||
|
AutoImport({
|
||||||
|
imports: [
|
||||||
|
'vue',
|
||||||
|
'pinia',
|
||||||
|
'vue-router',
|
||||||
|
{
|
||||||
|
from: 'pinia',
|
||||||
|
imports: ['storeToRefs', 'defineStore'],
|
||||||
|
type: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dts: 'src/auto-imports.d.ts', // 生成类型声明文件
|
||||||
|
eslintrc: {
|
||||||
|
enabled: true // 生成 eslint 配置
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
export default defineConfig(({ mode }) => {
|
||||||
|
console.log('mode', mode);
|
||||||
|
// 加载环境变量(支持 .env.development/.env.production)
|
||||||
|
const env = loadEnv(mode, process.cwd(), ['VITE_', 'VTJ_', 'SY_', 'Y_CODE_']);
|
||||||
|
return {
|
||||||
|
...config,
|
||||||
|
server: {
|
||||||
|
https: true,
|
||||||
|
port: env.VITE_PORT,
|
||||||
|
host: true
|
||||||
|
},
|
||||||
|
define: {
|
||||||
|
// 注入环境变量到客户端
|
||||||
|
__APP_ENV__: JSON.stringify(env)
|
||||||
|
}
|
||||||
|
// build: {
|
||||||
|
// outDir: path.resolve(process.cwd(), '../../dist/designer'),
|
||||||
|
// emptyOutDir: true // 构建前清空目录
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
});
|
5
apps/platform/.env
Normal file
5
apps/platform/.env
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# 应用标题
|
||||||
|
VITE_APP_TITLE=y-code-platform
|
||||||
|
|
||||||
|
# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
|
||||||
|
VITE_APP_NAMESPACE=y-code-platform
|
7
apps/platform/.env.analyze
Normal file
7
apps/platform/.env.analyze
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# public path
|
||||||
|
VITE_BASE=/
|
||||||
|
|
||||||
|
# Basic interface address SPA
|
||||||
|
VITE_GLOB_API_URL=/api
|
||||||
|
|
||||||
|
VITE_VISUALIZER=true
|
33
apps/platform/.env.development
Normal file
33
apps/platform/.env.development
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# 端口号
|
||||||
|
VITE_PORT=10010
|
||||||
|
|
||||||
|
VITE_BASE=/
|
||||||
|
|
||||||
|
# 接口地址
|
||||||
|
VITE_GLOB_API_URL=/api
|
||||||
|
|
||||||
|
# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
|
||||||
|
VITE_NITRO_MOCK=true
|
||||||
|
|
||||||
|
# 是否打开 devtools,true 为打开,false 为关闭
|
||||||
|
VITE_DEVTOOLS=true
|
||||||
|
|
||||||
|
# 是否注入全局loading
|
||||||
|
VITE_INJECT_APP_LOADING=true
|
||||||
|
|
||||||
|
# 只在开发模式中被载入
|
||||||
|
VITE_NODE_ENV = 'development'
|
||||||
|
|
||||||
|
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
|
||||||
|
VITE_BASE_URL = /
|
||||||
|
|
||||||
|
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/'
|
||||||
|
VITE_V1_URL = 'https://localhost:10013/'
|
33
apps/platform/.env.production
Normal file
33
apps/platform/.env.production
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
VITE_BASE=/
|
||||||
|
|
||||||
|
# 接口地址
|
||||||
|
VITE_GLOB_API_URL=https://mock-napi.vben.pro/api
|
||||||
|
|
||||||
|
# 是否开启压缩,可以设置为 none, brotli, gzip
|
||||||
|
VITE_COMPRESS=none
|
||||||
|
|
||||||
|
# 是否开启 PWA
|
||||||
|
VITE_PWA=false
|
||||||
|
|
||||||
|
# vue-router 的模式
|
||||||
|
VITE_ROUTER_HISTORY=hash
|
||||||
|
|
||||||
|
# 是否注入全局loading
|
||||||
|
VITE_INJECT_APP_LOADING=true
|
||||||
|
|
||||||
|
# 打包后是否生成dist.zip
|
||||||
|
VITE_ARCHIVER=true
|
||||||
|
|
||||||
|
|
||||||
|
# 只在生产模式中被载入
|
||||||
|
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-platform.shiyuegame.com/'
|
||||||
|
VITE_DESIGNER_URL = 'https://y-code-designer.shiyuegame.com/'
|
||||||
|
VITE_RENDERER_URL = 'https://y-code-renderer.shiyuegame.com/'
|
||||||
|
Y_CODE_V1_URL = 'https://custom-chart.shiyuegame.com/'
|
13
apps/platform/.env.staging
Normal file
13
apps/platform/.env.staging
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# 只在预发布模式中被载入
|
||||||
|
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-platform-pre.shiyue.com/'
|
||||||
|
VITE_DESIGNER_URL = 'https://y-code-designer-pre.shiyue.com/'
|
||||||
|
VITE_RENDERER_URL = 'https://y-code-renderer-pre.shiyue.com/'
|
||||||
|
Y_CODE_V1_URL = 'https://custom-chart.shiyue.com/'
|
35
apps/platform/index.html
Normal file
35
apps/platform/index.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
|
<meta name="renderer" content="webkit" />
|
||||||
|
<meta name="description" content="A Modern Back-end Management System" />
|
||||||
|
<meta name="keywords" content="Vben Admin Vue3 Vite" />
|
||||||
|
<meta name="author" content="Vben" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||||
|
/>
|
||||||
|
<!-- 由 vite 注入 VITE_APP_TITLE 变量,在 .env 文件内配置 -->
|
||||||
|
<title><%= VITE_APP_TITLE %></title>
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<script>
|
||||||
|
// 生产环境下注入百度统计
|
||||||
|
if (window._VBEN_ADMIN_PRO_APP_CONF_) {
|
||||||
|
var _hmt = _hmt || [];
|
||||||
|
(function () {
|
||||||
|
var hm = document.createElement('script');
|
||||||
|
hm.src =
|
||||||
|
'https://hm.baidu.com/hm.js?97352b16ed2df8c3860cf5a1a65fb4dd';
|
||||||
|
var s = document.getElementsByTagName('script')[0];
|
||||||
|
s.parentNode.insertBefore(hm, s);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
49
apps/platform/package.json
Normal file
49
apps/platform/package.json
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{
|
||||||
|
"name": "@sy/y-code-platform",
|
||||||
|
"version": "1.0.0-alpha.1",
|
||||||
|
"private": true,
|
||||||
|
"author": {
|
||||||
|
"name": "wangxuefeng",
|
||||||
|
"email": "wangxuefeng@shiyue.com"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "pnpm vite build --mode production",
|
||||||
|
"build:analyze": "pnpm vite build --mode analyze",
|
||||||
|
"dev": "pnpm vite --mode development",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"typecheck": "vue-tsc --noEmit --skipLibCheck"
|
||||||
|
},
|
||||||
|
"imports": {
|
||||||
|
"#/*": "./src/*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sy/unified-login": "1.0.29",
|
||||||
|
"@vben/access": "workspace:*",
|
||||||
|
"@vben/common-ui": "workspace:*",
|
||||||
|
"@vben/constants": "workspace:*",
|
||||||
|
"@vben/hooks": "workspace:*",
|
||||||
|
"@vben/icons": "workspace:*",
|
||||||
|
"@vben/layouts": "workspace:*",
|
||||||
|
"@vben/locales": "workspace:*",
|
||||||
|
"@vben/plugins": "workspace:*",
|
||||||
|
"@vben/preferences": "workspace:*",
|
||||||
|
"@vben/request": "workspace:*",
|
||||||
|
"@vben/stores": "workspace:*",
|
||||||
|
"@vben/styles": "workspace:*",
|
||||||
|
"@vben/types": "workspace:*",
|
||||||
|
"@vben/utils": "workspace:*",
|
||||||
|
"@vueuse/core": "catalog:",
|
||||||
|
"axios": "catalog:",
|
||||||
|
"dayjs": "catalog:",
|
||||||
|
"element-plus": "catalog:",
|
||||||
|
"pinia": "catalog:",
|
||||||
|
"postmate": "1.5.2",
|
||||||
|
"vue": "catalog:",
|
||||||
|
"vue-router": "catalog:"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"unplugin-element-plus": "catalog:",
|
||||||
|
"vite-plugin-mkcert": "catalog:"
|
||||||
|
}
|
||||||
|
}
|
1
apps/platform/postcss.config.mjs
Normal file
1
apps/platform/postcss.config.mjs
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from '@vben/tailwind-config/postcss';
|
BIN
apps/platform/public/favicon.ico
Normal file
BIN
apps/platform/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
255
apps/platform/src/adapter/component/index.ts
Normal file
255
apps/platform/src/adapter/component/index.ts
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
/**
|
||||||
|
* 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用
|
||||||
|
* 可用于 vben-form、vben-modal、vben-drawer 等组件使用,
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Component } from 'vue';
|
||||||
|
|
||||||
|
import type { BaseFormComponentType } from '@vben/common-ui';
|
||||||
|
import type { Recordable } from '@vben/types';
|
||||||
|
|
||||||
|
import { defineComponent, getCurrentInstance, h, ref } from 'vue';
|
||||||
|
|
||||||
|
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
|
||||||
|
import { $t } from '@vben/locales';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ElButton,
|
||||||
|
ElCheckbox,
|
||||||
|
ElCheckboxButton,
|
||||||
|
ElCheckboxGroup,
|
||||||
|
ElDatePicker,
|
||||||
|
ElDivider,
|
||||||
|
ElInput,
|
||||||
|
ElInputNumber,
|
||||||
|
ElNotification,
|
||||||
|
ElRadio,
|
||||||
|
ElRadioButton,
|
||||||
|
ElRadioGroup,
|
||||||
|
ElSelectV2,
|
||||||
|
ElSpace,
|
||||||
|
ElSwitch,
|
||||||
|
ElTimePicker,
|
||||||
|
ElTreeSelect,
|
||||||
|
ElUpload,
|
||||||
|
} from 'element-plus';
|
||||||
|
|
||||||
|
const withDefaultPlaceholder = <T extends Component>(
|
||||||
|
component: T,
|
||||||
|
type: 'input' | 'select',
|
||||||
|
) => {
|
||||||
|
return defineComponent({
|
||||||
|
inheritAttrs: false,
|
||||||
|
name: component.name,
|
||||||
|
setup: (props: any, { attrs, expose, slots }) => {
|
||||||
|
const placeholder =
|
||||||
|
props?.placeholder ||
|
||||||
|
attrs?.placeholder ||
|
||||||
|
$t(`ui.placeholder.${type}`);
|
||||||
|
// 透传组件暴露的方法
|
||||||
|
const innerRef = ref();
|
||||||
|
const publicApi: Recordable<any> = {};
|
||||||
|
expose(publicApi);
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
instance?.proxy?.$nextTick(() => {
|
||||||
|
for (const key in innerRef.value) {
|
||||||
|
if (typeof innerRef.value[key] === 'function') {
|
||||||
|
publicApi[key] = innerRef.value[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return () =>
|
||||||
|
h(component, { ...props, ...attrs, placeholder, ref: innerRef }, slots);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
|
||||||
|
export type ComponentType =
|
||||||
|
| 'ApiSelect'
|
||||||
|
| 'ApiTreeSelect'
|
||||||
|
| 'Checkbox'
|
||||||
|
| 'CheckboxGroup'
|
||||||
|
| 'DatePicker'
|
||||||
|
| 'Divider'
|
||||||
|
| 'IconPicker'
|
||||||
|
| 'Input'
|
||||||
|
| 'InputNumber'
|
||||||
|
| 'RadioGroup'
|
||||||
|
| 'Select'
|
||||||
|
| 'Space'
|
||||||
|
| 'Switch'
|
||||||
|
| 'TimePicker'
|
||||||
|
| 'TreeSelect'
|
||||||
|
| 'Upload'
|
||||||
|
| BaseFormComponentType;
|
||||||
|
|
||||||
|
async function initComponentAdapter() {
|
||||||
|
const components: Partial<Record<ComponentType, Component>> = {
|
||||||
|
// 如果你的组件体积比较大,可以使用异步加载
|
||||||
|
// Button: () =>
|
||||||
|
// import('xxx').then((res) => res.Button),
|
||||||
|
ApiSelect: (props, { attrs, slots }) => {
|
||||||
|
return h(
|
||||||
|
ApiComponent,
|
||||||
|
{
|
||||||
|
placeholder: $t('ui.placeholder.select'),
|
||||||
|
...props,
|
||||||
|
...attrs,
|
||||||
|
component: ElSelectV2,
|
||||||
|
loadingSlot: 'loading',
|
||||||
|
visibleEvent: 'onVisibleChange',
|
||||||
|
},
|
||||||
|
slots,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
ApiTreeSelect: (props, { attrs, slots }) => {
|
||||||
|
return h(
|
||||||
|
ApiComponent,
|
||||||
|
{
|
||||||
|
placeholder: $t('ui.placeholder.select'),
|
||||||
|
...props,
|
||||||
|
...attrs,
|
||||||
|
component: ElTreeSelect,
|
||||||
|
props: { label: 'label', children: 'children' },
|
||||||
|
nodeKey: 'value',
|
||||||
|
loadingSlot: 'loading',
|
||||||
|
optionsPropName: 'data',
|
||||||
|
visibleEvent: 'onVisibleChange',
|
||||||
|
},
|
||||||
|
slots,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Checkbox: ElCheckbox,
|
||||||
|
CheckboxGroup: (props, { attrs, slots }) => {
|
||||||
|
let defaultSlot;
|
||||||
|
if (Reflect.has(slots, 'default')) {
|
||||||
|
defaultSlot = slots.default;
|
||||||
|
} else {
|
||||||
|
const { options, isButton } = attrs;
|
||||||
|
if (Array.isArray(options)) {
|
||||||
|
defaultSlot = () =>
|
||||||
|
options.map((option) =>
|
||||||
|
h(isButton ? ElCheckboxButton : ElCheckbox, option),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h(
|
||||||
|
ElCheckboxGroup,
|
||||||
|
{ ...props, ...attrs },
|
||||||
|
{ ...slots, default: defaultSlot },
|
||||||
|
);
|
||||||
|
},
|
||||||
|
// 自定义默认按钮
|
||||||
|
DefaultButton: (props, { attrs, slots }) => {
|
||||||
|
return h(ElButton, { ...props, attrs, type: 'info' }, slots);
|
||||||
|
},
|
||||||
|
// 自定义主要按钮
|
||||||
|
PrimaryButton: (props, { attrs, slots }) => {
|
||||||
|
return h(ElButton, { ...props, attrs, type: 'primary' }, slots);
|
||||||
|
},
|
||||||
|
Divider: ElDivider,
|
||||||
|
IconPicker: (props, { attrs, slots }) => {
|
||||||
|
return h(
|
||||||
|
IconPicker,
|
||||||
|
{
|
||||||
|
iconSlot: 'append',
|
||||||
|
modelValueProp: 'model-value',
|
||||||
|
inputComponent: ElInput,
|
||||||
|
...props,
|
||||||
|
...attrs,
|
||||||
|
},
|
||||||
|
slots,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Input: withDefaultPlaceholder(ElInput, 'input'),
|
||||||
|
InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
|
||||||
|
RadioGroup: (props, { attrs, slots }) => {
|
||||||
|
let defaultSlot;
|
||||||
|
if (Reflect.has(slots, 'default')) {
|
||||||
|
defaultSlot = slots.default;
|
||||||
|
} else {
|
||||||
|
const { options } = attrs;
|
||||||
|
if (Array.isArray(options)) {
|
||||||
|
defaultSlot = () =>
|
||||||
|
options.map((option) =>
|
||||||
|
h(attrs.isButton ? ElRadioButton : ElRadio, option),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h(
|
||||||
|
ElRadioGroup,
|
||||||
|
{ ...props, ...attrs },
|
||||||
|
{ ...slots, default: defaultSlot },
|
||||||
|
);
|
||||||
|
},
|
||||||
|
Select: (props, { attrs, slots }) => {
|
||||||
|
return h(ElSelectV2, { ...props, attrs }, slots);
|
||||||
|
},
|
||||||
|
Space: ElSpace,
|
||||||
|
Switch: ElSwitch,
|
||||||
|
TimePicker: (props, { attrs, slots }) => {
|
||||||
|
const { name, id, isRange } = props;
|
||||||
|
const extraProps: Recordable<any> = {};
|
||||||
|
if (isRange) {
|
||||||
|
if (name && !Array.isArray(name)) {
|
||||||
|
extraProps.name = [name, `${name}_end`];
|
||||||
|
}
|
||||||
|
if (id && !Array.isArray(id)) {
|
||||||
|
extraProps.id = [id, `${id}_end`];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h(
|
||||||
|
ElTimePicker,
|
||||||
|
{
|
||||||
|
...props,
|
||||||
|
...attrs,
|
||||||
|
...extraProps,
|
||||||
|
},
|
||||||
|
slots,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
DatePicker: (props, { attrs, slots }) => {
|
||||||
|
const { name, id, type } = props;
|
||||||
|
const extraProps: Recordable<any> = {};
|
||||||
|
if (type && type.includes('range')) {
|
||||||
|
if (name && !Array.isArray(name)) {
|
||||||
|
extraProps.name = [name, `${name}_end`];
|
||||||
|
}
|
||||||
|
if (id && !Array.isArray(id)) {
|
||||||
|
extraProps.id = [id, `${id}_end`];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h(
|
||||||
|
ElDatePicker,
|
||||||
|
{
|
||||||
|
...props,
|
||||||
|
...attrs,
|
||||||
|
...extraProps,
|
||||||
|
},
|
||||||
|
slots,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
TreeSelect: withDefaultPlaceholder(ElTreeSelect, 'select'),
|
||||||
|
Upload: ElUpload,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 将组件注册到全局共享状态中
|
||||||
|
globalShareState.setComponents(components);
|
||||||
|
|
||||||
|
// 定义全局共享状态中的消息提示
|
||||||
|
globalShareState.defineMessage({
|
||||||
|
// 复制成功消息提示
|
||||||
|
copyPreferencesSuccess: (title, content) => {
|
||||||
|
ElNotification({
|
||||||
|
title,
|
||||||
|
message: content,
|
||||||
|
position: 'bottom-right',
|
||||||
|
duration: 0,
|
||||||
|
type: 'success',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { initComponentAdapter };
|
39
apps/platform/src/adapter/form.ts
Normal file
39
apps/platform/src/adapter/form.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
setupVbenForm<ComponentType>({
|
||||||
|
config: {
|
||||||
|
modelPropNameMap: {
|
||||||
|
Upload: 'fileList',
|
||||||
|
CheckboxGroup: 'model-value',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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 };
|
68
apps/platform/src/adapter/vxe-table.ts
Normal file
68
apps/platform/src/adapter/vxe-table.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import { h } from 'vue';
|
||||||
|
|
||||||
|
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
|
||||||
|
|
||||||
|
import { ElButton, ElImage } from 'element-plus';
|
||||||
|
|
||||||
|
import { useVbenForm } from './form';
|
||||||
|
|
||||||
|
setupVbenVxeTable({
|
||||||
|
configVxeTable: (vxeUI) => {
|
||||||
|
vxeUI.setConfig({
|
||||||
|
grid: {
|
||||||
|
align: 'center',
|
||||||
|
border: false,
|
||||||
|
columnConfig: {
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
minHeight: 180,
|
||||||
|
formConfig: {
|
||||||
|
// 全局禁用vxe-table的表单配置,使用formOptions
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
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;
|
||||||
|
const src = row[column.field];
|
||||||
|
return h(ElImage, { src, previewSrcList: [src] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格配置项可以用 cellRender: { name: 'CellLink' },
|
||||||
|
vxeUI.renderer.add('CellLink', {
|
||||||
|
renderTableDefault(renderOpts) {
|
||||||
|
const { props } = renderOpts;
|
||||||
|
return h(
|
||||||
|
ElButton,
|
||||||
|
{ size: 'small', link: true },
|
||||||
|
{ default: () => props?.text },
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 这里可以自行扩展 vxe-table 的全局配置,比如自定义格式化
|
||||||
|
// vxeUI.formats.add
|
||||||
|
},
|
||||||
|
useVbenForm,
|
||||||
|
});
|
||||||
|
|
||||||
|
export { useVbenVxeGrid };
|
||||||
|
|
||||||
|
export type * from '@vben/plugins/vxe-table';
|
51
apps/platform/src/api/core/auth.ts
Normal file
51
apps/platform/src/api/core/auth.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { baseRequestClient, requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
export namespace AuthApi {
|
||||||
|
/** 登录接口参数 */
|
||||||
|
export interface LoginParams {
|
||||||
|
password?: string;
|
||||||
|
username?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 登录接口返回值 */
|
||||||
|
export interface LoginResult {
|
||||||
|
accessToken: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RefreshTokenResult {
|
||||||
|
data: string;
|
||||||
|
status: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
*/
|
||||||
|
export async function loginApi(data: AuthApi.LoginParams) {
|
||||||
|
return requestClient.post<AuthApi.LoginResult>('/auth/login', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新accessToken
|
||||||
|
*/
|
||||||
|
export async function refreshTokenApi() {
|
||||||
|
return baseRequestClient.post<AuthApi.RefreshTokenResult>('/auth/refresh', {
|
||||||
|
withCredentials: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出登录
|
||||||
|
*/
|
||||||
|
export async function logoutApi() {
|
||||||
|
return baseRequestClient.post('/auth/logout', {
|
||||||
|
withCredentials: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户权限码
|
||||||
|
*/
|
||||||
|
export async function getAccessCodesApi() {
|
||||||
|
return requestClient.get<string[]>('/auth/codes');
|
||||||
|
}
|
3
apps/platform/src/api/core/index.ts
Normal file
3
apps/platform/src/api/core/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './auth';
|
||||||
|
export * from './menu';
|
||||||
|
export * from './user';
|
10
apps/platform/src/api/core/menu.ts
Normal file
10
apps/platform/src/api/core/menu.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { RouteRecordStringComponent } from '@vben/types';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户所有菜单
|
||||||
|
*/
|
||||||
|
export async function getAllMenusApi() {
|
||||||
|
return requestClient.get<RouteRecordStringComponent[]>('/menu/all');
|
||||||
|
}
|
10
apps/platform/src/api/core/user.ts
Normal file
10
apps/platform/src/api/core/user.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { UserInfo } from '@vben/types';
|
||||||
|
|
||||||
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户信息
|
||||||
|
*/
|
||||||
|
export async function getUserInfoApi() {
|
||||||
|
return requestClient.get<UserInfo>('/user/info');
|
||||||
|
}
|
1
apps/platform/src/api/index.ts
Normal file
1
apps/platform/src/api/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './core';
|
113
apps/platform/src/api/request.ts
Normal file
113
apps/platform/src/api/request.ts
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* 该文件可自行根据业务逻辑进行调整
|
||||||
|
*/
|
||||||
|
import type { RequestClientOptions } from '@vben/request';
|
||||||
|
|
||||||
|
import { useAppConfig } from '@vben/hooks';
|
||||||
|
import { preferences } from '@vben/preferences';
|
||||||
|
import {
|
||||||
|
authenticateResponseInterceptor,
|
||||||
|
defaultResponseInterceptor,
|
||||||
|
errorMessageResponseInterceptor,
|
||||||
|
RequestClient,
|
||||||
|
} from '@vben/request';
|
||||||
|
import { useAccessStore } from '@vben/stores';
|
||||||
|
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
import { useAuthStore } from '#/store';
|
||||||
|
|
||||||
|
import { refreshTokenApi } from './core';
|
||||||
|
|
||||||
|
const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD);
|
||||||
|
|
||||||
|
function createRequestClient(baseURL: string, options?: RequestClientOptions) {
|
||||||
|
const client = new RequestClient({
|
||||||
|
...options,
|
||||||
|
baseURL,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新认证逻辑
|
||||||
|
*/
|
||||||
|
async function doReAuthenticate() {
|
||||||
|
console.warn('Access token or refresh token is invalid or expired. ');
|
||||||
|
const accessStore = useAccessStore();
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
accessStore.setAccessToken(null);
|
||||||
|
if (
|
||||||
|
preferences.app.loginExpiredMode === 'modal' &&
|
||||||
|
accessStore.isAccessChecked
|
||||||
|
) {
|
||||||
|
accessStore.setLoginExpired(true);
|
||||||
|
} else {
|
||||||
|
await authStore.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新token逻辑
|
||||||
|
*/
|
||||||
|
async function doRefreshToken() {
|
||||||
|
const accessStore = useAccessStore();
|
||||||
|
const resp = await refreshTokenApi();
|
||||||
|
const newToken = resp.data;
|
||||||
|
accessStore.setAccessToken(newToken);
|
||||||
|
return newToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatToken(token: null | string) {
|
||||||
|
return token ? `Bearer ${token}` : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求头处理
|
||||||
|
client.addRequestInterceptor({
|
||||||
|
fulfilled: async (config) => {
|
||||||
|
const accessStore = useAccessStore();
|
||||||
|
|
||||||
|
config.headers.Authorization = formatToken(accessStore.accessToken);
|
||||||
|
config.headers['Accept-Language'] = preferences.app.locale;
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 处理返回的响应数据格式
|
||||||
|
client.addResponseInterceptor(
|
||||||
|
defaultResponseInterceptor({
|
||||||
|
codeField: 'code',
|
||||||
|
dataField: 'data',
|
||||||
|
successCode: 0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// token过期的处理
|
||||||
|
client.addResponseInterceptor(
|
||||||
|
authenticateResponseInterceptor({
|
||||||
|
client,
|
||||||
|
doReAuthenticate,
|
||||||
|
doRefreshToken,
|
||||||
|
enableRefreshToken: preferences.app.enableRefreshToken,
|
||||||
|
formatToken,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 通用的错误处理,如果没有进入上面的错误处理逻辑,就会进入这里
|
||||||
|
client.addResponseInterceptor(
|
||||||
|
errorMessageResponseInterceptor((msg: string, error) => {
|
||||||
|
// 这里可以根据业务进行定制,你可以拿到 error 内的信息进行定制化处理,根据不同的 code 做不同的提示,而不是直接使用 message.error 提示 msg
|
||||||
|
// 当前mock接口返回的错误字段是 error 或者 message
|
||||||
|
const responseData = error?.response?.data ?? {};
|
||||||
|
const errorMessage = responseData?.error ?? responseData?.message ?? '';
|
||||||
|
// 如果没有错误信息,则会根据状态码进行提示
|
||||||
|
ElMessage.error(errorMessage || msg);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const requestClient = createRequestClient(apiURL, {
|
||||||
|
responseReturn: 'data',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const baseRequestClient = new RequestClient({ baseURL: apiURL });
|
22
apps/platform/src/app.vue
Normal file
22
apps/platform/src/app.vue
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { useElementPlusDesignTokens } from '@vben/hooks';
|
||||||
|
|
||||||
|
import { ElConfigProvider } from 'element-plus';
|
||||||
|
|
||||||
|
import { elementLocale } from '#/locales';
|
||||||
|
import { useUserStore } from '#/store/user';
|
||||||
|
|
||||||
|
defineOptions({ name: 'App' });
|
||||||
|
|
||||||
|
useElementPlusDesignTokens();
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
userStore.login();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ElConfigProvider size="small" :locale="elementLocale">
|
||||||
|
<RouterView />
|
||||||
|
</ElConfigProvider>
|
||||||
|
</template>
|
73
apps/platform/src/bootstrap.ts
Normal file
73
apps/platform/src/bootstrap.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import { createApp, watchEffect } from 'vue';
|
||||||
|
|
||||||
|
import { registerAccessDirective } from '@vben/access';
|
||||||
|
import { initTippy, registerLoadingDirective } from '@vben/common-ui';
|
||||||
|
import { MotionPlugin } from '@vben/plugins/motion';
|
||||||
|
import { preferences } from '@vben/preferences';
|
||||||
|
import { initStores } from '@vben/stores';
|
||||||
|
import '@vben/styles';
|
||||||
|
import '@vben/styles/ele';
|
||||||
|
|
||||||
|
import { useTitle } from '@vueuse/core';
|
||||||
|
import { ElLoading } from 'element-plus';
|
||||||
|
|
||||||
|
import { $t, setupI18n } from '#/locales';
|
||||||
|
|
||||||
|
import { initComponentAdapter } from './adapter/component';
|
||||||
|
import App from './app.vue';
|
||||||
|
import { router } from './router';
|
||||||
|
|
||||||
|
async function bootstrap(namespace: string) {
|
||||||
|
// 初始化组件适配器
|
||||||
|
await initComponentAdapter();
|
||||||
|
// // 设置弹窗的默认配置
|
||||||
|
// setDefaultModalProps({
|
||||||
|
// fullscreenButton: false,
|
||||||
|
// });
|
||||||
|
// // 设置抽屉的默认配置
|
||||||
|
// setDefaultDrawerProps({
|
||||||
|
// zIndex: 2000,
|
||||||
|
// });
|
||||||
|
const app = createApp(App);
|
||||||
|
|
||||||
|
// 注册Element Plus提供的v-loading指令
|
||||||
|
app.directive('loading', ElLoading.directive);
|
||||||
|
|
||||||
|
// 注册Vben提供的v-loading和v-spinning指令
|
||||||
|
registerLoadingDirective(app, {
|
||||||
|
loading: false, // Vben提供的v-loading指令和Element Plus提供的v-loading指令二选一即可,此处false表示不注册Vben提供的v-loading指令
|
||||||
|
spinning: 'spinning',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 国际化 i18n 配置
|
||||||
|
await setupI18n(app);
|
||||||
|
|
||||||
|
// 配置 pinia-tore
|
||||||
|
await initStores(app, { namespace });
|
||||||
|
|
||||||
|
// 安装权限指令
|
||||||
|
registerAccessDirective(app);
|
||||||
|
|
||||||
|
// 初始化 tippy
|
||||||
|
initTippy(app);
|
||||||
|
|
||||||
|
// 配置路由及路由守卫
|
||||||
|
app.use(router);
|
||||||
|
|
||||||
|
// 配置Motion插件
|
||||||
|
app.use(MotionPlugin);
|
||||||
|
|
||||||
|
// 动态更新标题
|
||||||
|
watchEffect(() => {
|
||||||
|
if (preferences.app.dynamicTitle) {
|
||||||
|
const routeTitle = router.currentRoute.value.meta?.title;
|
||||||
|
const pageTitle =
|
||||||
|
(routeTitle ? `${$t(routeTitle)} - ` : '') + preferences.app.name;
|
||||||
|
useTitle(pageTitle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.mount('#app');
|
||||||
|
}
|
||||||
|
|
||||||
|
export { bootstrap };
|
76
apps/platform/src/components/renderer-adapter/index.vue
Normal file
76
apps/platform/src/components/renderer-adapter/index.vue
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
import Postmate from 'postmate';
|
||||||
|
|
||||||
|
import { useUserStore } from '#/store/user';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// const MAX_RETRIES = 3;
|
||||||
|
const route = useRoute();
|
||||||
|
// const MAX_RETRIES = 3;
|
||||||
|
|
||||||
|
const loading = ref(true);
|
||||||
|
const errorMessage = ref('');
|
||||||
|
// const retryCount = ref(0);
|
||||||
|
|
||||||
|
const initPostmate = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
errorMessage.value = '';
|
||||||
|
const container = document.querySelector('#low-code-adapter');
|
||||||
|
if (!container) {
|
||||||
|
errorMessage.value = '容器元素未找到';
|
||||||
|
loading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = new Postmate({
|
||||||
|
container,
|
||||||
|
url: route.meta?.app?.url,
|
||||||
|
name: 'y-code-renderer',
|
||||||
|
classListArray: ['responsive-iframe'],
|
||||||
|
model: {
|
||||||
|
accessToken: userStore.token,
|
||||||
|
name: route.meta?.app?.name,
|
||||||
|
applicationId: route.meta?.app?.applicationId,
|
||||||
|
projectId: route.meta?.app?.projectId,
|
||||||
|
fileId: route.meta?.app?.fileId,
|
||||||
|
url: route.meta?.app?.url,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.then((child) => {
|
||||||
|
// console.log('Postmate 连接成功', child);
|
||||||
|
child.on('some-event', (data) => console.log(data)); // Logs "Hello, World!"
|
||||||
|
child.call('child-connected', {
|
||||||
|
name: route.meta?.app?.name,
|
||||||
|
});
|
||||||
|
// retryCount.value = 0; // 重置重试计数器
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initPostmate();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div id="low-code-adapter"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.responsive-iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
#low-code-adapter {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
16
apps/platform/src/constants/env.ts
Normal file
16
apps/platform/src/constants/env.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export const devMode = 'development';
|
||||||
|
|
||||||
|
export const prodMode = 'production';
|
||||||
|
|
||||||
|
export const stagingMode = 'staging';
|
||||||
|
|
||||||
|
export const currentEnv = import.meta.env;
|
||||||
|
|
||||||
|
export const isDevMode = import.meta.env.MODE === devMode;
|
||||||
|
export const isProdMode = import.meta.env.MODE === prodMode;
|
||||||
|
export const isStagingMode = import.meta.env.MODE === stagingMode;
|
||||||
|
|
||||||
|
export const VITE_RENDERER_URL = currentEnv.VITE_RENDERER_URL;
|
||||||
|
export const VITE_DESIGNER_URL = currentEnv.VITE_DESIGNER_URL;
|
||||||
|
export const VITE_PLATFORM_URL = currentEnv.VITE_PLATFORM_URL;
|
||||||
|
export const VITE_V1_URL = currentEnv.VITE_V1_URL;
|
3
apps/platform/src/constants/index.ts
Normal file
3
apps/platform/src/constants/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// export * from '@sy/low-code-shared/constants';
|
||||||
|
export * from './env';
|
||||||
|
export * from './low-code';
|
2
apps/platform/src/constants/low-code.ts
Normal file
2
apps/platform/src/constants/low-code.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export const LOW_CODE_APPLICATION_ID = 0;
|
||||||
|
export const LOW_CODE_PROJECT_ID = 4;
|
22
apps/platform/src/io/application.ts
Normal file
22
apps/platform/src/io/application.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
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) => {
|
||||||
|
console.log(id);
|
||||||
|
const response = await instance.delete(`/api/v1/applications/${id}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
16
apps/platform/src/io/file.ts
Normal file
16
apps/platform/src/io/file.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import instance from './instance';
|
||||||
|
|
||||||
|
export const uploadFile = async (data: FormData) => {
|
||||||
|
const response = await instance.post('/api/v1/files/upload', data);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteFile = async (id: string) => {
|
||||||
|
const response = await instance.delete(`/api/v1/files/upload/${id}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFileList = async () => {
|
||||||
|
const response = await instance.get('/api/v1/files/upload');
|
||||||
|
return response.data;
|
||||||
|
};
|
3
apps/platform/src/io/index.ts
Normal file
3
apps/platform/src/io/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './application';
|
||||||
|
export * from './project';
|
||||||
|
export * from './user';
|
46
apps/platform/src/io/instance.ts
Normal file
46
apps/platform/src/io/instance.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
import appClient from '#/io/tianti';
|
||||||
|
import { useUserStore } from '#/store/user';
|
||||||
|
|
||||||
|
// axios拦截器
|
||||||
|
const { reqInterceptor, resInterceptor } = appClient.getInterceptor();
|
||||||
|
|
||||||
|
const baseApiUrl = import.meta.env.VITE_BASE_API_URL;
|
||||||
|
|
||||||
|
// 创建独立实例
|
||||||
|
const instance = axios.create({
|
||||||
|
baseURL: baseApiUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
instance.interceptors.request.use(
|
||||||
|
(config) => config,
|
||||||
|
(error) => Promise.reject(error),
|
||||||
|
);
|
||||||
|
instance.interceptors.request.use(
|
||||||
|
reqInterceptor.fulfilled,
|
||||||
|
reqInterceptor.rejected,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 响应拦截器
|
||||||
|
instance.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
// 检查是否为401未授权错误
|
||||||
|
if (response.data.code === 401) {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
console.log('用户未授权或登录已过期,即将跳转...');
|
||||||
|
// userStore.logout();
|
||||||
|
// 返回一个永远不会resolve的Promise,防止后续代码执行
|
||||||
|
return new Promise(() => {});
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
(error) => Promise.reject(error),
|
||||||
|
);
|
||||||
|
instance.interceptors.response.use(
|
||||||
|
resInterceptor.fulfilled,
|
||||||
|
resInterceptor.rejected,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 导出实例
|
||||||
|
export default instance;
|
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