25 Commits

Author SHA1 Message Date
wangxuefeng
b2ac996df2 Merge branch 'feature/low-code-platform' into release
# Conflicts:
#	package.json
2025-03-11 10:26:26 +08:00
王雪峰
4cebf31583 Merge branch 'feature/update-depencies' into 'release'
Feature/update depencies

See merge request workbench/y-code!41
2024-12-04 18:53:29 +08:00
wangxuefeng
abc9d36536 feat: 更新丢失的依赖 2024-12-04 18:30:46 +08:00
姚晓琼
90e773d96c Merge branch 'feature/new-sys' into 'release'
Feature/new sys

See merge request workbench/y-code!35
2024-10-30 11:09:59 +08:00
姚晓琼
ff54373a5d Merge branch 'feature/new-sys' into 'release'
fix: 预览接口新增类型传参

See merge request workbench/y-code!30
2024-10-29 12:03:52 +08:00
姚晓琼
3461528100 Merge branch 'feature/new-sys' into 'release'
新增筛选类型

See merge request workbench/y-code!28
2024-10-28 18:36:28 +08:00
吴骆婷
b6ce2afba3 Merge branch 'feature/new-sys' into 'release'
补充链接href

See merge request workbench/y-code!24
2024-08-09 18:03:52 +08:00
吴骆婷
633dafd80b Merge branch 'feature/new-sys' into 'release'
fix: 新增id展示

See merge request workbench/y-code!23
2024-08-09 17:35:01 +08:00
吴骆婷
1f12ba3d5e Merge branch 'feature/new-sys' into 'release'
预览支持图片等内容展示

See merge request workbench/y-code!22
2024-08-09 11:09:59 +08:00
吴骆婷
adbe6953c9 Merge branch 'feature/new-sys' into 'release'
fix: 筛选条件变化页数重置

See merge request workbench/y-code!20
2024-08-01 11:52:57 +08:00
姚晓琼
9d940b05ff Merge branch 'feature/new-sys' into 'release'
fix: 报表新增导出

See merge request workbench/y-code!18
2024-07-31 18:52:26 +08:00
吴骆婷
b2fd5051d1 Merge branch 'feature/new-sys' into 'release'
fix: 报表支持导出

See merge request workbench/y-code!17
2024-07-31 10:44:29 +08:00
姚晓琼
77fe2bdb0b Merge branch 'feature/new-sys' into 'release'
fix: 报表新增导出+样式隔离

See merge request workbench/y-code!16
2024-07-30 20:19:30 +08:00
姚晓琼
3e50d8e5f7 Merge branch 'feature/new-sys' into 'release'
fix: 添加传参

See merge request workbench/y-code!14
2024-07-29 15:36:01 +08:00
姚晓琼
bc1e123a09 Merge branch 'feature/new-sys' into 'release'
fix: 字段管理调整必填项

See merge request workbench/y-code!13
2024-07-29 15:28:05 +08:00
姚晓琼
da8c74f294 Merge branch 'feature/new-sys' into 'release'
fix: 修改vite配置

See merge request workbench/y-code!11
2024-07-26 17:44:08 +08:00
吴骆婷
b74992b562 Merge branch 'feature/new-sys' into 'release'
fix: 新增配置qiankun

See merge request workbench/y-code!10
2024-07-26 17:22:49 +08:00
吴骆婷
3545a324a4 Merge branch 'feature/new-sys' into 'release'
fix: 添加数据库驱动配置

See merge request workbench/y-code!9
2024-07-25 17:16:23 +08:00
姚晓琼
5999b3ec9c Merge branch 'feature/new-sys' into 'release'
fix: 字段管理新增一个字段

See merge request workbench/y-code!8
2024-07-24 20:42:22 +08:00
林梓阳
6b989638f0 Merge branch 'feature/new-sys' into 'release'
fix: 修改保存报错bug

See merge request workbench/y-code!7
2024-07-18 12:36:23 +08:00
吴骆婷
9c45ad8acd Merge branch 'feature/new-sys' into 'release'
fix: 修复数据来源操作bug

See merge request workbench/y-code!6
2024-07-18 11:56:50 +08:00
姚晓琼
d746c211e7 Merge branch 'feature/new-sys' into 'release'
删除文件

See merge request workbench/y-code!5
2024-07-17 23:50:33 +08:00
姚晓琼
59c2db7ca3 Merge branch 'feature/new-sys' into 'release'
fix: 调整数据来源配置

See merge request workbench/y-code!4
2024-07-17 23:38:24 +08:00
吴骆婷
a7d333069c Merge branch 'feature/new-sys' into 'release'
feat: 新增图表渲染

See merge request workbench/y-code!3
2024-07-17 11:54:41 +08:00
林梓阳
1fe3e6cd43 Merge branch 'feature/new-sys' into 'release'
feat: 新增配置管理和视图管理

See merge request workbench/y-code!1
2024-07-16 15:39:17 +08:00
246 changed files with 8697 additions and 13974 deletions

View File

@@ -1,8 +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)
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)
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)

View File

@@ -1,11 +1,18 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": "@changesets/cli/changelog",
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": [
"@changesets/changelog-github",
{ "repo": "vbenjs/vue-vben-admin" }
],
"commit": false,
"fixed": [],
"fixed": [["@vben-core/*", "@vben/*"]],
"snapshot": {
"prereleaseTemplate": "{tag}-{datetime}"
},
"privatePackages": { "version": true, "tag": true },
"linked": [],
"access": "restricted",
"baseBranch": "master",
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}

9
.gitignore vendored
View File

@@ -49,12 +49,3 @@ vite.config.ts.*
*.sln
*.sw?
.history
# 忽略 docs/src 中 sync-change-log.mjs 获得的 changelog 文件
apps/docs/src/renderer/CHANGELOG.md
apps/docs/src/designer/CHANGELOG.md
apps/docs/src/platform/CHANGELOG.md
# 忽略 turbo-graph 生成的文件
dependencies.html
dependencies.png

3
.npmrc
View File

@@ -1,4 +1,4 @@
registry = https://registry.npmmirror.com
registry = "https://registry.npmmirror.com"
@sy:registry=http://sy-registry.shiyue.com
public-hoist-pattern[]=husky
public-hoist-pattern[]=eslint
@@ -12,4 +12,3 @@ public-hoist-pattern[]=czg
strict-peer-dependencies=false
auto-install-peers=true
dedupe-peer-dependents=true
engine-strict=true

9
LICENSE Normal file
View 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.

View File

@@ -1,8 +1,65 @@
<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](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
<h1>Vue Vben Admin</h1>
</div>
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=vbenjs_vue-vben-admin&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=vbenjs_vue-vben-admin) ![codeql](https://github.com/vbenjs/vue-vben-admin/actions/workflows/codeql.yml/badge.svg) ![build](https://github.com/vbenjs/vue-vben-admin/actions/workflows/build.yml/badge.svg) ![ci](https://github.com/vbenjs/vue-vben-admin/actions/workflows/ci.yml/badge.svg) ![deploy](https://github.com/vbenjs/vue-vben-admin/actions/workflows/deploy.yml/badge.svg)
**中文** | [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 的免费在线开发环境)中打开项目,并立即开始编码.
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/vbenjs/vue-vben-admin)
## 文档
[文档地址](https://y-code-docs.shiyuegame.com)
[文档地址](https://doc.vben.pro/)
## 安装使用
- 获取项目代码
```bash
git clone https://github.com/vbenjs/vue-vben-admin.git
```
- 安装依赖
```bash
cd vue-vben-admin
corepack enable
pnpm install
@@ -24,6 +81,18 @@ pnpm build
[CHANGELOG](https://github.com/vbenjs/vue-vben-admin/releases)
## 如何贡献
非常欢迎你的加入![提一个 Issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) 或者提交一个 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))
@@ -50,3 +119,34 @@ pnpm build
| [<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
[![Star History Chart](https://api.star-history.com/svg?repos=vbenjs/vue-vben-admin&type=Date)](https://star-history.com/#vbenjs/vue-vben-admin&Date)
## 捐赠
如果你觉得这个项目对你有帮助,你可以帮作者买一杯咖啡表示支持!
![donate](https://unpkg.com/@vbenjs/static-source@0.1.7/source/sponsor.png)
<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)

View File

@@ -1,15 +0,0 @@
# 只在生产模式中被载入
VITE_NODE_ENV = 'development'
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
VITE_BASE_URL = /
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
VITE_PORT = 10011
VITE_DEBUG_MODE = true
VITE_PLATFORM_URL = 'https://localhost:10010'
VITE_DESIGNER_URL = 'https://localhost:10011'
VITE_RENDERER_URL = 'https://localhost:10012'

View File

@@ -1,16 +0,0 @@
# 只在预发布模式中被载入
VITE_NODE_ENV = 'development'
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
VITE_BASE_URL = /
# base api url
VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
VITE_PORT = 10011
VITE_DEBUG_MODE = true
VITE_PLATFORM_URL = 'https://localhost:10010'
VITE_DESIGNER_URL = 'https://localhost:10011'
VITE_RENDERER_URL = 'https://localhost:10012'

View File

@@ -4,12 +4,14 @@ 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'
VITE_PLATFORM_URL = 'https://localhost:10010/'
VITE_DESIGNER_URL = 'https://localhost:10011/'
VITE_RENDERER_URL = 'https://localhost:10012/'

View File

@@ -7,6 +7,6 @@ VITE_BASE_URL = /
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
VITE_PLATFORM_URL = 'https://y-code.shiyue.com/'
VITE_DESIGNER_URL = 'https://y-code-designer.shiyue.com/'
VITE_RENDERER_URL = 'https://y-code-renderer.shiyue.com/'
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/'

View File

@@ -7,6 +7,6 @@ VITE_BASE_URL = /
# base api url
VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
VITE_PLATFORM_URL = 'https://y-code-pre.shiyue.com/'
VITE_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/'

View File

@@ -1,3 +1,5 @@
{
"recommendations": ["vue.volar"]
}
"recommendations": [
"vue.volar"
]
}

View File

@@ -1,7 +0,0 @@
# @sy/y-code-designer
## 1.0.0
### Patch Changes
- project changeset init

View File

@@ -1,31 +1,29 @@
{
"name": "@sy/y-code-designer",
"version": "1.0.0",
"description": "低代码设计器",
"version": "1.0.0-1",
"description": "低代码编辑器",
"private": true,
"type": "module",
"scripts": {
"dev": "vite --mode development",
"dev:staging": "vite --mode dev-staging",
"dev:prod": "vite --mode dev-production",
"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",
"build:dev": "vite build --mode development",
"preview": "vite preview",
"typecheck": "vue-tsc --noEmit --skipLibCheck"
"clean": "rimraf node_modules"
},
"dependencies": {
"@vtj/core": "^0.11.12",
"@vtj/designer": "0.11.12",
"@vtj/icons": "0.11.12",
"@vtj/local": "^0.11.12",
"@vtj/materials": "^0.11.12",
"@vtj/node": "0.11.2",
"@vtj/pro": "^0.11.12",
"@vtj/renderer": "^0.11.12",
"@vtj/ui": "^0.11.12",
"@vtj/utils": "0.11.12",
"@vtj/web": "^0.11.12",
"@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",
@@ -37,8 +35,7 @@
"vue-router": "catalog:"
},
"devDependencies": {
"@types/postmate": "catalog:",
"@vtj/cli": "^0.11.2",
"@vtj/cli": "^0.10.2",
"vite": "catalog:",
"vite-plugin-mkcert": "catalog:",
"vitest": "catalog:"

View File

@@ -1,8 +1,7 @@
import { rm } from 'node:fs/promises';
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('开始完成!');
console.log('开始完成!');

View File

@@ -6,83 +6,98 @@
// 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']
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')
export type {
Component,
ComponentPublicInstance,
ComputedRef,
DirectiveBinding,
ExtractDefaultPropTypes,
ExtractPropTypes,
ExtractPublicPropTypes,
InjectionKey,
PropType,
Ref,
MaybeRef,
MaybeRefOrGetter,
VNode,
WritableComputedRef
} from 'vue';
import('vue');
}

View File

@@ -1 +1,2 @@
export const currentEnv = import.meta.env;
// @ts-ignore
export const currentEnv = __APP_ENV__;

View File

@@ -3,11 +3,11 @@
declare module '*.vue' {
import type { DefineComponent } from 'vue';
const component: DefineComponent<object, object, any>;
const component: DefineComponent<{}, {}, any>;
export default component;
}
declare namespace _NodeJS {
declare namespace NodeJS {
interface ProcessEnv {
[key: string]: any;
}
@@ -20,7 +20,6 @@ declare namespace global {
declare module 'vue' {
interface ComponentCustomProperties {
$uploader: any;
// cspell:disable-next-line
$reqeust: any;
$apis: any;
$libs: any;

View File

@@ -9,7 +9,6 @@ export type LowCodeFileSchema = {
file_path?: string;
project_id: number;
publish: boolean;
published_dsl: BlockSchema;
};
function transformFile(file: LowCodeFileSchema): LowCodeFileSchema {
@@ -80,6 +79,9 @@ export const publishAllFile = async (
* 发布单个文件
* @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', {

View File

@@ -11,7 +11,6 @@ const instance = axios.create({
instance.interceptors.request.use(
(config) => {
// 可在此处添加统一请求头等配置
config.headers.Authorization = `Bearer ${localStorage.getItem('y-code-access-token')}`;
return config;
},
(error) => {

View File

@@ -2,16 +2,6 @@ import type { MaterialDescription } from '@vtj/core';
import instance from './instance';
type MaterialData = {
created_at?: string;
// 从原interface合并的字段
id?: number;
name?: string;
project_id: number;
updated_at?: string;
value: Record<string, MaterialDescription>;
};
// 定义响应类型
interface MaterialResponse {
code: number;
@@ -61,6 +51,16 @@ export const getMaterials = async (id: number): Promise<MaterialResponse> => {
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,

View File

@@ -15,9 +15,8 @@ pinia.use(
storage: localStorage
})
);
const app = createApp(App);
// 关闭警告
app.config.warnHandler = () => null;
app.use(router);
app.use(pinia);
app.mount('#app');

View File

@@ -1,5 +1,3 @@
// @ts-nocheck 忽略所有类型检查
import type {
BlockFile,
BlockSchema,
@@ -8,8 +6,8 @@ import type {
HistorySchema,
MaterialDescription,
NodeFromPlugin,
ProjectSchema as OriginalProjectSchema,
PageFile
PageFile,
ProjectSchema
} from '@vtj/core';
import {
@@ -49,22 +47,17 @@ const stringifyFields = new Set([
'pages'
]);
// 扩展原始类型
type ProjectSchema = Omit<OriginalProjectSchema, 'projectId'> & {
projectId: number | string;
};
let initProject: ProjectSchema;
export class LowCodeService extends BaseService {
public api = (_type: string, _data: any): Promise<any> => {
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);
console.log('ExtensionConfig', extension);
return Promise.resolve(extension as ExtensionConfig | undefined);
}
@@ -72,9 +65,10 @@ export class LowCodeService extends BaseService {
return getLowCodeFile(id).then((lowCodeFile) => {
return lowCodeFile.dsl
? Promise.resolve(lowCodeFile.dsl as BlockSchema)
: Promise.reject(new Error('文件不存在'));
: Promise.reject(null);
});
}
public async getHistory(fileId: string): Promise<HistorySchema> {
const histories = await getLowCodeHistories({
project_id: initProject.id,
@@ -101,12 +95,13 @@ export class LowCodeService extends BaseService {
}
public getPluginMaterial(
_from: NodeFromPlugin
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'];
@@ -115,7 +110,9 @@ export class LowCodeService extends BaseService {
remoteProject[field] = [];
}
});
console.log('remoteProject', remoteProject);
const model = new ProjectModel(remoteProject);
console.log('model', model || { id: initProject.id });
const dsl = model.toDsl();
return dsl;
}
@@ -150,6 +147,7 @@ export class LowCodeService extends BaseService {
}
public async saveFile(file: BlockSchema): Promise<boolean> {
console.log('saveFile', file);
if (file.id) {
const existFile = await getLowCodeFile(file.id);
return existFile.file_id
@@ -164,7 +162,7 @@ export class LowCodeService extends BaseService {
throw error;
})
: createFile({
project_id: Number(initProject.id),
project_id: initProject.id,
publish: false,
active: true,
dsl: file,
@@ -180,7 +178,7 @@ export class LowCodeService extends BaseService {
return false;
}
public async saveHistory(_history: HistorySchema): Promise<boolean> {
public async saveHistory(history: HistorySchema): Promise<boolean> {
return true;
}
@@ -203,20 +201,25 @@ export class LowCodeService extends BaseService {
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
});
}
// 根据是否存在物料决定更新或创建
existMaterials
? await updateLowCodeMaterials({
project_id: project?.id,
value: materialData
})
: await postLowCodeMaterials({
project_id: project?.id,
value: materialData
});
// @ts-ignore - 暂时禁用此行代码,保留以备后续可能需要删除物料的操作
// @ts-ignore
// await deleteLowCodeMaterials(project.id);
return true;
}
@@ -235,7 +238,8 @@ export class LowCodeService extends BaseService {
return true;
}
protected uploader = (_file: File, _projectId: string): Promise<any> => {
protected uploader = (file: File, projectId: string): Promise<any> => {
// console.log('uploader', file, projectId);
return Promise.resolve(true);
};
}

View File

@@ -25,18 +25,15 @@ onMounted(async () => {
await handshake.then((parent) => {
parent.emit('sync-context', 'y-code-designer is ready');
Object.assign(model, parent.model);
console.log('get parent model', model);
// console.log('get parent model', model);
userStore.setToken(model.accessToken);
localStorage.setItem('y-code-access-token', model.accessToken);
request.useRequest((req) => {
req.headers.set('Authorization', `Bearer ${model.accessToken}`);
return req;
});
sessionStorage.setItem('projectId', model.projectId);
const _engine = new Engine({
const engine = new Engine({
container,
service,
window,
project: {
// @ts-ignore
id: model.projectId,
@@ -59,15 +56,6 @@ onMounted(async () => {
widgetManager.set('Templates', {
invisible: true
});
widgetManager.set('About', {
invisible: true
});
widgetManager.set('History', {
// 有 bug先隐藏
// invisible: true
});
});
});
</script>

View File

@@ -18,7 +18,7 @@ const { provider, onReady } = createProvider({
service,
project: {
// @ts-ignore
id: sessionStorage.getItem('projectId')
id: 4
},
adapter: {
request,

View File

@@ -1,19 +1,27 @@
{
"extends": "./node_modules/@vtj/cli/config/tsconfig.web.json",
"compilerOptions": {
"noUnusedLocals": false,
"noUnusedParameters": false,
"baseUrl": "./",
"paths": {
"@/*": ["src/*"],
"$vtj/*": [".vtj/*"]
},
"noUnusedLocals": false,
"noUnusedParameters": false
"@/*": [
"src/*"
],
"$vtj/*": [
".vtj/*"
]
}
},
"include": [
"src"
],
"exclude": [
".vtj",
],
"references": [
{
"path": "./tsconfig.node.json"
}
],
"include": ["src"],
"exclude": [".vtj"]
}
]
}

View File

@@ -1,10 +1,13 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"skipLibCheck": true
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts", "proxy.config.ts"]
}
"include": [
"vite.config.ts",
"proxy.config.ts"
]
}

View File

@@ -4,45 +4,49 @@ 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);
const env = loadEnv(mode, process.cwd(), ['VITE_']);
const isDev = env.VITE_NODE_ENV === 'development';
const config = createViteConfig({
// proxy,
plugins: [
createDevTools(),
isDev && mkcert(),
AutoImport({
imports: [
'vue',
'pinia',
'vue-router',
{
from: 'pinia',
imports: ['storeToRefs', 'defineStore'],
type: true
}
],
dts: 'src/auto-imports.d.ts', // 生成类型声明文件
eslintrc: {
enabled: true // 生成 eslint 配置
}
})
]
});
// 加载环境变量(支持 .env.development/.env.production
const env = loadEnv(mode, process.cwd(), ['VITE_', 'VTJ_', 'SY_', 'Y_CODE_']);
return {
...config,
server: {
cors: true,
https: true,
port: isDev ? Number(env.VITE_PORT) : undefined,
port: env.VITE_PORT,
host: true
},
define: {
// 注入环境变量到客户端
__APP_ENV__: JSON.stringify(env)
}
// build: {
// outDir: path.resolve(process.cwd(), '../../dist/designer'),
// emptyOutDir: true // 构建前清空目录
// }
};
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +0,0 @@
# @sy/y-code-docs
## 1.0.0
### Patch Changes
- project changeset init

View File

@@ -1,58 +0,0 @@
#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
// 获取当前脚本的目录
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 源目录和目标目录
const sourceDir = path.resolve(__dirname, '../.vitepress/dist');
const targetDir = path.resolve(process.cwd(), 'dist');
// 检查源目录是否存在
if (!fs.existsSync(sourceDir)) {
console.error(`错误:源目录 "${sourceDir}" 不存在!`);
console.error('请确保已经运行了 vitepress build 命令');
process.exit(1);
}
// 如果目标目录已存在,则先删除
if (fs.existsSync(targetDir)) {
console.log(`目标目录 "${targetDir}" 已存在,正在删除...`);
fs.rmSync(targetDir, { recursive: true, force: true });
}
// 递归复制目录函数
function copyDirRecursive(src, dest) {
// 创建目标目录
fs.mkdirSync(dest, { recursive: true });
// 读取源目录中的所有文件/目录
const entries = fs.readdirSync(src, { withFileTypes: true });
for (const entry of entries) {
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
// 根据文件类型进行不同处理
if (entry.isDirectory()) {
// 递归复制子目录
copyDirRecursive(srcPath, destPath);
} else {
// 复制文件
fs.copyFileSync(srcPath, destPath);
}
}
}
try {
// 复制目录
copyDirRecursive(sourceDir, targetDir);
console.log(`✅ 成功将 ".vitepress/dist" 复制到 "${targetDir}"`);
} catch (error) {
console.error(`❌ 复制过程中发生错误:${error.message}`);
process.exit(1);
}

View File

@@ -1,61 +0,0 @@
#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
// 获取当前脚本的目录
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 需要处理的应用列表
const appsToProcess = ['renderer', 'designer', 'platform'];
// 复制CHANGELOG.md文件
function copyChangelogFile(appName) {
const changelogSrcPath = path.resolve(
process.cwd(),
`../${appName}/CHANGELOG.md`,
);
const changelogDestDir = path.resolve(__dirname, `../src/${appName}`);
const changelogDestPath = path.resolve(changelogDestDir, 'CHANGELOG.md');
console.log(`正在复制${appName}的CHANGELOG.md文件...`);
// 检查源文件是否存在
if (!fs.existsSync(changelogSrcPath)) {
console.warn(
`⚠️ 警告:${appName}的CHANGELOG文件 "${changelogSrcPath}" 不存在!`,
);
return;
}
// 确保目标目录存在
if (!fs.existsSync(changelogDestDir)) {
console.log(`创建目标目录 "${changelogDestDir}"...`);
fs.mkdirSync(changelogDestDir, { recursive: true });
}
// 复制文件
try {
fs.copyFileSync(changelogSrcPath, changelogDestPath);
console.log(
`✅ 成功将${appName}的CHANGELOG.md复制到 "${changelogDestPath}"`,
);
} catch (error) {
console.error(
`❌ 复制${appName}的CHANGELOG.md时发生错误${error.message}`,
);
}
}
try {
// 复制各个应用的CHANGELOG.md文件
for (const app of appsToProcess) {
copyChangelogFile(app);
}
console.log(`✅ 所有CHANGELOG.md文件复制完成`);
} catch (error) {
console.error(`❌ 复制过程中发生错误:${error.message}`);
process.exit(1);
}

View File

@@ -1 +0,0 @@
设计器

View File

@@ -1,24 +0,0 @@
# 基础概念
## 低代码引擎
新版本中,悦码整体进行了重构,现在我们将会介绍一些基础概念,以便于你更好的理解悦码是如何工作的。请务必仔细阅读这一部分。
## 悦码中的 DSL (领域特定语言)
> DSL (Domain-Specific Language领域特定语言) 在低代码平台中是一种专门设计用来描述和定义应用程序特定方面的语言或表达方式。
核心特点:
- 专注于特定领域DSL 专门针对特定问题域设计,如 UI 布局、工作流定义、数据模型等。
- 声明式而非命令式:通常使用声明式语法描述"做什么"而非"怎么做"。
- 抽象层次高:隐藏底层实现细节,让用户专注于业务逻辑。
- 结构化数据格式:通常使用 JSON、YAML 或 XML 等格式表示。
主要作用:
- 抽象复杂性:将复杂的编程概念转化为领域专家能理解的表达方式。
- 提高效率:通过声明式语法快速构建应用,减少编码工作。
- 标准化:为应用开发提供统一的描述方式,便于团队协作。
- 可视化编辑DSL 通常可以通过可视化编辑器生成和修改,无需直接编写。
- 跨平台兼容:同一套 DSL 可以被转译为不同平台的代码。

View File

@@ -1 +0,0 @@
# 本地开发 {#development}

View File

@@ -1 +0,0 @@
# 外部模块

View File

@@ -1 +0,0 @@
# icons

View File

@@ -1 +0,0 @@
# route

View File

@@ -1 +0,0 @@
server

View File

@@ -1 +0,0 @@
# settings

View File

@@ -1 +0,0 @@
# styles

View File

@@ -1,5 +0,0 @@
# 物料创建
```bash
npm create vtj@latest --registry=https://registry.npmmirror.com -- -t material
```

View File

@@ -1,116 +0,0 @@
# 低代码渲染器接入指南
## 1. 概述
- 1.1 什么是低代码渲染器
- 1.2 核心功能和优势
- 1.3 适用项目
- vue2
- vue3
- react
- 其他框架请联系伊利sy或王雪峰sy3570添加适配器
## 2. 环境要求
- node >= 20
- vue2 > 2.7.0
- vue3 > 3.5.0
- react > 18.0.0
## 3. 准备工作
1.npmrc 配置文件增加镜像指定sy 组件库走 shiyue 源,其他走淘宝镜像
```bash
registry=https://registry.npmmirror.com
@sy:registry=http://sy-registry.shiyue.com
```
2. node 至少要升级为 20 以上的版本
```bash
nvm install 20
nvm use 20
```
若不可行,请查看 node 官网历代大版本的 lts 版本(长期维护),自行安装,查看是否能正常渲染,选取稳定渲染悦码的那一个 node 版本作为开发环境
## 5. 接入方式
### vue2 项目接入
```bash
pnpm i @sy/wujie-vue2-renderer-adapter@latest --save
# or 或者
npm i @sy/wujie-vue2-renderer-adapter@latest --save
```
```vue
<script>
import WujieVueRendererAdapter from '@sy/wujie-vue2-renderer-adapter';
</script>
<template>
<!-- 默认使用高级渲染模式与原页面深度共享 document 与内存上下文 -->
<WujieVueRendererAdapter fileId="13a9dmbz" projectId="22" />
<!-- 降级渲染模式使用无界 iframe 加载悦码渲染器应用 -->
<!-- 缺点在于弹窗与遮罩层会约束在 iframe 空间内无法与原页面共享 document但无界的 iframe 可以与原页面共享内存上下文 这是比传统 iframe 更优的解决方案 -->
<WujieVueRendererAdapter fileId="13a9dmbz" projectId="22" />
</template>
```
### vue3 项目接入
```bash
pnpm i @sy/wujie-vue3-renderer-adapter@latest --save
# or 或者
npm i @sy/wujie-vue3-renderer-adapter@latest --save
```
```vue
<script setup>
import WujieVueRendererAdapter from '@sy/wujie-vue3-renderer-adapter';
</script>
<template>
<!-- 默认使用高级渲染模式与原页面深度共享 document 与内存上下文 -->
<WujieVueRendererAdapter fileId="13a9dmbz" projectId="22" />
<!-- 降级渲染模式使用无界 iframe 加载悦码渲染器应用 -->
<!-- 缺点在于弹窗与遮罩层会约束在 iframe 空间内无法与原页面共享 document但无界的 iframe 可以与原页面共享内存上下文 这是比传统 iframe 更优的解决方案 -->
<WujieVueRendererAdapter fileId="13a9dmbz" projectId="22" />
</template>
```
### react 项目接入
```bash
pnpm i @sy/wujie-react-renderer-adapter@latest --save
# or 或者
npm i @sy/wujie-react-renderer-adapter@latest --save
```
```jsx
import WujieReactRendererAdapter from '@sy/wujie-react-renderer-adapter';
return <WujieReactRendererAdapter fileId="13a9dmbz" projectId="22" />;
```
## API 参考
- 6.1 Props 参数详解
- 6.2 事件监听与回调
- 6.3 实例方法
- 6.4 拦截器使用
## 故障排除
- 常见错误及解决方案
- 日志与调试
- 悦码的日志输出一般在控制台中有 `console.ts 40` 的源码位置标记
- 兼容性问题处理
- renderer-adapter 是默认使用无界微应用来加载悦码渲染器应用的,这种集成方式会让悦码与你的父应用有更深的上下文结合和交互,但有一定的兼容性问题,当出现你无法解决的兼容性问题时,你可以手动设置 `degrade``false`,这将开启传统降级渲染,使用无界 iframe 加载悦码渲染器应用若还不行可摇人处理王雪峰sy3570
- 性能问题诊断
- 悦码渲染器内部使用了 sentry 上报错误,你可以跟 徐川sy0182 申请对应警告邮箱的使用权,获取报错邮件
![sentry 邮箱](https://cms-1256453865.cos.ap-shanghai.myqcloud.com/y-code/20250320/企业微信截图_20250320192100.png)

View File

@@ -1,5 +0,0 @@
<<< @/designer/CHANGELOG.md
<<< @/platform/CHANGELOG.md
<<< @/renderer/CHANGELOG.md

View File

@@ -1,17 +0,0 @@
# 关于低代码管理平台
## 特点
- **最新技术栈**:使用 `Vue3``Vite``TypeScript` 等前端前沿技术开发。
- **组件丰富**:提供了丰富的组件,可以满足大部分的业务需求。
- **多UI库支持**:支持 `Ant Design Vue``Element Plus` 等主流 UI 库,不再限制于特定框架。
## 浏览器支持
- **本地开发**推荐使用`Chrome 最新版`浏览器,**不支持**`Chrome 80`以下版本。
- **生产环境**支持现代浏览器,不支持 IE。
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt="IE" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)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/)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/)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/)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/)Safari |
| :-: | :-: | :-: | :-: | :-: |
| 不支持 | last 2 versions | last 2 versions | last 2 versions | last 2 versions |

View File

@@ -1,179 +0,0 @@
---
outline: deep
---
# 快速开始 {#quick-start}
## 前置准备
::: info 适用项目
- vue2
- vue3
- react
- 其他框架请联系伊利sy或王雪峰sy3570添加适配器
## 环境要求
- node >= 20
- vue2 > 2.7.0
- vue3 > 3.5.0
- react > 18.0.0
## 准备工作
1. npmrc 配置文件增加镜像指定sy 组件库走 shiyue 源,其他走淘宝镜像
```bash
# .npmrc
registry=https://registry.npmmirror.com
@sy:registry=http://sy-registry.shiyue.com
```
2. node 至少要升级为 20 以上的版本
```bash
nvm install 20
nvm use 20
```
若不可行,请查看 node 官网历代大版本的 lts 版本(长期维护),自行安装,查看是否能正常渲染,选取稳定渲染悦码的那一个 node 版本作为开发环境
:::
## 接入方式
### vue2 项目接入
```bash
pnpm i @sy/wujie-vue2-renderer-adapter@latest --save
# or 或者
npm i @sy/wujie-vue2-renderer-adapter@latest --save
```
```vue
<script>
import WujieVueRendererAdapter from '@sy/wujie-vue2-renderer-adapter';
</script>
<template>
<!-- 默认使用高级渲染模式与原页面深度共享 document 与内存上下文 -->
<WujieVueRendererAdapter fileId="test123" projectId="test123" />
<!-- 降级渲染模式使用无界 iframe 加载悦码渲染器应用 -->
<!-- 缺点在于弹窗与遮罩层会约束在 iframe 空间内无法与原页面共享 document但无界的 iframe 可以与原页面共享内存上下文 这是比传统 iframe 更优的解决方案 -->
<WujieVueRendererAdapter fileId="test123" projectId="test123" />
</template>
```
### vue3 项目接入
```bash
pnpm i @sy/wujie-vue3-renderer-adapter@latest --save
# or 或者
npm i @sy/wujie-vue3-renderer-adapter@latest --save
```
#### 路由形式使用
```ts
import type { RouteRecordRaw } from 'vue-router';
import RendererAdapter from '@sy/vue3-renderer-adapter';
import { isDevMode, LOW_CODE_PROJECT_ID, VITE_DESIGNER_URL } from '@/constants';
import router from '@/router';
const routes: RouteRecordRaw[] = [
{
path: '/micro',
name: 'Micro',
meta: {
title: '微应用容器',
icon: 'ant-design:appstore-outlined',
},
children: [
{
path: 'admin-designer',
name: 'AdminDesigner',
meta: {
hideInMenu: !isDevMode,
title: '平台设计器',
icon: 'ant-design:edit-outlined',
},
component: RendererAdapter,
// 可动态注入 props,根据必要性,可以注入 route 等参数
// 悦码里通过 ctxProps 获取,意思为上下文参数
props: (route) => {
return {
url: `${VITE_DESIGNER_URL}`,
projectId: 22,
fileId: '13a9dmbz',
// 你还可以提供 父应用的 router来实现子应用执行父应用的 router 方法来实现跳转
router, // 悦码里通过 ctxProps.router 调用
query: {
...route.query,
},
};
},
},
],
},
];
export default routes;
```
#### 组件形式使用
```vue
<script setup>
import WujieVueRendererAdapter from '@sy/wujie-vue3-renderer-adapter';
</script>
<template>
<!-- 默认使用高级渲染模式与原页面深度共享 document 与内存上下文 -->
<WujieVueRendererAdapter fileId="13a9dmbz" projectId="22" />
<!-- 降级渲染模式使用无界 iframe 加载悦码渲染器应用 -->
<!-- 缺点在于弹窗与遮罩层会约束在 iframe 空间内无法与原页面共享 document但无界的 iframe 可以与原页面共享内存上下文 这是比传统 iframe 更优的解决方案 -->
<WujieVueRendererAdapter fileId="13a9dmbz" projectId="22" />
</template>
```
### react 项目接入
```bash
pnpm i @sy/wujie-react-renderer-adapter@latest --save
# or 或者
npm i @sy/wujie-react-renderer-adapter@latest --save
```
```jsx
import WujieReactRendererAdapter from '@sy/wujie-react-renderer-adapter';
return <WujieReactRendererAdapter fileId="13a9dmbz" projectId="22" />;
```
## API 参考
- 6.1 Props 参数详解
- 6.2 事件监听与回调
- 6.3 实例方法
- 6.4 拦截器使用
## 故障排除
- 常见错误及解决方案
- 日志与调试
- 悦码的日志输出一般在控制台中有 `console.ts 40` 的源码位置标记
- 兼容性问题处理
- renderer-adapter 是默认使用无界微应用来加载悦码渲染器应用的,这种集成方式会让悦码与你的父应用有更深的上下文结合和交互,但有一定的兼容性问题,当出现你无法解决的兼容性问题时,你可以手动设置 `degrade``false`,这将开启传统降级渲染,使用无界 iframe 加载悦码渲染器应用若还不行可摇人处理王雪峰sy3570
- 性能问题诊断
- 悦码渲染器内部使用了 sentry 上报错误,你可以跟 徐川sy0182 申请对应警告邮箱的使用权,获取报错邮件
- 也可以加到悦码渲染器的报错沟通群,跟进自己应用的报错推送
![sentry.dashboard](https://cms-1256453865.cos.ap-shanghai.myqcloud.com/y-code/20250324/企业微信截图_1742796499189.png)
![报错沟通群](https://cms-1256453865.cos.ap-shanghai.myqcloud.com/y-code/20250324/企业微信截图_17427961669787.png)
![sentry 邮箱](https://cms-1256453865.cos.ap-shanghai.myqcloud.com/y-code/20250320/企业微信截图_20250320192100.png)

View File

@@ -1,53 +0,0 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
sidebar: false
hero:
name: y-code 悦码
text: 低代码管理平台
tagline: 全新升级,打开即用,简单高效
image:
src: https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp
alt: 悦码
actions:
- theme: brand
text: 快速开始 ->
link: /guide/introduction/platform
- theme: alt
text: 立即体验 ->
link: https://y-code.shiyue.com
features:
- icon: 🚀
title: 最新技术栈
details: 基于 Vue3、Pinia、Vue Router、TypeScript、等最新技术栈。
link: /guide/essentials/concept
linkText: 基础概念
- icon: 📚
title: 低学习成本
details: 专为前端开发者设计无需改变您熟悉的前端开发流程和编码习惯。只需了解Vue即可轻松上手实现无缝对接真正做到零学习成本。
- icon: 🛠️
title: 自由个性化
details: 悦码设计器支持源码级别的自定义,可轻松适配个性化需求,理论上写代码开发能实现的在设计器上都能完成。
---
<!-- <script setup>
import {
VPTeamPage,
VPTeamPageTitle,
VPTeamMembers,
VPTeamPageSection
} from 'vitepress/theme';
</script>
<VPTeamPage>
<VPTeamPageTitle>
<template #title>
核心成员介绍
</template>
</VPTeamPageTitle>
</VPTeamPage> -->
<!-- <VbenContributors /> -->

View File

@@ -1 +0,0 @@
物料

View File

@@ -1 +0,0 @@
渲染器

View File

@@ -1,20 +0,0 @@
{
"$schema": "https://turbo.build/schema.json",
"ui": "tui",
"globalDependencies": ["pnpm-lock.yaml"],
"globalEnv": ["NODE_ENV"],
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"build:staging": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"preview": {
"dependsOn": ["build"]
}
},
"extends": ["//"]
}

View File

@@ -1,37 +0,0 @@
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 = 'development'
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
VITE_BASE_URL = /
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
VITE_PORT=10010
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'

View File

@@ -1,17 +0,0 @@
# 只在预发布模式中被载入
VITE_NODE_ENV = 'development'
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
VITE_BASE_URL = /
# base api url
VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
VITE_DEBUG_MODE = true
VITE_PORT=10010
VITE_PLATFORM_URL = 'https://localhost:10010'
VITE_DESIGNER_URL = 'https://localhost:10011'
VITE_RENDERER_URL = 'https://localhost:10012'
VITE_V1_URL = 'https://localhost:10013'

View File

@@ -1,3 +1,4 @@
# 端口号
VITE_PORT=10010
VITE_BASE=/
@@ -26,7 +27,7 @@ VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.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'
VITE_PLATFORM_URL = 'https://localhost:10010/'
VITE_DESIGNER_URL = 'https://localhost:10011/'
VITE_RENDERER_URL = 'https://localhost:10012/'
VITE_V1_URL = 'https://localhost:10013/'

View File

@@ -27,7 +27,7 @@ VITE_BASE_URL = /
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
VITE_PLATFORM_URL = 'https://y-code.shiyue.com/'
VITE_DESIGNER_URL = 'https://y-code-designer.shiyue.com/'
VITE_RENDERER_URL = 'https://y-code-renderer.shiyue.com/'
VITE_V1_URL = 'https://custom-chart.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/'

View File

@@ -7,7 +7,7 @@ VITE_BASE_URL = /
# base api url
VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
VITE_PLATFORM_URL = 'https://y-code-pre.shiyue.com/'
VITE_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/'
VITE_V1_URL = 'https://custom-chart.shiyue.com/'
Y_CODE_V1_URL = 'https://custom-chart.shiyue.com/'

View File

@@ -1,24 +0,0 @@
# @sy/y-code-platform
## 1.0.2
### Patch Changes
- Updated dependencies
- @sy/wujie-vue3-renderer-adapter@1.0.2
## 1.0.1
### Patch Changes
- 天梯登陆接入内部用户信息
## 1.0.0
### Patch Changes
- project changeset init
- Updated dependencies
- @sy/wujie-vue3-renderer-adapter@1.0.0
- @sy/vue3-renderer-adapter@1.0.0
- @sy/web-vitals@1.0.0

View File

@@ -14,9 +14,22 @@
<!-- 由 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="low-code-platform"></div>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@@ -1,6 +1,6 @@
{
"name": "@sy/y-code-platform",
"version": "1.0.2",
"version": "1.0.0-alpha.1",
"private": true,
"author": {
"name": "wangxuefeng",
@@ -8,12 +8,9 @@
},
"type": "module",
"scripts": {
"build": "vite build --mode production",
"build:analyze": "vite build --mode analyze",
"build:staging": "vite build --mode staging",
"dev": "vite --mode development",
"dev:staging": "vite --mode dev-staging",
"dev:prod": "vite --mode dev-production",
"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"
},
@@ -22,9 +19,6 @@
},
"dependencies": {
"@sy/unified-login": "1.0.29",
"@sy/vue3-renderer-adapter": "workspace:*",
"@sy/web-vitals": "workspace:*",
"@sy/wujie-vue3-renderer-adapter": "workspace:*",
"@vben/access": "workspace:*",
"@vben/common-ui": "workspace:*",
"@vben/constants": "workspace:*",
@@ -46,11 +40,9 @@
"pinia": "catalog:",
"postmate": "1.5.2",
"vue": "catalog:",
"vue-router": "catalog:",
"wujie-vue3": "catalog:"
"vue-router": "catalog:"
},
"devDependencies": {
"@types/postmate": "catalog:",
"unplugin-element-plus": "catalog:",
"vite-plugin-mkcert": "catalog:"
}

View File

@@ -6,7 +6,7 @@ import { ElConfigProvider } from 'element-plus';
import { elementLocale } from '#/locales';
import { useUserStore } from '#/store/user';
defineOptions({ name: 'YCode' });
defineOptions({ name: 'App' });
useElementPlusDesignTokens();

View File

@@ -10,7 +10,6 @@ import '@vben/styles/ele';
import { useTitle } from '@vueuse/core';
import { ElLoading } from 'element-plus';
// import WujieVue from 'wujie-vue3';
import { $t, setupI18n } from '#/locales';
@@ -30,7 +29,6 @@ async function bootstrap(namespace: string) {
// zIndex: 2000,
// });
const app = createApp(App);
// app.use(WujieVue);
// 注册Element Plus提供的v-loading指令
app.directive('loading', ElLoading.directive);
@@ -69,7 +67,7 @@ async function bootstrap(namespace: string) {
}
});
app.mount('#low-code-platform');
app.mount('#app');
}
export { bootstrap };

View 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>

View File

@@ -1,31 +0,0 @@
<script setup lang="ts">
import WujieVueRendererAdapter from '@sy/wujie-vue3-renderer-adapter';
import axios from 'axios';
import { useUserStore } from '#/store/user';
const props = defineProps<{
[key: string]: any;
fileId: string;
projectId: number;
}>();
const userStore = useUserStore();
const instance = axios.create({});
instance.interceptors.request.use(
(config) => {
config.headers.Authorization = `Bearer ${userStore.token}`;
return config;
},
(error) => Promise.reject(error),
);
</script>
<template>
<WujieVueRendererAdapter
v-bind="props"
:interceptors="instance.interceptors"
/>
</template>

View File

@@ -16,6 +16,7 @@ export const updateApplication = async (id: string, data: any) => {
};
export const deleteApplication = async (id: string) => {
console.log(id);
const response = await instance.delete(`/api/v1/applications/${id}`);
return response.data;
};

View File

@@ -29,7 +29,7 @@ instance.interceptors.response.use(
if (response.data.code === 401) {
const userStore = useUserStore();
console.log('用户未授权或登录已过期,即将跳转...');
userStore.logout();
// userStore.logout();
// 返回一个永远不会resolve的Promise防止后续代码执行
return new Promise(() => {});
}

View File

@@ -1,4 +1,4 @@
// @ts-ignore 天梯没有定义 types
// @ts-ignore
import AxiosAppClient from '@sy/unified-login/es/app-client/axios';
export type Env = 'dev' | 'pre' | 'prod' | 'test';

View File

@@ -1,6 +1,6 @@
import instance from './instance';
export const login = async (data: { password: string; username: string }) => {
export const login = async (data: { username: string; password: string }) => {
const response = await instance.post('/login', data);
return response.data;
};

View File

@@ -124,10 +124,10 @@ watch(
<BasicLayout @clear-preferences-and-logout="handleLogout">
<template #user-dropdown>
<UserDropdown
:menus="menus"
:avatar="avatar"
:text="userStore.userInfo?.alias"
:description="userStore.userInfo?.username"
:avatar
:menus
:text="userStore.userInfo?.realName"
description="ann.vben@gmail.com"
tag-text="Pro"
@logout="handleLogout"
/>

View File

@@ -3,8 +3,9 @@ import { unmountGlobalLoading } from '@vben/utils';
import { overridesPreferences } from './preferences';
// import '@sy/web-vitals';
/**
* 应用初始化完成之后再进行页面加载渲染
*/
async function initApplication() {
// name用于指定项目唯一标识
// 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据

View File

@@ -16,6 +16,8 @@ const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue');
console.log('pageMap', pageMap);
const layoutMap: ComponentRecordType = {
BasicLayout,
IFrameView,

View File

@@ -95,6 +95,7 @@ function setupAccessGuard(router: Router) {
// 当前登录用户拥有的角色标识列表
// const userInfo = userStore.userInfo || (await authStore.fetchUserInfo());
const userInfo = userStore.userInfo;
console.log('userInfo', userInfo);
const userRoles = userInfo?.roles ?? [];
// 生成菜单和路由
const { accessibleMenus, accessibleRoutes } = await generateAccess({
@@ -113,8 +114,7 @@ function setupAccessGuard(router: Router) {
// ? userInfo.homePath || DEFAULT_HOME_PATH
// : to.fullPath)) as string;
// const redirectPath = DEFAULT_HOME_PATH;
const redirectPath = '/example/echart';
const redirectPath = DEFAULT_HOME_PATH;
return {
...router.resolve(decodeURIComponent(redirectPath)),

View File

@@ -9,6 +9,8 @@ import { resetStaticRoutes } from '@vben/utils';
import { createRouterGuard } from './guard';
import { routes } from './routes';
console.log('routes', routes);
/**
* @zh_CN 创建vue-router实例
*/
@@ -26,7 +28,7 @@ const router = createRouter({
return to.hash ? { behavior: 'smooth', el: to.hash } : { left: 0, top: 0 };
},
// 是否应该禁止尾部斜杠。
strict: true,
// strict: true,
});
const resetRoutes = () => resetStaticRoutes(router, routes);

View File

@@ -1,5 +1,7 @@
import type { RouteRecordRaw } from 'vue-router';
import { DEFAULT_HOME_PATH } from '@vben/constants';
import { BasicLayout } from '#/layouts';
/** 全局404页面 */
@@ -30,8 +32,7 @@ const coreRoutes: RouteRecordRaw[] = [
},
name: 'Root',
path: '/',
// redirect: DEFAULT_HOME_PATH,
redirect: '/example/echart',
redirect: DEFAULT_HOME_PATH,
children: [],
},
// {

View File

@@ -1,7 +1,10 @@
import type { RouteRecordRaw } from 'vue-router';
import Renderer from '#/components/renderer/index.vue';
import { isDevMode, LOW_CODE_PROJECT_ID, VITE_RENDERER_URL } from '#/constants';
import { VITE_RENDERER_URL } from '#/constants';
import {
LOW_CODE_APPLICATION_ID,
LOW_CODE_PROJECT_ID,
} from '#/constants/low-code';
const moduleName = 'acl';
@@ -11,45 +14,29 @@ const routes: Array<RouteRecordRaw> = [
name: moduleName,
redirect: '/acl/list',
meta: {
hideInMenu: !isDevMode,
title: '用户管理',
title: '权限管理',
icon: 'ant-design:user-outlined',
},
children: [
{
path: 'list',
name: 'AclList',
name: `${moduleName}-list`,
meta: {
hideInMenu: true,
title: '权限列表',
keepAlive: true,
icon: 'ant-design:list',
app: {
url: VITE_RENDERER_URL,
name: 'y-code-platform-project-list',
// sync: true,
// alive: true,
// degrade: true,
applicationId: LOW_CODE_APPLICATION_ID,
projectId: LOW_CODE_PROJECT_ID,
fileId: '1hsd0407hf',
},
},
component: Renderer,
props: {
url: `${VITE_RENDERER_URL}`,
accessToken: localStorage.getItem('y-code-access-token'),
fileId: '1hsd0407hf',
projectId: LOW_CODE_PROJECT_ID,
degrade: false,
},
},
{
path: 'user',
name: 'AclUser',
meta: {
title: '用户列表',
keepAlive: true,
icon: 'ant-design:list',
},
component: Renderer,
props: {
url: `${VITE_RENDERER_URL}`,
accessToken: localStorage.getItem('y-code-access-token'),
fileId: '7pfu5radx',
projectId: LOW_CODE_PROJECT_ID,
degrade: false,
},
component: () => import('#/components/renderer-adapter/index.vue'),
},
],
},

View File

@@ -1,41 +1,38 @@
import type { RouteRecordRaw } from 'vue-router';
import Renderer from '#/components/renderer/index.vue';
import { LOW_CODE_PROJECT_ID, VITE_RENDERER_URL } from '#/constants';
import { router } from '#/router';
import { VITE_RENDERER_URL } from '#/constants';
// 微前端路由
const moduleName = 'application';
const routes: Array<RouteRecordRaw> = [
{
path: '/application',
name: 'Application',
name: moduleName,
meta: {
title: '应用管理',
icon: 'ant-design:appstore-outlined',
hideInMenu: true,
},
children: [
{
path: 'list',
name: 'ApplicationList',
name: `${moduleName}-list`,
meta: {
title: '应用列表',
keepAlive: false,
keepAlive: true,
icon: 'ant-design:list',
},
component: Renderer,
props: (route) => {
return {
url: `${VITE_RENDERER_URL}`,
accessToken: localStorage.getItem('y-code-access-token'),
app: {
url: VITE_RENDERER_URL,
name: 'y-code-platform-application-list',
// sync: true,
// alive: true,
// degrade: true,
applicationId: 0,
projectId: 4,
fileId: 'b91n1y9yr',
projectId: LOW_CODE_PROJECT_ID,
router,
getRouter: () => router,
route,
degrade: false,
height: '100%',
};
},
},
component: () => import('#/components/renderer-adapter/index.vue'),
},
],
},

View File

@@ -22,15 +22,15 @@ const routes: RouteRecordRaw[] = [
title: $t('page.dashboard.analytics'),
},
},
// {
// name: 'Workspace',
// path: '/workspace',
// component: () => import('#/views/dashboard/workspace/index.vue'),
// meta: {
// icon: 'carbon:workspace',
// title: $t('page.dashboard.workspace'),
// },
// },
{
name: 'Workspace',
path: '/workspace',
component: () => import('#/views/dashboard/workspace/index.vue'),
meta: {
icon: 'carbon:workspace',
title: $t('page.dashboard.workspace'),
},
},
],
},
];

View File

@@ -1,52 +0,0 @@
import type { RouteRecordRaw } from 'vue-router';
import Renderer from '#/components/renderer/index.vue';
import { VITE_RENDERER_URL } from '#/constants';
const routes: Array<RouteRecordRaw> = [
{
path: '/example',
name: 'Example',
redirect: '/example/echart',
meta: {
title: '示例',
icon: 'ant-design:edit-outlined',
},
children: [
{
path: '/example/echart',
name: 'Echart',
meta: {
// 移除 hideInMenu: true 或将其设置为 false
hideInMenu: false,
title: 'Echart 图表',
icon: 'ant-design:list',
},
component: Renderer,
props: {
url: `${VITE_RENDERER_URL}`,
fileId: '13a9dmbz',
projectId: 22,
},
},
{
path: '/example/table',
name: 'Table',
meta: {
// 移除 hideInMenu: true 或将其设置为 false
hideInMenu: false,
title: 'Table 表格',
icon: 'ant-design:list',
},
component: Renderer,
props: {
url: `${VITE_RENDERER_URL}`,
fileId: '13a9dmbz',
projectId: 22,
},
},
],
},
];
export default routes;

View File

@@ -1,77 +1,53 @@
import type { RouteRecordRaw } from 'vue-router';
import RendererAdapter from '@sy/vue3-renderer-adapter';
import { VITE_DESIGNER_URL, VITE_V1_URL } from '#/constants';
import {
isDevMode,
LOW_CODE_PROJECT_ID,
VITE_DESIGNER_URL,
VITE_V1_URL,
} from '#/constants';
const moduleName = 'micro';
const routes: RouteRecordRaw[] = [
const routes: Array<RouteRecordRaw> = [
{
path: '/micro',
name: 'Micro',
name: moduleName,
meta: {
title: '微应用容器',
icon: 'ant-design:appstore-outlined',
hideInMenu: !isDevMode,
},
children: [
{
path: 'admin-designer',
name: 'AdminDesigner',
path: 'designer',
name: `${moduleName}-designer`,
meta: {
hideInMenu: !isDevMode,
title: '平台设计器',
title: '低代码编辑器',
keepAlive: true,
icon: 'ant-design:edit-outlined',
app: {
url: VITE_DESIGNER_URL,
name: 'y-code-designer',
projectId: 4,
sync: true,
alive: true,
degrade: true,
},
},
component: RendererAdapter,
props: (route) => {
return {
url: `${VITE_DESIGNER_URL}`,
projectId: LOW_CODE_PROJECT_ID,
name: 'admin-designer',
accessToken: localStorage.getItem('y-code-access-token'),
route,
};
},
},
{
path: 'y-code-designer',
name: 'YCodeDesigner',
meta: {
hideInMenu: true,
title: '低代码设计器',
icon: 'ant-design:edit-outlined',
},
component: RendererAdapter,
props: (route) => {
return {
url: `${VITE_DESIGNER_URL}`,
projectId: route.query.projectId,
name: `y-code-designer-${route.params.projectId}`,
route,
accessToken: localStorage.getItem('y-code-access-token'),
};
},
component: () => import('#/components/renderer-adapter/index.vue'),
},
{
path: 'y-code-v1',
name: 'YCodeV1',
name: `${moduleName}-y-code-v1`,
meta: {
keepAlive: false,
title: '悦码 1.0',
keepAlive: true,
// hideInMenu: true,
icon: 'ant-design:delete-outlined',
app: {
url: VITE_V1_URL,
name: 'y-code-v1',
// sync: true,
// alive: true,
degrade: true,
},
},
component: RendererAdapter,
props: () => {
return {
url: `${VITE_V1_URL}`,
accessToken: localStorage.getItem('y-code-access-token'),
};
},
component: () => import('#/components/renderer-adapter/index.vue'),
},
],
},

View File

@@ -1,8 +1,10 @@
import type { RouteRecordRaw } from 'vue-router';
import Renderer from '#/components/renderer/index.vue';
import { LOW_CODE_PROJECT_ID, VITE_RENDERER_URL } from '#/constants';
import { router } from '#/router';
import { VITE_RENDERER_URL } from '#/constants';
import {
LOW_CODE_APPLICATION_ID,
LOW_CODE_PROJECT_ID,
} from '#/constants/low-code';
// 微前端路由
const moduleName = 'project';
@@ -12,52 +14,49 @@ const routes: Array<RouteRecordRaw> = [
path: '/project',
name: moduleName,
meta: {
// hideInMenu: true,
title: '项目管理',
icon: 'ant-design:appstore-outlined',
redirect: '/project/list',
},
children: [
{
path: 'list',
name: 'ProjectList',
name: `${moduleName}-list`,
meta: {
title: '项目列表',
keepAlive: true,
icon: 'ant-design:list',
// hideInMenu: true,
},
component: Renderer,
props: (route) => {
return {
url: `${VITE_RENDERER_URL}`,
accessToken: localStorage.getItem('y-code-access-token'),
fileId: '4g4mz6qi8u',
app: {
url: VITE_RENDERER_URL,
name: 'y-code-platform-project-list',
// sync: true,
// alive: true,
// degrade: true,
applicationId: LOW_CODE_APPLICATION_ID,
projectId: LOW_CODE_PROJECT_ID,
router,
route,
};
fileId: '4g4mz6qi8u',
},
},
component: () => import('#/components/renderer-adapter/index.vue'),
},
{
path: 'DSLFileList',
name: 'DSLFileList',
path: 'file',
name: `${moduleName}-file`,
meta: {
hideInMenu: true,
title: 'dsl 文件列表',
keepAlive: true,
icon: 'ant-design:file',
},
component: Renderer,
props: (route) => {
return {
url: `${VITE_RENDERER_URL}`,
accessToken: localStorage.getItem('y-code-access-token'),
fileId: '45ucatjys',
app: {
url: VITE_RENDERER_URL,
name: 'y-code-platform-project-file',
// sync: true,
// alive: true,
// degrade: true,
applicationId: LOW_CODE_APPLICATION_ID,
projectId: LOW_CODE_PROJECT_ID,
getRouter: () => router,
degrade: false,
route,
};
fileId: '7pftwojzu',
},
},
component: () => import('#/components/renderer-adapter/index.vue'),
},
],
},

View File

@@ -1,33 +1,39 @@
import type { RouteRecordRaw } from 'vue-router';
import Renderer from '#/components/renderer/index.vue';
import { VITE_RENDERER_URL } from '#/constants';
import { router } from '#/router';
import {
LOW_CODE_APPLICATION_ID,
LOW_CODE_PROJECT_ID,
} from '#/constants/low-code';
const routes: RouteRecordRaw[] = [
// 微前端路由
const moduleName = 'static-file';
const routes: Array<RouteRecordRaw> = [
{
path: '/static-file',
name: 'StaticFile',
name: moduleName,
meta: {
icon: 'ant-design:file',
title: '静态文件管理',
icon: 'ant-design:file',
},
children: [
{
path: '/static-file/list',
name: 'StaticFileList',
component: Renderer,
path: 'list',
name: `${moduleName}-list`,
meta: {
icon: 'ant-design:file-text',
title: '静态文件列表',
keepAlive: false,
icon: 'ant-design:file',
app: {
url: VITE_RENDERER_URL,
name: 'y-code-platform-application-list',
applicationId: LOW_CODE_APPLICATION_ID,
projectId: LOW_CODE_PROJECT_ID,
fileId: '7pfr394d6',
},
},
props: {
url: `${VITE_RENDERER_URL}`,
fileId: '7pfr394d6',
projectId: 4,
name: '7pfr394d6',
getRouter: () => router,
},
component: () => import('#/components/renderer-adapter/index.vue'),
},
],
},

View File

@@ -58,8 +58,8 @@ const routes: RouteRecordRaw[] = [
// ],
// },
{
name: 'AdminAbout',
path: '/admin/about',
name: 'VbenAbout',
path: '/vben-admin/about',
component: () => import('#/views/_core/about/index.vue'),
meta: {
icon: 'lucide:copyright',

View File

@@ -34,6 +34,7 @@ export const useUserStore = defineStore(
setTimeout(() => {
getCurrentUser().then((res) => {
userInfo.value = res.data.data;
console.log('userInfo', userInfo.value);
});
}, 1000);
}

View File

@@ -1,26 +0,0 @@
{
"$schema": "https://turbo.build/schema.json",
"ui": "tui",
"globalDependencies": ["pnpm-lock.yaml"],
"globalEnv": ["NODE_ENV"],
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"build:staging": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"preview": {
"dependsOn": ["build"]
},
"dev": {
"dependsOn": ["^build"],
"outputs": [],
"cache": false,
"persistent": true
}
},
"extends": ["//"]
}

View File

@@ -14,7 +14,6 @@ const __APP_INFO__ = {
export default defineConfig(async ({ mode }) => {
const env = loadEnv(mode, process.cwd());
const isDev = env.VITE_NODE_ENV === 'development';
return {
application: {},
define: {
@@ -24,7 +23,7 @@ export default defineConfig(async ({ mode }) => {
},
vite: {
plugins: [
isDev && mkcert(),
mkcert(),
ElementPlus({
format: 'esm',
}),
@@ -32,7 +31,6 @@ export default defineConfig(async ({ mode }) => {
server: {
http2: true,
https: true,
port: isDev ? Number(env.VITE_PORT) : undefined,
proxy: {
'/api': {
changeOrigin: true,

View File

@@ -1,11 +0,0 @@
# 只在生产模式中被载入
VITE_NODE_ENV = 'analyze'
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
VITE_BASE_URL = /
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
VITE_PLATFORM_URL = 'https://y-code.shiyue.com/'
VITE_DESIGNER_URL = 'https://y-code-designer.shiyue.com/'
VITE_RENDERER_URL = 'https://y-code-renderer.shiyue.com/'

View File

@@ -1,15 +0,0 @@
# 只在生产模式中被载入
VITE_NODE_ENV = 'development'
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
VITE_BASE_URL = /
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
VITE_DEBUG_MODE = true
VITE_PORT = 10012
VITE_PLATFORM_URL = 'https://localhost:10010'
VITE_DESIGNER_URL = 'https://localhost:10011'
VITE_RENDERER_URL = 'https://localhost:10012'

View File

@@ -1,16 +0,0 @@
# 只在预发布模式中被载入
VITE_NODE_ENV = 'development'
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
VITE_BASE_URL = /
# 端口
VITE_PORT = 10012
# base api url
VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
VITE_DEBUG_MODE = true
VITE_PLATFORM_URL = 'https://localhost:10010'
VITE_DESIGNER_URL = 'https://localhost:10011'
VITE_RENDERER_URL = 'https://localhost:10012'

View File

@@ -4,6 +4,7 @@ VITE_NODE_ENV = 'development'
# 公共基础路径, 详见: https://cn.vitejs.dev/guide/build.html#public-base-path
VITE_BASE_URL = /
# 前端可见变量(必须以 VITE_ 开头)
VITE_PORT = 10012
# VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
@@ -11,6 +12,6 @@ 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_PLATFORM_URL = 'https://localhost:10010/'
VITE_DESIGNER_URL = 'https://localhost:10011/'
VITE_RENDERER_URL = 'https://localhost:10012/'

View File

@@ -6,6 +6,6 @@ VITE_BASE_URL = /
VITE_BASE_API_URL = 'https://custom-chart-api.shiyuegame.com/'
VITE_PLATFORM_URL = 'https://y-code.shiyue.com/'
VITE_DESIGNER_URL = 'https://y-code-designer.shiyue.com/'
VITE_RENDERER_URL = 'https://y-code-renderer.shiyue.com/'
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/'

View File

@@ -10,6 +10,6 @@ VITE_PORT = 10010
# base api url
VITE_BASE_API_URL = 'https://custom-chart-pre-api.shiyue.com/'
VITE_PLATFORM_URL = 'https://y-code-pre.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/'

View File

@@ -1,7 +0,0 @@
# @sy/y-code-renderer
## 1.0.0
### Patch Changes
- project changeset init

View File

@@ -0,0 +1,39 @@
import path from 'node:path';
import { defineConfig, loadEnv } from '@farmfe/core';
import vue from '@vitejs/plugin-vue';
import mkcert from 'vite-plugin-mkcert';
// @ts-ignore
export default defineConfig(({ mode }) => {
console.log('mode', mode);
const env = loadEnv(mode, process.cwd(), ['VITE_', 'Y_CODE_']);
return {
server: {
port: Number(env.VITE_PORT),
cors: true,
},
// @ts-ignore coding
vitePlugins: [vue(), mkcert({ source: 'coding' })],
compilation: {
resolve: {
alias: {
'@': path.resolve(process.cwd(), 'src'),
$vtj: path.resolve(process.cwd(), '.vtj'),
},
},
define: {
// 注入环境变量到客户端
'process.env': JSON.stringify(env),
},
// output: {
// path: path.resolve(process.cwd(), "../../dist/renderer"),
// clean: true,
// },
script: {
target: 'es2022',
},
},
};
});

View File

@@ -4,25 +4,11 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<title>悦码渲染器</title>
<title>Farm + Vue3 + TS</title>
</head>
<body>
<div id="y-code-renderer" style="width: 100%; height: 100%"></div>
<script type="module" src="/src/index.ts"></script>
<!-- Google tag (gtag.js) -->
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-LPQRRS1VVF"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-LPQRRS1VVF');
</script>
<div id="y-code-renderer"></div>
<script src="./src/index.ts"></script>
</body>
</html>

View File

@@ -3,43 +3,41 @@
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite dev --mode development",
"dev:staging": "vite dev --mode dev-staging",
"dev:prod": "vite dev --mode dev-production",
"build": "vite build --mode production",
"build:staging": "vite build --mode staging",
"build:dev": "vite build --mode development",
"build:analyze": "vite build --mode analyze",
"preview": "vite preview",
"typecheck": "vue-tsc --noEmit --skipLibCheck"
"dev": "farm dev --mode development",
"start": "farm start --mode production",
"build": "farm build --mode production",
"build:staging": "farm build --mode staging",
"preview": "farm preview",
"clean:lock": "rimraf pnpm-lock.yaml && rimraf package.lock.json",
"clean:lib": "rimraf node_modules",
"test": "echo 'test",
"clean": "rimraf node_modules"
},
"dependencies": {
"@sentry/vue": "^9.7.0",
"@tanstack/vue-query": "^5.69.0",
"@vtj/charts": "^0.11.12",
"@vtj/core": "^0.11.12",
"@vtj/icons": "0.11.12",
"@vtj/materials": "^0.11.12",
"@vtj/pro": "^0.11.12",
"@vtj/renderer": "^0.11.12",
"@vtj/ui": "^0.11.12",
"@vtj/utils": "^0.11.12",
"@vtj/web": "^0.11.12",
"ant-design-vue": "catalog:",
"@iframe-resizer/child": "^5.3.3",
"@sy/web-vitals": "workspace:*",
"@tanstack/vue-query": "^5.66.9",
"@vtj/core": "^0.10.10",
"@vtj/icons": "0.10.10",
"@vtj/materials": "^0.10.10",
"@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": "catalog:",
"core-js": "catalog:",
"core-js": "^3.40.0",
"element-plus": "catalog:",
"licia-es": "catalog:",
"licia-es": "^1.46.0",
"postmate": "catalog:",
"vue": "catalog:",
"vue-router": "catalog:"
"rrweb": "2.0.0-alpha.4",
"vue": "catalog:"
},
"devDependencies": {
"@types/postmate": "catalog:",
"@vitejs/plugin-vue": "catalog:",
"@vtj/cli": "^0.11.2",
"rollup-plugin-visualizer": "5.14.0",
"vite": "catalog:",
"@farmfe/cli": "^1.0.4",
"@farmfe/core": "^1.6.6",
"@vitejs/plugin-vue": "^5.2.1",
"@vtj/cli": "^0.10.2",
"vite-plugin-mkcert": "catalog:"
}
}

View File

@@ -1,452 +1,80 @@
<script setup lang="ts">
import type { AxiosInterceptorManager, AxiosResponse } from 'axios';
import {
getCurrentInstance,
onBeforeUnmount,
onMounted,
provide,
reactive,
ref,
watch,
} from 'vue';
import { useQuery } from '@tanstack/vue-query';
import { jsonp, request } from '@vtj/utils';
import { computed, watch, ref, getCurrentInstance } from 'vue';
import { ElLoading } from 'element-plus';
import Postmate from 'postmate';
import { createProvider } from '@vtj/web';
import { ElLoading, ElMessage } from 'element-plus';
import { isFn } from 'licia-es';
import { useQuery } from '@tanstack/vue-query';
import { LowCodeService } from './service';
interface WujieProps {
interceptors?: {
request: AxiosInterceptorManager<InternalAxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
};
// 必填参数
fileId: string;
projectId: number | string;
// 可选参数
applicationId?: number | string;
name?: string;
[key: string]: any;
}
declare global {
interface Window {
$wujie?: {
bus: {
$emit: (event: string, data?: any) => void;
};
props: WujieProps;
};
}
}
// 定义必要的初始化参数
interface InitParams {
// 必填参数
fileId: string;
projectId: number | string;
// 可选参数
applicationId?: number | string;
[key: string]: any;
}
import { getFile } from './io';
import { request, jsonp } from '@vtj/utils';
// import * as VtjUI from '@vtj/ui'
// 响应式状态
const renderer = ref();
const lowCodeService = new LowCodeService();
const isLoading = ref(true);
const provider = ref(null);
const loadingInstance = ref(null);
const errorMessage = ref('');
const initParams = ref<InitParams | null | WujieProps>(null);
// 判断是否为wujie子应用
const isWujieSubApp = window.$wujie !== undefined;
// Postmate 握手协议
const postmate = new Postmate.Model({
sayHi: (data: any) => {
console.log('sayHi', data);
},
});
// 从URL解析查询参
const getParamsFromUrl = (): Partial<InitParams> => {
const params = new URLSearchParams(window.location.search);
return {
fileId: params.get('fileId') || undefined,
projectId: params.get('projectId') || undefined,
applicationId: params.get('applicationId') || undefined,
};
// 数据模型
const model = {
name: '',
applicationId: -1,
projectId: -1,
fileId: '',
url: '',
accessToken: '',
};
// 按优先级获取初始化参
const getInitParams = (): InitParams | null => {
if (isWujieSubApp && window.$wujie?.props) {
const props: WujieProps = window.$wujie.props;
console.log('WujieProps', props);
if (props.fileId && props.projectId) {
console.log('使用无界初始化渲染器');
return props as WujieProps;
}
}
// 2. 其次从URL参数获取
const urlParams = getParamsFromUrl();
if (urlParams.fileId && urlParams.projectId) {
console.log('使用URL参数初始化渲染器:', urlParams);
return urlParams as InitParams;
}
// 3. 都不满足返回null
console.error('无法获取初始化参数');
errorMessage.value = '无法获取初始化参数请检查无界配置或URL参数';
return null;
};
// 检查参数是否有效
const isValidParams = (params: InitParams | null): params is InitParams => {
return !!params && !!params.fileId && !!params.projectId;
};
// 初始化请求配置
const initRequestConfig = () => {
if (!isWujieSubApp) return console.log('不是无界渲染模式,不进行拦截器合并');
const props = window.$wujie.props;
const mergeRequestInterceptors = () => {
const requestHandlers = props.interceptors?.request?.handlers || [];
requestHandlers.forEach((handler) => {
if (isFn(handler?.fulfilled)) {
request.useRequest(
handler.fulfilled,
handler.rejected,
handler.options,
);
}
});
};
mergeRequestInterceptors();
};
// 显示加载中
const showLoading = (text = '低代码文件加载中...') => {
if (loadingInstance.value) return;
loadingInstance.value = ElLoading.service({ text });
};
// 隐藏加载中
const hideLoading = () => {
if (loadingInstance.value) {
loadingInstance.value.close();
loadingInstance.value = null;
}
};
// 初始化低代码引擎 - 只初始化一次
const initLowCodeEngine = async () => {
// 如果已经初始化过,直接返回
if (provider.value) return provider.value;
// 检查参数是否有效
if (!isValidParams(initParams.value)) {
const error = new Error('缺少必要参数fileId 和 projectId');
errorMessage.value = error.message;
throw error;
}
// 初始化请求配置
initRequestConfig();
try {
const { provider: lowCodeProvider, onReady } = createProvider({
nodeEnv: import.meta.env.NODE_ENV,
service: lowCodeService,
project: { id: Number(initParams.value.projectId) },
adapter: {
request,
jsonp,
},
// 数据查询
const { data: file, isFetching } = useQuery({
queryKey: ['getFile'],
queryFn: async () => {
await postmate.then((parent) => {
parent.emit('some-event', 'y-code-renderer is ready');
Object.assign(model, parent.model);
localStorage.setItem('y-code-access-token', model.accessToken || '');
});
provider.value = { provider: lowCodeProvider, onReady };
return { provider: lowCodeProvider, onReady };
} catch (error) {
console.error('初始化低代码引擎失败:', error);
errorMessage.value = '初始化低代码引擎失败';
ElMessage.error('初始化低代码引擎失败');
return Promise.reject(error);
}
};
// 获取渲染组件
const getRenderComponent = async () => {
if (!isValidParams(initParams.value)) {
errorMessage.value = '缺少必要参数fileId 和 projectId';
return null;
}
isLoading.value = true;
showLoading();
try {
// 1. 确保低代码引擎已初始化
const { provider: lowCodeProvider, onReady } = await initLowCodeEngine();
// 2. 获取渲染组件
return new Promise<any>((resolve) => {
return getFile(model.fileId).then(() => {
request.useRequest((req) => {
req.headers.set('Authorization', `Bearer ${model.accessToken}`);
return req;
});
const { provider, onReady } = createProvider({
nodeEnv: import.meta.env.NODE_ENV,
service: lowCodeService,
project: { id: model.projectId },
adapter: {
request,
jsonp,
},
});
onReady(async () => {
const instance = getCurrentInstance();
instance?.appContext.app.use(lowCodeProvider);
try {
const renderComponent = await lowCodeProvider.getRenderComponent(
initParams.value!.fileId,
);
console.log('渲染组件获取成功');
resolve(renderComponent);
} catch (error) {
console.error('获取渲染组件失败:', error);
errorMessage.value = '获取渲染组件失败';
ElMessage.error('获取渲染组件失败');
resolve(null);
}
instance?.appContext.app.use(provider);
renderer.value = await provider.getRenderComponent(model.fileId);
});
});
} catch (error) {
console.error('获取渲染组件过程出错:', error);
return null;
} finally {
isLoading.value = false;
hideLoading();
}
};
// 使用 useQuery 管理渲染组件
const { data: rendererComponent, isError } = useQuery({
queryKey: [
'getRenderer',
initParams.value?.fileId,
initParams.value?.projectId,
],
queryFn: getRenderComponent,
enabled: false, // 初始不自动执行,改为手动控制
retry: 1, // 失败后重试一次
staleTime: 1000 * 60 * 5, // 5分钟内不重新获取
},
});
// 当组件挂载时,将渲染器组件赋值给 renderer
watch(rendererComponent, (newVal) => {
// 加载状态监控
watch(isFetching, (newVal) => {
if (newVal) {
renderer.value = newVal;
console.log('渲染器组件已更新');
}
});
// 向父应用发送状态消息
const notifyParent = (event: string, data?: any) => {
if (isWujieSubApp && window.$wujie?.bus) {
window.$wujie.bus.$emit(event, data);
}
};
// 创建响应式上下文对象
const contextRef = ref(null);
// 初始化上下文
const initContext = () => {
if (!isValidParams(initParams.value)) return;
contextRef.value = reactive({
...initParams.value,
updateTimestamp: Date.now(),
});
};
// 提供上下文给所有子组件
provide('lowCodeContext', contextRef);
// 添加一个函数来检测 wujie props 的变化并更新上下文
const setupWujiePropsWatcher = () => {
if (!isWujieSubApp) return;
// 获取当前 props 的快照
let prevPropsSnapshot = window.$wujie?.props
? JSON.stringify(window.$wujie.props)
: null;
// 设置定时器定期检查 props 变化
const intervalId = setInterval(() => {
if (!window.$wujie?.props) return;
// 获取最新的 props 并序列化
const currentPropsSnapshot = JSON.stringify(window.$wujie.props);
// 比较是否发生变化
if (currentPropsSnapshot !== prevPropsSnapshot) {
console.log('检测到 wujie props 变化:', window.$wujie.props);
// 更新快照
prevPropsSnapshot = currentPropsSnapshot;
// 解析新的 props
const newProps = JSON.parse(currentPropsSnapshot);
const oldParams = initParams.value;
// 更新 initParams
initParams.value = {
...newProps,
_timestamp: Date.now(),
};
// 如果上下文已初始化,更新上下文
if (contextRef.value) {
// 使用 Object.assign 保持响应式
Object.assign(contextRef.value, {
...newProps,
updateTimestamp: Date.now(),
});
console.log('上下文已更新:', contextRef.value);
// 触发上下文更新事件
if (isWujieSubApp) {
window.$wujie.bus.$emit('context-updated', contextRef.value);
}
}
// 如果核心参数发生变化,重新加载组件
if (
isValidParams(initParams.value) &&
(oldParams?.fileId !== initParams.value.fileId ||
oldParams?.projectId !== initParams.value.projectId)
) {
console.log('核心参数发生变化,重新加载组件');
reloadComponent();
}
}
}, 300);
onBeforeUnmount(() => {
clearInterval(intervalId);
});
};
// 重新加载组件的函数
const reloadComponent = async () => {
if (!isValidParams(initParams.value)) {
errorMessage.value = '缺少必要参数fileId 和 projectId';
if (isWujieSubApp) {
notifyParent('render-fail', errorMessage.value);
}
return;
}
isLoading.value = true;
showLoading('参数已更新,重新加载组件...');
try {
// 如果需要,重置 provider 以强制重新初始化
provider.value = null;
// 重新初始化低代码引擎
await initLowCodeEngine();
// 获取新的渲染组件
const component = await getRenderComponent();
if (component) {
renderer.value = component;
if (isWujieSubApp) {
notifyParent('render-success');
}
} else {
if (isWujieSubApp) {
notifyParent('render-fail', 'Failed to get component');
}
}
} catch (error) {
console.error('重新加载过程出错:', error);
if (isWujieSubApp) {
notifyParent('render-fail', error);
}
} finally {
isLoading.value = false;
hideLoading();
}
};
// 组件挂载后执行初始化
onMounted(async () => {
// 通知父应用已准备就绪如果是wujie子应用
if (isWujieSubApp) {
notifyParent('ready', 'y-code-renderer is ready');
}
// 获取初始化参数
initParams.value = getInitParams();
const paramsValid = isValidParams(initParams.value);
if (!paramsValid) {
errorMessage.value = '缺少必要参数fileId 和 projectId';
if (isWujieSubApp) {
notifyParent('render-fail', errorMessage.value);
}
return;
}
try {
await initLowCodeEngine();
const component = await getRenderComponent();
if (component) {
renderer.value = component;
if (isWujieSubApp) {
notifyParent('render-success');
// 初始化上下文
initContext();
// 设置 wujie props 监听器
setupWujiePropsWatcher();
}
} else {
if (isWujieSubApp) {
notifyParent('render-fail', 'Failed to get component');
}
}
} catch (error) {
console.error('初始化过程出错:', error);
if (isWujieSubApp) {
notifyParent('render-fail', error);
}
ElLoading.service({ text: '低代码文件加载中...' });
} else {
ElLoading.service().close();
}
});
</script>
<template>
<div class="renderer-container">
<component
:is="renderer"
v-if="renderer"
:ctx-props="contextRef"
style="width: 100%; height: 100%"
/>
<div v-else-if="!isValidParams(initParams)" class="error-message">
{{ errorMessage || '缺少必要参数fileId projectId' }}
</div>
<div v-else-if="!isLoading && isError" class="error-message">
{{ errorMessage || '组件加载失败请检查参数和网络连接' }}
</div>
<div style="padding: 20px">
<component :is="renderer" v-if="renderer" />
</div>
</template>
<style scoped>
.renderer-container {
box-sizing: border-box;
width: 100%;
height: 100%;
}
.error-message {
margin-top: 50px;
color: red;
text-align: center;
}
</style>

View File

@@ -1,45 +1,24 @@
import { createApp } from 'vue';
import * as Sentry from '@sentry/vue';
import { VueQueryPlugin } from '@tanstack/vue-query';
import * as VtjCharts from '@vtj/charts';
import { IconsPlugin } from '@vtj/icons';
import * as VtjUI from '@vtj/ui';
import Antd from 'ant-design-vue';
import ElementPlus from 'element-plus';
import App from './App.vue';
import '@sy/web-vitals';
import 'element-plus/dist/index.css';
import '@vtj/ui/dist/style.css';
import './style.css';
const app = createApp(App);
Sentry.init({
app,
dsn: 'https://44939af86b1f2bb9890579556f01204e@o4509037014482944.ingest.de.sentry.io/4509037067173968',
integrations: [
// 异常路径回放
Sentry.replayIntegration(),
// 异常端信息追踪
Sentry.browserTracingIntegration(),
],
// Session Replay
replaysSessionSampleRate: 0.1, // This 1sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});
// 批量注册组件
Object.entries(VtjUI).forEach(([name, component]) => {
app.component(name, component);
});
Object.entries(VtjCharts).forEach(([name, component]) => {
app.component(name, component);
});
app
.use(Antd)
.use(ElementPlus)
.use(IconsPlugin)
.use(VueQueryPlugin)

View File

@@ -1,4 +1,4 @@
import type { BlockSchema } from '@vtj/core';
import { BlockSchema } from '@vtj/core';
import instance from './instance';
@@ -9,7 +9,6 @@ export type LowCodeFileSchema = {
file_path?: string;
project_id: number;
publish: boolean;
published_dsl: BlockSchema;
};
export const getFile = async (id: string): Promise<LowCodeFileSchema> => {

View File

@@ -4,21 +4,40 @@ import { getFile as getLowCodeFile, getProject } from '@/io';
import { ProjectModel } from '@vtj/core';
import { BaseService } from '@vtj/renderer';
let initProject: ProjectModel = {};
export class LowCodeService extends BaseService {
public async getFile(id: string): Promise<BlockSchema> {
console.log('service getFile', id);
return getLowCodeFile(id).then((lowCodeFile) => {
return lowCodeFile.published_dsl
? Promise.resolve(lowCodeFile.published_dsl as BlockSchema)
: Promise.reject(new Error(`dsl 不存在, id: ${id}`));
return lowCodeFile.dsl
? Promise.resolve(lowCodeFile.dsl as BlockSchema)
: Promise.reject(null);
});
}
public async init(project: ProjectSchema) {
// @ts-ignore 忽略错误
console.log('init', project);
initProject = project;
const remoteProject = await getProject(project.id);
const projectModel = new ProjectModel(remoteProject);
const projectDSL = projectModel.toDsl();
console.log('project dsl', projectDSL);
return projectDSL;
console.log('remoteProject', remoteProject);
const model = new ProjectModel(remoteProject);
const dsl = model.toDsl();
return dsl;
}
public saveProject(project: ProjectSchema): Promise<boolean> {
const newProject = {
...project,
...Object.fromEntries(
Object.entries(project)
.filter(([key]) => stringifyFields.includes(key))
.map(([key, value]) => [key, JSON.stringify(value)]),
),
};
updateProject(initProject.id, newProject);
const model = new ProjectModel(newProject);
// storage.save(`project_${model.id}`, model.toDsl());
return Promise.resolve(true);
}
}

Some files were not shown because too many files have changed in this diff Show More