diff --git a/.github/workflows/deploy-cdn.yml b/.github/workflows/deploy-cdn.yml
index 98df2d182f..9e7dd8bde2 100644
--- a/.github/workflows/deploy-cdn.yml
+++ b/.github/workflows/deploy-cdn.yml
@@ -9,12 +9,6 @@ on:
default: true
type: boolean
-env:
- HUAWEI_CLOUD_AK: ${{ secrets.HUAWEI_CLOUD_AK }}
- HUAWEI_CLOUD_SK: ${{ secrets.HUAWEI_CLOUD_SK }}
- HUAWEI_CLOUD_ENDPOINT: ${{ secrets.HUAWEI_CLOUD_ENDPOINT }}
- HUAWEI_CLOUD_BUCKET: ${{ secrets.HUAWEI_CLOUD_BUCKET }}
-
jobs:
check-secrets:
runs-on: ubuntu-latest
@@ -146,12 +140,12 @@ jobs:
- name: Configure and Upload to OBS
run: |
- obsutil config -i=${{ env.HUAWEI_CLOUD_AK }} \
- -k=${{ env.HUAWEI_CLOUD_SK }} \
- -e=${{ env.HUAWEI_CLOUD_ENDPOINT }}
+ obsutil config -i=${{ secrets.HUAWEI_CLOUD_AK }} \
+ -k=${{ secrets.HUAWEI_CLOUD_SK }} \
+ -e=${{ secrets.HUAWEI_CLOUD_ENDPOINT }}
# Upload to versioned path
obsutil cp ./designer-demo/dist \
- obs://${{ env.HUAWEI_CLOUD_BUCKET }}/${{ needs.build.outputs.obs-path }} \
+ obs://${{ secrets.HUAWEI_CLOUD_BUCKET }}/${{ needs.build.outputs.obs-path }} \
-r -f -flat
# If is_latest_release is true, also upload to latest path
@@ -160,9 +154,9 @@ jobs:
find ./designer-demo/dist -type f \( -name "*.html" -o -name "*.js" -o -name "*.mjs" -o -name "*.css" \) \
-exec sed -i "s|${{ needs.build.outputs.cdn-base }}|${{ needs.build.outputs.cdn-base-latest }}|g" {} +
obsutil cp ./designer-demo/dist \
- obs://${{ env.HUAWEI_CLOUD_BUCKET }}/${{ needs.build.outputs.obs-path-latest }} \
+ obs://${{ secrets.HUAWEI_CLOUD_BUCKET }}/${{ needs.build.outputs.obs-path-latest }} \
-r -f -flat
fi
- echo "Uploaded to: obs://${{ env.HUAWEI_CLOUD_BUCKET }}/${{ needs.build.outputs.obs-path }}"
+ echo "Uploaded to: obs://${{ secrets.HUAWEI_CLOUD_BUCKET }}/${{ needs.build.outputs.obs-path }}"
echo "CDN URL: https://res-static.opentiny.design/${{ needs.build.outputs.obs-path }}"
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000000..1598b97b6a
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,120 @@
+# TinyEngine — Repository Instructions for Coding Agents
+
+## Purpose and Scope
+
+This file is the canonical source of truth for repo-wide agent instructions.
+
+- Applies to the whole repository unless a closer `AGENTS.md` overrides it for a subtree.
+- `CLAUDE.md` is a compatibility entrypoint that imports this file. Do not maintain a second independent copy of the same rules.
+- Keep this file limited to repo-wide guidance. Package-specific implementation details belong in package-level instruction files.
+
+## Repository Snapshot
+
+- Monorepo: pnpm workspaces + lerna (independent versioning)
+- Primary stack: Vue 3, Vite, JavaScript/TypeScript
+- Package manager: `pnpm` only for interactive work in this repo
+- Designer app: `designer-demo/`
+- Local mock backend: `mockServer/`
+
+## Working Model
+
+- Inspect the affected package, its `package.json`, and the nearest instruction file before editing.
+- Keep changes scoped. Do not normalize unrelated files or rename fixtures just for consistency.
+- Prefer targeted package-level validation over whole-repo commands when possible.
+- Treat `pnpm lint` and `pnpm format` as mutating commands, not read-only verification.
+- Do not invoke `npm` or `yarn` directly for normal repo work. Existing package scripts may still shell out internally; leave that alone unless the task is specifically about package scripts.
+
+## Common Commands
+
+### Read-mostly commands
+
+```sh
+pnpm install
+pnpm dev
+pnpm build:plugin
+pnpm build:alpha
+pnpm --filter @opentiny/tiny-engine-dsl-vue test:unit
+```
+
+### Mutating commands
+
+```sh
+pnpm lint # ESLint with --fix
+pnpm format # Prettier --write
+```
+
+Canonical script definitions live in:
+
+- `package.json`
+- `packages/*/package.json`
+- `.github/workflows/push-check.yml`
+- `.github/workflows/Release.yml`
+
+## Verification Matrix
+
+Run the smallest sufficient verification for the change surface, then expand if the change is broad or risky.
+
+1. Docs-only changes:
+ No code verification required unless the docs change commands or workflow descriptions that should be checked against source files.
+2. `packages/vue-generator/**`:
+ Run the affected testcase or `pnpm --filter @opentiny/tiny-engine-dsl-vue test:unit`.
+ If generator behavior changes, run the full `test:unit` suite before handoff and inspect any changed `expected/*.vue` files.
+3. Published library packages under `packages/**`:
+ Run the package-local `test` script if one exists.
+ Run `pnpm build:plugin` when build output or published package behavior may be affected.
+4. `designer-demo/**` or shared packages consumed by the demo:
+ Run `pnpm build:alpha`.
+5. Cross-package build or release-facing changes:
+ Run `pnpm build:plugin` and `pnpm build:alpha`.
+6. Config, workspace, CI, or release script changes:
+ Verify the directly affected command(s) after approval.
+
+## Approval Boundaries
+
+### Always OK
+
+- Read any source file
+- Run targeted tests and builds
+- Edit implementation files inside existing packages
+- Add or update tests that match the scope of the change
+- Update docs that reflect current repo behavior
+
+### Ask First
+
+- Changing workspace, lerna, pnpm, ESLint, Prettier, or TypeScript configuration
+- Modifying CI workflows, release scripts, or publish flows
+- Upgrading major dependencies or changing pinned overrides
+- Reordering or adding/removing default vue-generator attribute hooks
+- Large-scale edits to generated mappings or vendored patches
+
+When asking first, include:
+
+- what you want to change
+- why the current rules or implementation are insufficient
+- what verification you would run after approval
+
+### Never
+
+- Use `npm` or `yarn` directly for routine repo commands
+- Skip hooks with `--no-verify`
+- Hardcode versions for workspace packages
+- Edit `patches/` without understanding the upstream issue and the patch purpose
+- Rewrite generated expectations or snapshots without validating the new output first
+
+## Task-Specific Expectations
+
+- Bug fix:
+ Add or update a regression test when behavior changes.
+- Refactor:
+ Preserve behavior and prove it with targeted verification.
+- Snapshot or generated output change:
+ Explain why the output changed and list the affected fixture directories.
+- Commit or PR work:
+ Only do it if asked. Use Conventional Commits and target `develop` unless the user specifies otherwise.
+
+## Gotchas
+
+- `pnpm install` is enforced by `preinstall`; npm and yarn are rejected for direct repo usage.
+- `pnpm lint` writes fixes. Use it deliberately.
+- CI relies on `build:plugin` and `build:alpha`, not only lint or unit tests.
+- Test directories such as `test/`, `expected/`, and `output/` are not always linted; do not treat lint success as fixture validation.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000000..36fb0d736b
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,7 @@
+# TinyEngine — Claude Code Entry
+
+This file is intentionally thin. The canonical repo-wide instructions live in `AGENTS.md`.
+
+@./AGENTS.md
+
+When working inside a subtree that has its own `CLAUDE.md`, follow the closer file as an extension of these repo-wide rules.
diff --git a/designer-demo/engine.config.js b/designer-demo/engine.config.js
index 5f9e5a703d..b773842f19 100644
--- a/designer-demo/engine.config.js
+++ b/designer-demo/engine.config.js
@@ -5,5 +5,7 @@ export default {
scripts: [],
styles: [],
// 是否开启 TailWindCSS 特性
- enableTailwindCSS: true
+ enableTailwindCSS: true,
+ // 是否开启 使用结构化CSS 特性
+ enableStructuredCss: false
}
diff --git a/designer-demo/env/.env.development b/designer-demo/env/.env.development
index 25a3fd1e9d..3d28957eba 100644
--- a/designer-demo/env/.env.development
+++ b/designer-demo/env/.env.development
@@ -5,4 +5,4 @@ VITE_CDN_DOMAIN=https://registry.npmmirror.com
# 使用npmmirror的cdn 时,需要声明 VITE_CDN_TYPE=npmmirror
VITE_CDN_TYPE=npmmirror
# request data via alpha service
-# VITE_ORIGIN=
+# VITE_ORIGIN=
\ No newline at end of file
diff --git a/designer-demo/package.json b/designer-demo/package.json
index e926a0d4cb..abb9f337d0 100644
--- a/designer-demo/package.json
+++ b/designer-demo/package.json
@@ -1,7 +1,7 @@
{
"name": "designer-demo",
"private": true,
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"type": "module",
"scripts": {
"dev": "cross-env vite",
diff --git a/designer-demo/public/mock/bundle.json b/designer-demo/public/mock/bundle.json
index 0495b36964..361479b2b1 100644
--- a/designer-demo/public/mock/bundle.json
+++ b/designer-demo/public/mock/bundle.json
@@ -3,6 +3,1045 @@
"framework": "Vue",
"materials": {
"components": [
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "动作菜单"
+ },
+ "component": "TinyActionMenu",
+ "icon": "dropdown",
+ "description": "动作菜单",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@opentiny/vue",
+ "exportName": "TinyActionMenu",
+ "destructuring": true
+ },
+ "group": "component",
+ "category": "动作菜单",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "cols": 12,
+ "type": "object",
+ "label": {
+ "text": {
+ "zh_CN": "绑定值"
+ }
+ },
+ "widget": {
+ "props": {
+ "height": 150,
+ "language": "json"
+ },
+ "component": "CodeConfigurator"
+ },
+ "disabled": false,
+ "property": "options",
+ "readOnly": false,
+ "required": true,
+ "description": {
+ "zh_CN": "菜单项列表的数据"
+ },
+ "defaultValue": null,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "number",
+ "label": {
+ "text": {
+ "zh_CN": "最大显示数量"
+ }
+ },
+ "widget": {
+ "props": {
+ "step": 2
+ },
+ "component": "NumberConfigurator"
+ },
+ "disabled": false,
+ "property": "maxShowNum",
+ "readOnly": false,
+ "required": false,
+ "description": "最多显示菜单按钮的个数,其他菜单在下拉弹框显示",
+ "defaultValue": 2,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "按钮模式"
+ }
+ },
+ "widget": {
+ "props": {
+ "options": [
+ {
+ "label": "default",
+ "value": "default"
+ },
+ {
+ "label": "card",
+ "value": "card"
+ }
+ ]
+ },
+ "component": "SelectConfigurator"
+ },
+ "disabled": false,
+ "property": "mode",
+ "readOnly": false,
+ "required": false,
+ "description": "菜单按钮模式",
+ "defaultValue": "default",
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "下拉按钮文本"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入..."
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "moreText",
+ "readOnly": false,
+ "required": false,
+ "description": "下拉按钮文本",
+ "defaultValue": "更多",
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "二级下拉面板的显示位置"
+ }
+ },
+ "widget": {
+ "props": {
+ "options": [
+ {
+ "label": "bottom-start",
+ "value": "bottom-start"
+ },
+ {
+ "label": "bottom-end",
+ "value": "bottom-end"
+ }
+ ]
+ },
+ "component": "SelectConfigurator"
+ },
+ "disabled": false,
+ "property": "placement",
+ "readOnly": false,
+ "required": false,
+ "description": "二级下拉面板的显示位置",
+ "defaultValue": "bottom-end",
+ "labelPosition": "top"
+ },
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "show-icon"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "CheckBoxConfigurator"
+ },
+ "disabled": false,
+ "property": "showIcon",
+ "readOnly": false,
+ "required": false,
+ "description": "是否显示下拉触发源图标",
+ "defaultValue": true,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "text-field"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入..."
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "textField",
+ "readOnly": false,
+ "required": false,
+ "description": "菜单按钮文本的键值",
+ "defaultValue": "label",
+ "labelPosition": "left"
+ }
+ ],
+ "description": {
+ "zh_CN": "组件核心功能相关的配置,包括 name、size、type 等核心属性"
+ }
+ },
+ {
+ "name": "1",
+ "label": {
+ "zh_CN": "样式属性"
+ },
+ "content": [
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "按钮间距"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入..."
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "spacing",
+ "readOnly": false,
+ "required": false,
+ "description": "菜单按钮之间的间距",
+ "defaultValue": "5px",
+ "labelPosition": "left"
+ }
+ ],
+ "description": {
+ "zh_CN": "组件外观、颜色、尺寸相关的配置,包括 width、height、backgroundColor、color 等与视觉呈现相关的属性"
+ }
+ }
+ ],
+ "events": {
+ "onItemClick": {
+ "type": "event",
+ "label": {
+ "zh_CN": "菜单项点击"
+ },
+ "description": {
+ "zh_CN": "监听点击菜单项事件"
+ },
+ "defaultValue": "",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "data",
+ "type": "IItemClickParam",
+ "description": {
+ "zh_CN": "点击的菜单项参数数据"
+ },
+ "defaultValue": ""
+ }
+ ],
+ "returns": {
+ "type": "",
+ "description": {
+ "zh_CN": "事件返回值的描述文字"
+ },
+ "defaultValue": ""
+ }
+ }
+ },
+ "onButtonClick": {
+ "type": "event",
+ "label": {
+ "zh_CN": "左侧按钮点击"
+ },
+ "description": {
+ "zh_CN": "监听左侧按钮点击事件,仅 split-button 为 true 时生效"
+ },
+ "defaultValue": "",
+ "functionInfo": {
+ "params": [],
+ "returns": {
+ "type": "",
+ "description": {
+ "zh_CN": "事件返回值的描述文字"
+ },
+ "defaultValue": ""
+ }
+ }
+ },
+ "onVisibleChange": {
+ "type": "event",
+ "label": {
+ "zh_CN": "显隐状态变化"
+ },
+ "description": {
+ "zh_CN": "监听下拉框的显示或隐藏状态"
+ },
+ "defaultValue": "",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "status",
+ "type": "boolean",
+ "description": {
+ "zh_CN": "下拉框的显示或隐藏状态"
+ },
+ "defaultValue": ""
+ }
+ ],
+ "returns": {
+ "type": "",
+ "description": {
+ "zh_CN": "事件返回值的描述文字"
+ },
+ "defaultValue": ""
+ }
+ }
+ }
+ },
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "默认内容"
+ },
+ "description": {
+ "zh_CN": "自定义触发源文本区域。 注意: 必须是一个元素或者或者组件"
+ }
+ },
+ "dropdown": {
+ "label": {
+ "zh_CN": "下拉列表"
+ },
+ "description": {
+ "zh_CN": "自定义下拉列表区域,通常使用 tiny-dropdown-menu 组件"
+ }
+ }
+ }
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
+ {
+ "version": "3.22.0",
+ "name": {
+ "zh_CN": "下拉菜单"
+ },
+ "component": "TinyDropdown",
+ "icon": "dropdown",
+ "description": "下拉菜单",
+ "docUrl": "",
+ "screenshot": "",
+ "tags": "",
+ "keywords": "",
+ "devMode": "proCode",
+ "npm": {
+ "package": "@opentiny/vue",
+ "exportName": "TinyDropdown",
+ "destructuring": true
+ },
+ "group": "component",
+ "category": "下拉菜单",
+ "priority": 2,
+ "schema": {
+ "properties": [
+ {
+ "name": "0",
+ "label": {
+ "zh_CN": "基础属性"
+ },
+ "content": [
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "尺寸"
+ }
+ },
+ "widget": {
+ "props": {
+ "options": [
+ {
+ "label": "medium",
+ "value": "medium"
+ },
+ {
+ "label": "small",
+ "value": "small"
+ },
+ {
+ "label": "mini",
+ "value": "mini"
+ }
+ ]
+ },
+ "component": "SelectConfigurator"
+ },
+ "disabled": false,
+ "property": "size",
+ "readOnly": false,
+ "required": false,
+ "description": "菜单尺寸。注意:只在 split-button为 true 的情况下生效",
+ "defaultValue": null,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "分割按钮"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "CheckBoxConfigurator"
+ },
+ "disabled": false,
+ "property": "split-button",
+ "readOnly": false,
+ "required": false,
+ "description": "下拉触发元素呈现为按钮",
+ "defaultValue": false,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "ibuttontype",
+ "label": {
+ "text": {
+ "zh_CN": "按钮类型"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入..."
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "type",
+ "readOnly": false,
+ "required": false,
+ "description": "按钮类型。注意:只在 split-button 为 true 的情况下有效",
+ "defaultValue": null,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "触发方式"
+ }
+ },
+ "widget": {
+ "props": {
+ "options": [
+ {
+ "label": "hover",
+ "value": "hover"
+ },
+ {
+ "label": "click",
+ "value": "click"
+ },
+ {
+ "label": "contextmenu",
+ "value": "contextmenu"
+ }
+ ]
+ },
+ "component": "SelectConfigurator"
+ },
+ "disabled": false,
+ "property": "trigger",
+ "readOnly": false,
+ "required": false,
+ "description": "触发下拉的方式",
+ "defaultValue": "hover",
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "iplacementtype",
+ "label": {
+ "text": {
+ "zh_CN": "弹出位置"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入..."
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "placement",
+ "readOnly": false,
+ "required": false,
+ "description": "菜单弹出位置",
+ "defaultValue": "bottom-end",
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "显隐状态"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "CheckBoxConfigurator"
+ },
+ "disabled": false,
+ "property": "visible",
+ "readOnly": false,
+ "required": false,
+ "description": "手动控制下拉弹框显隐,优先级高于trigger",
+ "defaultValue": false,
+ "labelPosition": "left"
+ }
+ ],
+ "description": {
+ "zh_CN": "组件核心功能相关的配置,包括 name、size、type 等核心属性"
+ }
+ },
+ {
+ "name": "1",
+ "label": {
+ "zh_CN": "样式属性"
+ },
+ "content": [
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "标题"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入..."
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "title",
+ "readOnly": false,
+ "required": false,
+ "description": "自定义触发源的文本",
+ "defaultValue": "下拉菜单",
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "显示图标"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "SwitchConfigurator"
+ },
+ "disabled": false,
+ "property": "show-icon",
+ "readOnly": false,
+ "required": false,
+ "description": "是否显示下拉触发源图标",
+ "defaultValue": true,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "component",
+ "label": {
+ "text": {
+ "zh_CN": "图标"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入图标名称"
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "suffix-icon",
+ "readOnly": false,
+ "required": false,
+ "description": "下拉触发源图标",
+ "defaultValue": null,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "继承宽度"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "CheckBoxConfigurator"
+ },
+ "disabled": false,
+ "property": "inherit-width",
+ "readOnly": false,
+ "required": false,
+ "description": "下拉弹框的最小宽度是否继承触发源的宽度,默认不继承",
+ "defaultValue": false,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "显示箭头"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "CheckBoxConfigurator"
+ },
+ "disabled": false,
+ "property": "visible-arrow",
+ "readOnly": false,
+ "required": false,
+ "description": "下拉弹框是否显示箭头,默认不显示",
+ "defaultValue": false,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "弹框类名"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入..."
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "popper-class",
+ "readOnly": false,
+ "required": false,
+ "description": "下拉弹框的类名,用于自定义样式",
+ "defaultValue": null,
+ "labelPosition": "left"
+ }
+ ],
+ "description": {
+ "zh_CN": "组件外观、颜色、尺寸相关的配置,包括 width、height、backgroundColor、color 等与视觉呈现相关的属性"
+ }
+ },
+ {
+ "name": "2",
+ "label": {
+ "zh_CN": "行为属性"
+ },
+ "content": [
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "禁用"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "CheckBoxConfigurator"
+ },
+ "disabled": false,
+ "property": "disabled",
+ "readOnly": false,
+ "required": false,
+ "description": "是否禁用",
+ "defaultValue": false,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "点击收起"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "CheckBoxConfigurator"
+ },
+ "disabled": false,
+ "property": "hide-on-click",
+ "readOnly": false,
+ "required": false,
+ "description": "点击菜单项后是否收起菜单。默认点击后收起",
+ "defaultValue": true,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "number",
+ "label": {
+ "text": {
+ "zh_CN": "收起延时"
+ }
+ },
+ "widget": {
+ "props": {
+ "step": 1
+ },
+ "component": "NumberConfigurator"
+ },
+ "disabled": false,
+ "property": "hide-timeout",
+ "readOnly": false,
+ "required": false,
+ "description": "延时多久收起下拉菜单,单位毫秒。注意:仅在 trigger 为 hover 时有效",
+ "defaultValue": 150,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "number",
+ "label": {
+ "text": {
+ "zh_CN": "展开延时"
+ }
+ },
+ "widget": {
+ "props": {
+ "step": 1
+ },
+ "component": "NumberConfigurator"
+ },
+ "disabled": false,
+ "property": "show-timeout",
+ "readOnly": false,
+ "required": false,
+ "description": "延时多久展开下拉菜单,单位毫秒。注意:仅在 trigger 为 hover 时有效",
+ "defaultValue": 250,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "number",
+ "label": {
+ "text": {
+ "zh_CN": "Tab索引"
+ }
+ },
+ "widget": {
+ "props": {
+ "step": 1
+ },
+ "component": "NumberConfigurator"
+ },
+ "disabled": false,
+ "property": "tabindex",
+ "readOnly": false,
+ "required": false,
+ "description": "初始化触发元素的原生属性 tabindex",
+ "defaultValue": 0,
+ "labelPosition": "left"
+ }
+ ],
+ "description": {
+ "zh_CN": "组件交互、事件、状态相关的配置,包括 disabled、loading、onClick 等与用户操作和状态相关的属性"
+ }
+ },
+ {
+ "name": "3",
+ "label": {
+ "zh_CN": "高级属性"
+ },
+ "content": [
+ {
+ "cols": 12,
+ "type": "boolean",
+ "label": {
+ "text": {
+ "zh_CN": "懒加载"
+ }
+ },
+ "widget": {
+ "props": {},
+ "component": "CheckBoxConfigurator"
+ },
+ "disabled": false,
+ "property": "lazy-show-popper",
+ "readOnly": false,
+ "required": false,
+ "description": "是否懒加载下拉菜单及内部的项,以优化性能,默认初始全加载菜单及内部项。",
+ "defaultValue": false,
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "imenuoption",
+ "label": {
+ "text": {
+ "zh_CN": "菜单配置"
+ }
+ },
+ "widget": {
+ "props": {
+ "height": 150,
+ "language": "json"
+ },
+ "component": "CodeConfigurator"
+ },
+ "disabled": false,
+ "property": "menu-options",
+ "readOnly": false,
+ "required": false,
+ "description": "配置式且只使用 tiny-dropdown 组件时使用",
+ "defaultValue": "{ options:[], textField:\"label\", popperClass:\"\", placement:\"bottom-end\" }",
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "iitemdata[]",
+ "label": {
+ "text": {
+ "zh_CN": "菜单项配置"
+ }
+ },
+ "widget": {
+ "props": {
+ "height": 150,
+ "language": "json"
+ },
+ "component": "CodeConfigurator"
+ },
+ "disabled": false,
+ "property": "options",
+ "readOnly": false,
+ "required": false,
+ "description": "通过配置式设置菜单项的属性",
+ "defaultValue": "[]",
+ "labelPosition": "left"
+ },
+ {
+ "cols": 12,
+ "type": "string",
+ "label": {
+ "text": {
+ "zh_CN": "文本字段"
+ }
+ },
+ "widget": {
+ "props": {
+ "placeholder": "请输入..."
+ },
+ "component": "InputConfigurator"
+ },
+ "disabled": false,
+ "property": "text-field",
+ "readOnly": false,
+ "required": false,
+ "description": "菜单项文本的字段,结合 options 属性使用",
+ "defaultValue": "label",
+ "labelPosition": "left"
+ }
+ ],
+ "description": {
+ "zh_CN": "组件可选的专业配置项,包括复杂对象配置、高级功能选项等不常用的特殊配置"
+ }
+ }
+ ],
+ "events": {
+ "onItemClick": {
+ "type": "event",
+ "label": {
+ "zh_CN": "菜单项点击"
+ },
+ "description": {
+ "zh_CN": "监听点击菜单项事件"
+ },
+ "defaultValue": "",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "data",
+ "type": "IItemClickParam",
+ "description": {
+ "zh_CN": "点击的菜单项参数数据"
+ },
+ "defaultValue": ""
+ }
+ ],
+ "returns": {
+ "type": "",
+ "description": {
+ "zh_CN": "事件返回值的描述文字"
+ },
+ "defaultValue": ""
+ }
+ }
+ },
+ "onButtonClick": {
+ "type": "event",
+ "label": {
+ "zh_CN": "左侧按钮点击"
+ },
+ "description": {
+ "zh_CN": "监听左侧按钮点击事件,仅 split-button 为 true 时生效"
+ },
+ "defaultValue": "",
+ "functionInfo": {
+ "params": [],
+ "returns": {
+ "type": "",
+ "description": {
+ "zh_CN": "事件返回值的描述文字"
+ },
+ "defaultValue": ""
+ }
+ }
+ },
+ "onVisibleChange": {
+ "type": "event",
+ "label": {
+ "zh_CN": "显隐状态变化"
+ },
+ "description": {
+ "zh_CN": "监听下拉框的显示或隐藏状态"
+ },
+ "defaultValue": "",
+ "functionInfo": {
+ "params": [
+ {
+ "name": "status",
+ "type": "boolean",
+ "description": {
+ "zh_CN": "下拉框的显示或隐藏状态"
+ },
+ "defaultValue": ""
+ }
+ ],
+ "returns": {
+ "type": "",
+ "description": {
+ "zh_CN": "事件返回值的描述文字"
+ },
+ "defaultValue": ""
+ }
+ }
+ }
+ },
+ "slots": {
+ "default": {
+ "label": {
+ "zh_CN": "默认内容"
+ },
+ "description": {
+ "zh_CN": "自定义触发源文本区域。 注意: 必须是一个元素或者或者组件"
+ }
+ },
+ "dropdown": {
+ "label": {
+ "zh_CN": "下拉列表"
+ },
+ "description": {
+ "zh_CN": "自定义下拉列表区域,通常使用 tiny-dropdown-menu 组件"
+ }
+ }
+ }
+ },
+ "configure": {
+ "loop": true,
+ "condition": true,
+ "styles": true,
+ "isContainer": false,
+ "isModal": false,
+ "nestingRule": {
+ "childWhitelist": "",
+ "parentWhitelist": "",
+ "descendantBlacklist": "",
+ "ancestorWhitelist": ""
+ },
+ "isNullNode": false,
+ "isLayout": false,
+ "rootSelector": "",
+ "shortcuts": {
+ "properties": []
+ },
+ "contextMenu": {
+ "actions": [
+ "create symbol"
+ ],
+ "disable": [
+ "copy",
+ "remove"
+ ]
+ }
+ }
+ },
{
"version": "3.22.0",
"name": {
@@ -26232,6 +27271,76 @@
"node-key": "id"
}
}
+ },
+ {
+ "name": {
+ "zh_CN": "下拉菜单"
+ },
+ "icon": "dropdown",
+ "screenshot": "",
+ "snippetName": "TinyDropdown",
+ "schema": {
+ "componentName": "TinyDropdown",
+ "props": {
+ "menu-options": {
+ "options": [
+ {
+ "name": "老友粉",
+ "disabled": true
+ },
+ {
+ "name": "狮子头",
+ "divided": true
+ },
+ {
+ "name": "黄金糕",
+ "divided": true
+ }
+ ],
+ "textField": "name"
+ }
+ }
+ }
+ },
+ {
+ "name": {
+ "zh_CN": "动作菜单"
+ },
+ "icon": "dropdown",
+ "screenshot": "",
+ "snippetName": "TinyActionMenu",
+ "schema": {
+ "componentName": "TinyActionMenu",
+ "props": {
+ "options": [
+ {
+ "label": "远程登录"
+ },
+ {
+ "label": "开机"
+ },
+ {
+ "label": "关机"
+ },
+ {
+ "label": "重启",
+ "divided": true
+ },
+ {
+ "label": "网络设置",
+ "children": [
+ {
+ "label": "更改安全组"
+ },
+ {
+ "label": "切换 VPC",
+ "divided": true
+ }
+ ]
+ }
+ ]
+ }
+ }
}
]
},
diff --git a/docs/README.md b/docs/README.md
index ca958736c8..bd9ebe4da1 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -95,7 +95,6 @@
- [应用工具类管理](./api/backend-api/app-utility-management.md)
- [区块管理](./api/backend-api/block-management-api.md)
- [数据源管理](./api/backend-api/data-source-management.md)
- - [DSL代码生成](./api/backend-api/dsl-code-generation.md)
- [物料中心](./api/backend-api/material-center.md)
- [页面管理](./api/backend-api/page-management-api.md)
- [APP服务](./api/backend-api/app-services.md)
diff --git a/docs/api/backend-api/dsl-code-generation.md b/docs/api/backend-api/dsl-code-generation.md
deleted file mode 100644
index 1dff789d74..0000000000
--- a/docs/api/backend-api/dsl-code-generation.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# DSL代码生成
-
-## generateCode
-
-
-
-### 基本信息
-
-**Path:** /generateCode
-
-**Method:** GET
-
-**接口描述:**
-
-
作为npm包使用generateCode方法生成代码示例:
-
-const path = require('path')
-const fs = require('fs')
-const { generateCode } = require('@opentiny/tiny-engine-dsl-ng-tiny/lib/generate-code.js')
-
-
-
-const result = generateCode({ pageInfo, blocksData })
-result.forEach((item) => fs.writeFileSync(`dist/${item.filePath}/${item.panelName}`, item.panelValue))
-
-
-输入示例: { pageInfo, blocksData };
-
-// pageInfo为页面的schema信息,
-// pageInfo: { schema, name });
-{
- name: 'page1',
- schema: {
- // 页面schema
- }
-}
-
-
-// blocksData为页面引用的区块的schema数据
-// blocksData: Array<{ label, content }>
-[
- {
- label: 'image-title',
- content: {
- // 区块的schema
- }
- },
- {
- // 其他区块...
- }
-]
-
-
-输出示例:
-[
- {
- "panelName": "page1.component.html", // 文件名
- "panelValue": "xxx", // 生成代码的内容
- "panelType": "html", // 生成代码的文件类型:html、css、ts
- "prettierOpt": { "parser": "html", "tabWidth": 2, "printWidth": 120 }, // prettier格式化选项
- "type": "page", // 生成代码类型:page、block、service
- "filePath": "pages/page1" // 生成代码文件的相对目录路径
- },
- {
- "panelName": "page1.component.ts",
- "panelValue": "xxx",
- "panelType": "ts",
- "prettierOpt": { "parser": "typescript", "tabWidth": 2, "printWidth": 120 },
- "type": "page",
- "filePath": "pages/page1"
- },
- {
- "panelName": "block1.component.ts",
- "type": "block",
- "panelType": "ts",
- "prettierOpt": { "parser": "typescript", "tabWidth": 2, "printWidth": 120 },
- "filePath": "blocks/block1",
- "panelValue": "xxx"
- },
- {
- "panelName": "fetch.service.ts",
- "panelType": "ts",
- "prettierOpt": { "parser": "typescript", "tabWidth": 2, "printWidth": 120 },
- "type": "service",
- "filePath": "service",
- "panelValue": "xxx"
- },
- // ...
-]
-
-
-
-
-### 请求参数
-
-### 返回数据
-
-
-
-
- | 名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
-
- | | object [] | 非必须 | | | item 类型: object |
| ├─ panelName | string | 必须 | | 文件名 | |
| ├─ panelValue | string | 必须 | | 文件文本 | |
| ├─ panelType | string | 必须 | | 代码类型 | |
| ├─ prettierOpt | object | 必须 | | 代码美化选项 | |
| ├─ parser | string | 非必须 | | 指定要使用的解析器 | |
| ├─ tabWidth | number | 非必须 | | 指定使用几个空格来表示一个制表符(Tab) | |
| ├─ printWidth | number | 非必须 | | 指定每行代码的最大列数 | |
| ├─ type | string | 必须 | | 代码类型 | |
| ├─ filePath | string | 必须 | | 文件路径 | |
-
-
-
diff --git a/docs/catalog.json b/docs/catalog.json
index bea1934510..97e64f383d 100644
--- a/docs/catalog.json
+++ b/docs/catalog.json
@@ -8,23 +8,56 @@
"title": "新手指引",
"name": "getting-started",
"articles": [
- { "title": "简介", "name": "introduction.md" },
- { "title": "快速上手", "name": "quick-start.md" }
+ {
+ "title": "简介",
+ "name": "introduction.md"
+ },
+ {
+ "title": "快速上手",
+ "name": "quick-start.md"
+ }
]
},
{
"title": "基础功能",
"name": "basic-features",
"articles": [
- { "title": "设计器界面模块简介", "name": "designer-ui-modules.md" },
- { "title": "设计前端应用流程", "name": "frontend-application-flow.md" },
- { "title": "页面管理", "name": "page-management.md" },
- { "title": "使用组件", "name": "using-components.md" },
- { "title": "样式设置", "name": "style-settings.md" },
- { "title": "使用状态管理和变量绑定", "name": "state-management-and-variable-binding.md" },
- { "title": "行内样式绑定状态变量", "name": "inline-style-variable-binding.md" },
- { "title": "查看大纲树", "name": "outline-tree.md" },
- { "title": "国际化", "name": "internationalization.md" },
+ {
+ "title": "设计器界面模块简介",
+ "name": "designer-ui-modules.md"
+ },
+ {
+ "title": "设计前端应用流程",
+ "name": "frontend-application-flow.md"
+ },
+ {
+ "title": "页面管理",
+ "name": "page-management.md"
+ },
+ {
+ "title": "使用组件",
+ "name": "using-components.md"
+ },
+ {
+ "title": "样式设置",
+ "name": "style-settings.md"
+ },
+ {
+ "title": "使用状态管理和变量绑定",
+ "name": "state-management-and-variable-binding.md"
+ },
+ {
+ "title": "行内样式绑定状态变量",
+ "name": "inline-style-variable-binding.md"
+ },
+ {
+ "title": "查看大纲树",
+ "name": "outline-tree.md"
+ },
+ {
+ "title": "国际化",
+ "name": "internationalization.md"
+ },
{
"title": "资源管理",
"name": "resources-management.md"
@@ -39,40 +72,94 @@
"title": "进阶功能",
"name": "advanced-features",
"articles": [
- { "title": "区块管理", "name": "block-management.md" },
- { "title": "使用JS面板和事件绑定", "name": "js-panel-and-event-binding.md" },
+ {
+ "title": "区块管理",
+ "name": "block-management.md"
+ },
+ {
+ "title": "使用JS面板和事件绑定",
+ "name": "js-panel-and-event-binding.md"
+ },
{
"title": "使用工具类方法 utils",
"name": "using-utils-methods.md"
},
- { "title": "高级面板设置", "name": "advanced-panel-settings.md" },
- { "title": "如何使用插槽", "name": "how-to-use-slots.md" },
- { "title": "循环渲染", "name": "loop-rendering.md" },
- { "title": "条件渲染", "name": "conditional-rendering.md" },
- { "title": "新版AI插件使用", "name": "new-ai-plugin-usage.md" },
- { "title": "数据源和Collection—远程字段", "name": "data-source-and-collection-remote-fields.md" },
- { "title": "数据源和Collection—mock数据", "name": "data-source-and-collection-mock-data.md" },
- { "title": "数据源和Collection—使用数据源", "name": "data-source-and-collection-usage.md" },
+ {
+ "title": "高级面板设置",
+ "name": "advanced-panel-settings.md"
+ },
+ {
+ "title": "如何使用插槽",
+ "name": "how-to-use-slots.md"
+ },
+ {
+ "title": "循环渲染",
+ "name": "loop-rendering.md"
+ },
+ {
+ "title": "条件渲染",
+ "name": "conditional-rendering.md"
+ },
+ {
+ "title": "新版AI插件使用",
+ "name": "new-ai-plugin-usage.md"
+ },
+ {
+ "title": "数据源和Collection—远程字段",
+ "name": "data-source-and-collection-remote-fields.md"
+ },
+ {
+ "title": "数据源和Collection—mock数据",
+ "name": "data-source-and-collection-mock-data.md"
+ },
+ {
+ "title": "数据源和Collection—使用数据源",
+ "name": "data-source-and-collection-usage.md"
+ },
{
"title": "路由能力",
"name": "route-capabilities",
"articles": [
- { "title": "页面支持嵌套路由", "name": "page-support-nested-route.md" },
- { "title": "路由bar一键清除预览页面路径", "name": "route-bar-clear-preview-page.md" },
- { "title": "路由bar高亮显示预览页面路径", "name": "route-bar-current-page-highlight.md" },
- { "title": "RouterView组件支持预览子界面", "name": "route-view-support-preview-subpage.md" }
+ {
+ "title": "页面支持嵌套路由",
+ "name": "page-support-nested-route.md"
+ },
+ {
+ "title": "路由bar一键清除预览页面路径",
+ "name": "route-bar-clear-preview-page.md"
+ },
+ {
+ "title": "路由bar高亮显示预览页面路径",
+ "name": "route-bar-current-page-highlight.md"
+ },
+ {
+ "title": "RouterView组件支持预览子界面",
+ "name": "route-view-support-preview-subpage.md"
+ }
]
},
- { "title": "主题切换功能", "name": "theme-switch.md" },
- { "title": "画布快捷操作", "name": "canvas-shortcuts.md" }
+ {
+ "title": "主题切换功能",
+ "name": "theme-switch.md"
+ },
+ {
+ "title": "画布快捷操作",
+ "name": "canvas-shortcuts.md"
+ }
]
},
{
"title": "教程",
"name": "tutorials",
"articles": [
- { "title": "从零搭建一个页面", "name": "build-a-page-from-scratch.md" },
- { "title": "第一期2023.10.27", "name": "issue-1-2023.10.27.md" }
+ {
+ "title": "从零搭建一个页面",
+ "name": "build-a-page-from-scratch.md"
+ },
+ {
+ "title": "第一期2023.10.27",
+ "name": "issue-1-2023.10.27.md"
+ }
]
}
]
@@ -85,18 +172,32 @@
"title": "开始",
"name": "development-getting-started",
"articles": [
- { "title": "简介", "name": "dev-intro.md" },
- { "title": "快速上手", "name": "dev-quick-start.md" },
- { "title": "前后端启动联调(Java服务端)", "name": "debugging-of-java-backend.md" }
+ {
+ "title": "简介",
+ "name": "dev-intro.md"
+ },
+ {
+ "title": "快速上手",
+ "name": "dev-quick-start.md"
+ },
+ {
+ "title": "前后端启动联调(Java服务端)",
+ "name": "debugging-of-java-backend.md"
+ }
]
},
-
{
"title": "更新日志",
"name": "changelog",
"articles": [
- { "title": "更新日志", "name": "changelog.md" },
- { "title": "v2.7升级指南", "name": "v2.7-upgrade-guide.md" }
+ {
+ "title": "更新日志",
+ "name": "changelog.md"
+ },
+ {
+ "title": "v2.7升级指南",
+ "name": "v2.7-upgrade-guide.md"
+ }
]
},
{
@@ -107,84 +208,212 @@
"title": "前端及Java服务端docker部署",
"name": "front-backend-docker-deployment.md"
},
- { "title": "Java服务端部署", "name": "server-deployment-solution-java.md" },
- { "title": "Node.js服务端部署", "name": "server-deployment-solution.md" },
- { "title": "区块发布方案(Node.js服务端)", "name": "block-release-solution.md" },
- { "title": "区块局域网发布方案(Node.js服务端)", "name": "block-lan-release-solution.md" },
- { "title": "设计器中引入第三方组件库", "name": "third-party-library-in-designer.md" },
- { "title": "物料同步方案", "name": "material-sync-solution.md" },
- { "title": "本地化CDN方案", "name": "import-map-local.md" },
- { "title": "全新区块构建方案", "name": "block-construction-solution.md" },
- { "title": "全新画布通信方案", "name": "canvas-communication-solution.md" }
+ {
+ "title": "Java服务端部署",
+ "name": "server-deployment-solution-java.md"
+ },
+ {
+ "title": "Node.js服务端部署",
+ "name": "server-deployment-solution.md"
+ },
+ {
+ "title": "区块发布方案(Node.js服务端)",
+ "name": "block-release-solution.md"
+ },
+ {
+ "title": "区块局域网发布方案(Node.js服务端)",
+ "name": "block-lan-release-solution.md"
+ },
+ {
+ "title": "设计器中引入第三方组件库",
+ "name": "third-party-library-in-designer.md"
+ },
+ {
+ "title": "物料同步方案",
+ "name": "material-sync-solution.md"
+ },
+ {
+ "title": "本地化CDN方案",
+ "name": "import-map-local.md"
+ },
+ {
+ "title": "全新区块构建方案",
+ "name": "block-construction-solution.md"
+ },
+ {
+ "title": "全新画布通信方案",
+ "name": "canvas-communication-solution.md"
+ }
]
},
{
"title": "扩展能力介绍",
"name": "extension-capabilities-overview",
"articles": [
- { "title": "新架构介绍", "name": "new-architecture.md" },
- { "title": "注册表", "name": "registry.md" },
- { "title": "注册表(新版)", "name": "new-registry.md" },
- { "title": "注册表高级特性", "name": "new-registry-advanced.md" },
- { "title": "元服务和元应用", "name": "meta-services-and-meta-apps.md" }
+ {
+ "title": "新架构介绍",
+ "name": "new-architecture.md"
+ },
+ {
+ "title": "注册表",
+ "name": "registry.md"
+ },
+ {
+ "title": "注册表(新版)",
+ "name": "new-registry.md"
+ },
+ {
+ "title": "注册表高级特性",
+ "name": "new-registry-advanced.md"
+ },
+ {
+ "title": "元服务和元应用",
+ "name": "meta-services-and-meta-apps.md"
+ }
]
},
{
"title": "扩展能力使用教程",
"name": "extension-capabilities-tutorial",
"articles": [
- { "title": "如何开发插件", "name": "how-to-develop-plugins.md" },
+ {
+ "title": "如何开发插件",
+ "name": "how-to-develop-plugins.md"
+ },
{
"title": "出码功能",
"name": "code-output-function",
"articles": [
- { "title": "出码功能简介与使用", "name": "code-output-overview-and-usage.md" },
- { "title": "如何自定义出码", "name": "how-to-customize-code-output.md" },
- { "title": "如何自定义出码插件", "name": "how-to-customize-code-output-plugins.md" },
- { "title": "自定义页面出码插件", "name": "custom-page-code-output-plugin.md" },
- { "title": "官方出码能力API", "name": "official-code-output-api.md" }
+ {
+ "title": "出码功能简介与使用",
+ "name": "code-output-overview-and-usage.md"
+ },
+ {
+ "title": "如何自定义出码",
+ "name": "how-to-customize-code-output.md"
+ },
+ {
+ "title": "如何自定义出码插件",
+ "name": "how-to-customize-code-output-plugins.md"
+ },
+ {
+ "title": "自定义页面出码插件",
+ "name": "custom-page-code-output-plugin.md"
+ },
+ {
+ "title": "官方出码能力API",
+ "name": "official-code-output-api.md"
+ }
]
},
- { "title": "定制插件UI", "name": "customize-plugin-ui.md" },
- { "title": "定制元服务逻辑", "name": "customize-meta-service-logic.md" },
- { "title": "开发设置器组件", "name": "develop-configurator-components.md" },
- { "title": "AI插件使用前配置", "name": "ai-plugin-configuration.md" },
- { "title": "如何自定义主题", "name": "how-to-custom-theme.md" }
+ {
+ "title": "定制插件UI",
+ "name": "customize-plugin-ui.md"
+ },
+ {
+ "title": "定制元服务逻辑",
+ "name": "customize-meta-service-logic.md"
+ },
+ {
+ "title": "开发设置器组件",
+ "name": "develop-configurator-components.md"
+ },
+ {
+ "title": "AI插件使用前配置",
+ "name": "ai-plugin-configuration.md"
+ },
+ {
+ "title": "如何自定义主题",
+ "name": "how-to-custom-theme.md"
+ }
]
},
{
"title": "API",
"name": "api",
"articles": [
- { "title": "API总览", "name": "api-overview.md" },
+ {
+ "title": "API总览",
+ "name": "api-overview.md"
+ },
{
"title": "前端API",
"name": "frontend-api",
"articles": [
- { "title": "主包API", "name": "main-package-api.md" },
- { "title": "画布API", "name": "canvas-api.md" },
- { "title": "全局布局API", "name": "global-layout-api.md" },
- { "title": "物料API", "name": "material-api.md" },
- { "title": "设置面板API", "name": "settings-panel-api.md" },
- { "title": "预览API", "name": "preview-api.md" },
- { "title": "元服务API", "name": "globalService-api.md" },
- { "title": "注册表API", "name": "registry-api.md" }
+ {
+ "title": "主包API",
+ "name": "main-package-api.md"
+ },
+ {
+ "title": "画布API",
+ "name": "canvas-api.md"
+ },
+ {
+ "title": "全局布局API",
+ "name": "global-layout-api.md"
+ },
+ {
+ "title": "物料API",
+ "name": "material-api.md"
+ },
+ {
+ "title": "设置面板API",
+ "name": "settings-panel-api.md"
+ },
+ {
+ "title": "预览API",
+ "name": "preview-api.md"
+ },
+ {
+ "title": "元服务API",
+ "name": "globalService-api.md"
+ },
+ {
+ "title": "注册表API",
+ "name": "registry-api.md"
+ }
]
},
{
"title": "后端API",
"name": "backend-api",
"articles": [
- { "title": "AI功能接口", "name": "ai-function-api.md" },
- { "title": "应用管理", "name": "app-management.md" },
- { "title": "区块分类", "name": "block-categories.md" },
- { "title": "应用工具类管理", "name": "app-utility-management.md" },
- { "title": "区块管理", "name": "block-management-api.md" },
- { "title": "数据源管理", "name": "data-source-management.md" },
- { "title": "DSL代码生成", "name": "dsl-code-generation.md" },
- { "title": "物料中心", "name": "material-center.md" },
- { "title": "页面管理", "name": "page-management-api.md" },
- { "title": "APP服务", "name": "app-services.md" }
+ {
+ "title": "AI功能接口",
+ "name": "ai-function-api.md"
+ },
+ {
+ "title": "应用管理",
+ "name": "app-management.md"
+ },
+ {
+ "title": "区块分类",
+ "name": "block-categories.md"
+ },
+ {
+ "title": "应用工具类管理",
+ "name": "app-utility-management.md"
+ },
+ {
+ "title": "区块管理",
+ "name": "block-management-api.md"
+ },
+ {
+ "title": "数据源管理",
+ "name": "data-source-management.md"
+ },
+ {
+ "title": "物料中心",
+ "name": "material-center.md"
+ },
+ {
+ "title": "页面管理",
+ "name": "page-management-api.md"
+ },
+ {
+ "title": "APP服务",
+ "name": "app-services.md"
+ }
]
}
]
@@ -193,9 +422,18 @@
"title": "实战案例",
"name": "practical-cases",
"articles": [
- { "title": "PDM元数据审批电子流", "name": "pdm-metadata-approval-workflow.md" },
- { "title": "图元编排设计器", "name": "graphical-element-arrangement-designer.md" },
- { "title": "SMB轻量应用服务", "name": "smb-lightweight-application-service.md" }
+ {
+ "title": "PDM元数据审批电子流",
+ "name": "pdm-metadata-approval-workflow.md"
+ },
+ {
+ "title": "图元编排设计器",
+ "name": "graphical-element-arrangement-designer.md"
+ },
+ {
+ "title": "SMB轻量应用服务",
+ "name": "smb-lightweight-application-service.md"
+ }
]
}
]
@@ -208,10 +446,22 @@
"title": "生态中心",
"name": "ecosystem-center",
"articles": [
- { "title": "介绍", "name": "ecosystem-intro.md" },
- { "title": "如何导入组件库", "name": "how-to-import-library.md" },
- { "title": "如何发布区块", "name": "how-to-publish-block.md" },
- { "title": "发布其他生态", "name": "publish-other-ecosystems.md" }
+ {
+ "title": "介绍",
+ "name": "ecosystem-intro.md"
+ },
+ {
+ "title": "如何导入组件库",
+ "name": "how-to-import-library.md"
+ },
+ {
+ "title": "如何发布区块",
+ "name": "how-to-publish-block.md"
+ },
+ {
+ "title": "发布其他生态",
+ "name": "publish-other-ecosystems.md"
+ }
]
},
{
@@ -222,33 +472,57 @@
"title": "创建应用(创建空白应用、从模板创建应用)",
"name": "create-application-blank-or-template.md"
},
- { "title": "开发应用", "name": "develop-application.md" }
+ {
+ "title": "开发应用",
+ "name": "develop-application.md"
+ }
]
},
{
"title": "关于物料",
"name": "about-materials",
"articles": [
- { "title": "介绍", "name": "materials-intro.md" },
- { "title": "创建物料资产包", "name": "create-material-asset-package.md" },
- { "title": "添加组件库和区块", "name": "add-library-and-blocks.md" },
- { "title": "构建物料资产包", "name": "build-material-asset-package.md" }
+ {
+ "title": "介绍",
+ "name": "materials-intro.md"
+ },
+ {
+ "title": "创建物料资产包",
+ "name": "create-material-asset-package.md"
+ },
+ {
+ "title": "添加组件库和区块",
+ "name": "add-library-and-blocks.md"
+ },
+ {
+ "title": "构建物料资产包",
+ "name": "build-material-asset-package.md"
+ }
]
},
{
"title": "关于设计器",
"name": "about-designer",
"articles": [
- { "title": "介绍", "name": "designer-intro.md" },
- { "title": "创建设计器", "name": "create-designer.md" },
+ {
+ "title": "介绍",
+ "name": "designer-intro.md"
+ },
+ {
+ "title": "创建设计器",
+ "name": "create-designer.md"
+ },
{
"title": "定制物料资产包、主题、DSL、工具栏和插件栏",
"name": "customize-material-package-themes-dsl-toolbar-plugins.md"
},
- { "title": "定制设计器", "name": "customize-designer.md" }
+ {
+ "title": "定制设计器",
+ "name": "customize-designer.md"
+ }
]
}
]
}
]
-}
+}
\ No newline at end of file
diff --git a/lint-staged.config.js b/lint-staged.config.js
index f794152af8..21f321f7ac 100644
--- a/lint-staged.config.js
+++ b/lint-staged.config.js
@@ -1,4 +1,4 @@
module.exports = {
- './packages/**/**.{js,mjs,jsx,ts,mts,tsx,vue}': 'eslint',
+ './packages/**/**.{js,mjs,jsx,ts,mts,tsx,vue}': 'eslint --no-warn-ignored',
'./packages/**/**.{js,mjs,jsx,ts,mts,tsx,vue,html,json,less}': 'prettier --write'
}
diff --git a/mockServer/package.json b/mockServer/package.json
index 54e51c7c4f..cefcc7092c 100644
--- a/mockServer/package.json
+++ b/mockServer/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentiny/tiny-engine-mock",
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"publishConfig": {
"access": "public"
},
diff --git a/mockServer/src/assets/json/model.json b/mockServer/src/assets/json/model.json
index a0dab4b340..8fa7d42d56 100644
--- a/mockServer/src/assets/json/model.json
+++ b/mockServer/src/assets/json/model.json
@@ -529,4 +529,4 @@
"current": 1,
"pages": 1
}
-}
+}
\ No newline at end of file
diff --git a/mockServer/src/database/model.db b/mockServer/src/database/model.db
new file mode 100644
index 0000000000..f94205f057
--- /dev/null
+++ b/mockServer/src/database/model.db
@@ -0,0 +1,2 @@
+{"_id":1,"id":5,"createdBy":"1","lastUpdatedBy":"1","tenantId":null,"renterId":null,"siteId":null,"appId":null,"platformId":1,"nameCn":"员工","nameEn":"staff","version":"1.0.0","modelUrl":"https://agent-alpha.opentiny.design/platform-center/api/model-data","parameters":[{"prop":"id","isModel":false,"type":"Number","required":true,"description":"主键","_RID":"row_1"},{"prop":"name","isModel":false,"type":"String","required":true,"description":"姓名","_RID":"row_2"},{"prop":"status","isModel":false,"type":"Enum","options":"[{\"value\":\"1\",\"label\":\"已转正\"},{\"value\":\"0\",\"label\":\"未转正\"}]","required":true,"description":"状态","_RID":"row_3"},{"prop":"test","type":"String","required":false,"description":"","isModel":false,"_RID":"row_4"}],"method":[{"name":"新增方法","nameEn":"insertApi","requestParameters":[{"prop":"nameEn","type":"String"},{"prop":"params","type":"Object","children":[{"prop":"id","isModel":false,"type":"Number","required":true,"description":"主键"},{"prop":"name","isModel":false,"type":"String","required":true,"description":"姓名"},{"prop":"status","isModel":false,"type":"Enum","options":"[{\"value\":\"1\",\"label\":\"已转正\"},{\"value\":\"0\",\"label\":\"未转正\"}]","required":true,"description":"状态"},{"prop":"test","type":"String","required":false,"description":""}]}],"responseParameters":[{"prop":"code","type":"Number"},{"prop":"message","type":"String"},{"prop":"data","type":"Enum"}]},{"name":"修改方法","nameEn":"updateApi","requestParameters":[{"prop":"nameEn","type":"String"},{"prop":"data","type":"Object","children":[{"prop":"id","isModel":false,"type":"Number","required":true,"description":"主键"},{"prop":"name","isModel":false,"type":"String","required":true,"description":"姓名"},{"prop":"status","isModel":false,"type":"Enum","options":"[{\"value\":\"1\",\"label\":\"已转正\"},{\"value\":\"0\",\"label\":\"未转正\"}]","required":true,"description":"状态"},{"prop":"test","type":"String","required":false,"description":""}]},{"prop":"params","type":"Object","children":[{"prop":"id","isModel":false,"type":"Number","required":true,"description":"主键"},{"prop":"name","isModel":false,"type":"String","required":true,"description":"姓名"},{"prop":"status","isModel":false,"type":"Enum","options":"[{\"value\":\"1\",\"label\":\"已转正\"},{\"value\":\"0\",\"label\":\"未转正\"}]","required":true,"description":"状态"},{"prop":"test","type":"String","required":false,"description":""}]}],"responseParameters":[{"prop":"code","type":"Number"},{"prop":"message","type":"String"},{"prop":"data","type":"Enum"}]},{"name":"查询方法","nameEn":"queryApi","requestParameters":[{"prop":"nameEn","type":"String"},{"prop":"currentPage","type":"Number"},{"prop":"pageSize","type":"Number"},{"prop":"nameCn","type":"String"},{"prop":"params","type":"Object","children":[{"prop":"id","isModel":false,"type":"Number","required":true,"description":"主键"},{"prop":"name","isModel":false,"type":"String","required":true,"description":"姓名"},{"prop":"status","isModel":false,"type":"Enum","options":"[{\"value\":\"1\",\"label\":\"已转正\"},{\"value\":\"0\",\"label\":\"未转正\"}]","required":true,"description":"状态"},{"prop":"test","type":"String","required":false,"description":""}]}],"responseParameters":[{"prop":"total","type":"Number"},{"prop":"code","type":"Number"},{"prop":"message","type":"String"},{"prop":"data","type":"Enum"}]},{"name":"删除方法","nameEn":"deleteApi","requestParameters":[{"prop":"nameEn","type":"String"},{"prop":"id","type":"Number"}],"responseParameters":[{"prop":"code","type":"Number"},{"prop":"message","type":"String"},{"prop":"data","type":"Enum"}]}],"description":"1112","created_at":"2026-01-27 10:41:10","updated_at":"2026-01-27 10:41:10"}
+{"_id":2,"id":6,"createdBy":"11","lastUpdatedBy":"11","tenantId":null,"renterId":null,"siteId":null,"appId":null,"platformId":1,"nameCn":"用户","nameEn":"user","version":"1.0.0","modelUrl":"https://agent-alpha.opentiny.design/platform-center/api","parameters":[{"prop":"name","type":"String","required":false,"description":""},{"prop":"age","type":"Number","required":false,"description":""}],"method":[{"name":"新增方法","nameEn":"insertApi","requestParameters":[{"prop":"nameEn","type":"String"},{"prop":"params","type":"Object","children":[{"prop":"name","type":"String","required":false,"description":""},{"prop":"age","type":"Number","required":false,"description":""}]}],"responseParameters":[{"prop":"code","type":"Number"},{"prop":"message","type":"String"},{"prop":"data","type":"Enum"}]},{"name":"修改方法","nameEn":"updateApi","requestParameters":[{"prop":"nameEn","type":"String"},{"prop":"data","type":"Object","children":[{"prop":"name","type":"String","required":false,"description":""},{"prop":"age","type":"Number","required":false,"description":""}]},{"prop":"params","type":"Object","children":[{"prop":"name","type":"String","required":false,"description":""},{"prop":"age","type":"Number","required":false,"description":""}]}],"responseParameters":[{"prop":"code","type":"Number"},{"prop":"message","type":"String"},{"prop":"data","type":"Enum"}]},{"name":"查询方法","nameEn":"queryApi","requestParameters":[{"prop":"nameEn","type":"String"},{"prop":"currentPage","type":"Number"},{"prop":"pageSize","type":"Number"},{"prop":"nameCn","type":"String"},{"prop":"params","type":"Object","children":[{"prop":"name","type":"String","required":false,"description":""},{"prop":"age","type":"Number","required":false,"description":""}]}],"responseParameters":[{"prop":"total","type":"Number"},{"prop":"code","type":"Number"},{"prop":"message","type":"String"},{"prop":"data","type":"Enum"}]},{"name":"删除方法","nameEn":"deleteApi","requestParameters":[{"prop":"nameEn","type":"String"},{"prop":"id","type":"Number"}],"responseParameters":[{"prop":"code","type":"Number"},{"prop":"message","type":"String"},{"prop":"data","type":"Enum"}]}],"description":"","created_at":"2026-01-29 03:00:21","updated_at":"2026-01-29 03:00:21"}
diff --git a/mockServer/src/database/pages.db b/mockServer/src/database/pages.db
index c90a9bb17a..808e35401d 100644
--- a/mockServer/src/database/pages.db
+++ b/mockServer/src/database/pages.db
@@ -1,4 +1,3 @@
{"name":"CreateVm","id":"1","app":"1","route":"CreateVm","page_content":{"state":{"dataDisk":[1,2,3]},"methods":{},"componentName":"Page","css":"body {\r\n background-color:#eef0f5 ;\r\n margin-bottom: 80px;\r\n}","props":{},"children":[{"componentName":"div","props":{"style":"padding-bottom: 10px; padding-top: 10px;"},"id":"2b2cabf0","children":[{"componentName":"TinyTimeLine","props":{"active":"2","data":[{"name":"基础配置"},{"name":"网络配置"},{"name":"高级配置"},{"name":"确认配置"}],"horizontal":true,"style":"border-radius: 0px;"},"id":"dd764b17"}]},{"componentName":"div","props":{"style":"border-width: 1px; border-style: solid; border-radius: 4px; border-color: #fff; padding-top: 10px; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px; background-color: #fff; margin-bottom: 10px;"},"id":"30c94cc8","children":[{"componentName":"TinyForm","props":{"labelWidth":"80px","labelPosition":"top","inline":false,"label-position":"left ","label-width":"150px","style":"border-radius: 0px;"},"children":[{"componentName":"TinyFormItem","props":{"label":"计费模式"},"children":[{"componentName":"TinyButtonGroup","props":{"data":[{"text":"包年/包月","value":"1"},{"text":"按需计费","value":"2"}],"modelValue":"1"},"id":"a8d84361"}],"id":"9f39f3e7"},{"componentName":"TinyFormItem","props":{"label":"区域"},"children":[{"componentName":"TinyButtonGroup","props":{"data":[{"text":"乌兰察布二零一","value":"1"}],"modelValue":"1","style":"border-radius: 0px; margin-right: 10px;"},"id":"c97ccd99"},{"componentName":"Text","props":{"text":"温馨提示:页面左上角切换区域","style":"background-color: [object Event]; color: #8a8e99; font-size: 12px;"},"id":"20923497"},{"componentName":"Text","props":{"text":"不同区域的云服务产品之间内网互不相通;请就近选择靠近您业务的区域,可减少网络时延,提高访问速度","style":"display: block; color: #8a8e99; border-radius: 0px; font-size: 12px;"},"id":"54780a26"}],"id":"4966384d"},{"componentName":"TinyFormItem","props":{"label":"可用区","style":"border-radius: 0px;"},"children":[{"componentName":"TinyButtonGroup","props":{"data":[{"text":"可用区1","value":"1"},{"text":"可用区2","value":"2"},{"text":"可用区3","value":"3"}],"modelValue":"1"},"id":"6184481b"}],"id":"690837bf"}],"id":"b6a425d4"}]},{"componentName":"div","props":{"style":"border-width: 1px; border-style: solid; border-radius: 4px; border-color: #fff; padding-top: 10px; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px; background-color: #fff; margin-bottom: 10px;"},"children":[{"componentName":"TinyForm","props":{"labelWidth":"80px","labelPosition":"top","inline":false,"label-position":"left ","label-width":"150px","style":"border-radius: 0px;"},"children":[{"componentName":"TinyFormItem","props":{"label":"CPU架构"},"children":[{"componentName":"TinyButtonGroup","props":{"data":[{"text":"x86计算","value":"1"},{"text":"鲲鹏计算","value":"2"}],"modelValue":"1"},"id":"7d33ced7"}],"id":"05ed5a79"},{"componentName":"TinyFormItem","props":{"label":"区域"},"children":[{"componentName":"div","props":{"style":"display: flex; justify-content: flex-start; align-items: center;"},"id":"606edf78","children":[{"componentName":"div","props":{"style":"display: flex; align-items: center; margin-right: 10px;"},"id":"f3f98246","children":[{"componentName":"Text","props":{"text":"vCPUs","style":"width: 80px;"},"id":"c287437e"},{"componentName":"TinySelect","props":{"modelValue":"","placeholder":"请选择","options":[{"value":"1","label":"黄金糕"},{"value":"2","label":"双皮奶"}]},"id":"4c43286b"}]},{"componentName":"div","props":{"style":"display: flex; align-items: center; margin-right: 10px;"},"children":[{"componentName":"Text","props":{"text":"内存","style":"width: 80px; border-radius: 0px;"},"id":"38b8fa1f"},{"componentName":"TinySelect","props":{"modelValue":"","placeholder":"请选择","options":[{"value":"1","label":"黄金糕"},{"value":"2","label":"双皮奶"}]},"id":"cd33328e"}],"id":"2b2c678f"},{"componentName":"div","props":{"style":"display: flex; align-items: center;"},"children":[{"componentName":"Text","props":{"text":"规格名称","style":"width: 80px;"},"id":"d3eb6352"},{"componentName":"TinySearch","props":{"modelValue":"","placeholder":"输入关键词"},"id":"21cb9282"}],"id":"b8e0f35c"}]},{"componentName":"div","props":{"style":"border-radius: 0px;"},"id":"5000c83e","children":[{"componentName":"TinyButtonGroup","props":{"data":[{"text":"通用计算型","value":"1"},{"text":"通用计算增强型","value":"2"},{"text":"内存优化型","value":"3"},{"text":"内存优化型","value":"4"},{"text":"磁盘增强型","value":"5"},{"text":"超高I/O型","value":"6"},{"text":"GPU加速型","value":"7"}],"modelValue":"1","style":"border-radius: 0px; margin-top: 12px;"},"id":"b8724703"},{"componentName":"TinyGrid","props":{"editConfig":{"trigger":"click","mode":"cell","showStatus":true},"columns":[{"type":"radio","width":60},{"field":"employees","title":"规格名称"},{"field":"created_date","title":"vCPUs | 内存(GiB)","sortable":true},{"field":"city","title":"CPU","sortable":true},{"title":"基准 / 最大带宽\t","sortable":true},{"title":"内网收发包","sortable":true}],"data":[{"id":"1","name":"GFD科技有限公司","city":"福州","employees":800,"created_date":"2014-04-30 00:56:00","boole":false},{"id":"2","name":"WWW科技有限公司","city":"深圳","employees":300,"created_date":"2016-07-08 12:36:22","boole":true}],"style":"margin-top: 12px; border-radius: 0px;","auto-resize":true},"id":"77701c25"},{"componentName":"div","props":{"style":"margin-top: 12px; border-radius: 0px;"},"id":"3339838b","children":[{"componentName":"Text","props":{"text":"当前规格","style":"width: 150px; display: inline-block;"},"id":"203b012b"},{"componentName":"Text","props":{"text":"通用计算型 | Si2.large.2 | 2vCPUs | 4 GiB","style":"font-weight: 700;"},"id":"87723f52"}]}]}],"id":"657fb2fc"}],"id":"d19b15cf"}],"id":"9991228b"},{"componentName":"div","props":{"style":"border-width: 1px; border-style: solid; border-radius: 4px; border-color: #fff; padding-top: 10px; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px; background-color: #fff; margin-bottom: 10px;"},"children":[{"componentName":"TinyForm","props":{"labelWidth":"80px","labelPosition":"top","inline":false,"label-position":"left ","label-width":"150px","style":"border-radius: 0px;"},"children":[{"componentName":"TinyFormItem","props":{"label":"镜像","style":"border-radius: 0px;"},"children":[{"componentName":"TinyButtonGroup","props":{"data":[{"text":"公共镜像","value":"1"},{"text":"私有镜像","value":"2"},{"text":"共享镜像","value":"3"}],"modelValue":"1"},"id":"922b14cb"},{"componentName":"div","props":{"style":"display: flex; margin-top: 12px; border-radius: 0px;"},"id":"6b679524","children":[{"componentName":"TinySelect","props":{"modelValue":"","placeholder":"请选择","options":[{"value":"1","label":"黄金糕"},{"value":"2","label":"双皮奶"}],"style":"width: 170px; margin-right: 10px;"},"id":"4851fff7"},{"componentName":"TinySelect","props":{"modelValue":"","placeholder":"请选择","options":[{"value":"1","label":"黄金糕"},{"value":"2","label":"双皮奶"}],"style":"width: 340px;"},"id":"a7183eb7"}]},{"componentName":"div","props":{"style":"margin-top: 12px;"},"id":"57aee314","children":[{"componentName":"Text","props":{"text":"请注意操作系统的语言类型。","style":"color: #e37d29;"},"id":"56d36c27"}]}],"id":"e3b02436"}],"id":"59aebf2b"}],"id":"87ff7b99"},{"componentName":"div","props":{"style":"border-width: 1px; border-style: solid; border-radius: 4px; border-color: #fff; padding-top: 10px; padding-bottom: 10px; padding-left: 10px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px; background-color: #fff; margin-bottom: 10px;"},"children":[{"componentName":"TinyForm","props":{"labelWidth":"80px","labelPosition":"top","inline":false,"label-position":"left ","label-width":"150px","style":"border-radius: 0px;"},"children":[{"componentName":"TinyFormItem","props":{"label":"系统盘","style":"border-radius: 0px;"},"children":[{"componentName":"div","props":{"style":"display: flex;"},"id":"cddba5b8","children":[{"componentName":"TinySelect","props":{"modelValue":"","placeholder":"请选择","options":[{"value":"1","label":"黄金糕"},{"value":"2","label":"双皮奶"}],"style":"width: 200px; margin-right: 10px;"},"id":"a97fbe15"},{"componentName":"TinyInput","props":{"placeholder":"请输入","modelValue":"","style":"width: 120px; margin-right: 10px;"},"id":"1cde4c0f"},{"componentName":"Text","props":{"text":"GiB \nIOPS上限240,IOPS突发上限5,000","style":"color: #575d6c; font-size: 12px;"},"id":"2815d82d"}]}],"id":"50239a3a"}],"id":"e8582986"},{"componentName":"TinyForm","props":{"labelWidth":"80px","labelPosition":"top","inline":false,"label-position":"left ","label-width":"150px","style":"border-radius: 0px;"},"children":[{"componentName":"TinyFormItem","props":{"label":"数据盘","style":"border-radius: 0px;"},"children":[{"componentName":"div","props":{"style":"margin-top: 12px; display: flex;"},"id":"728c9825","children":[{"componentName":"Icon","props":{"style":"margin-right: 10px; width: 16px; height: 16px;","name":"IconPanelMini"},"id":"fded6930"},{"componentName":"TinySelect","props":{"modelValue":"","placeholder":"请选择","options":[{"value":"1","label":"黄金糕"},{"value":"2","label":"双皮奶"}],"style":"width: 200px; margin-right: 10px;"},"id":"62734e3f"},{"componentName":"TinyInput","props":{"placeholder":"请输入","modelValue":"","style":"width: 120px; margin-right: 10px;"},"id":"667c7926"},{"componentName":"Text","props":{"text":"GiB \nIOPS上限600,IOPS突发上限5,000","style":"color: #575d6c; font-size: 12px; margin-right: 10px;"},"id":"e7bc36d6"},{"componentName":"TinyInput","props":{"placeholder":"请输入","modelValue":"","style":"width: 120px;"},"id":"1bd56dc0"}],"loop":{"type":"JSExpression","value":"this.state.dataDisk"}},{"componentName":"div","props":{"style":"display: flex; margin-top: 12px; border-radius: 0px;"},"children":[{"componentName":"Icon","props":{"name":"IconPlus","style":"width: 16px; height: 16px; margin-right: 10px;"},"id":"65c89f2b"},{"componentName":"Text","props":{"text":"增加一块数据盘","style":"font-size: 12px; border-radius: 0px; margin-right: 10px;"},"id":"cb344071"},{"componentName":"Text","props":{"text":"您还可以挂载 21 块磁盘(云硬盘)","style":"color: #8a8e99; font-size: 12px;"},"id":"80eea996"}],"id":"e9e530ab"}],"id":"078e03ef"}],"id":"ccef886e"}],"id":"0fb7bd74"},{"componentName":"div","props":{"style":"border-width: 1px; border-style: solid; border-color: #ffffff; padding-top: 10px; padding-left: 10px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px; background-color: #fff; position: fixed; inset: auto 0% 0% 0%; height: 80px; line-height: 80px; border-radius: 0px;"},"children":[{"componentName":"TinyForm","props":{"labelWidth":"80px","labelPosition":"top","inline":false,"label-position":"left ","label-width":"150px","style":"border-radius: 0px;"},"children":[],"id":"21ed4475"},{"componentName":"TinyRow","props":{"style":"border-radius: 0px; height: 100%;"},"children":[{"componentName":"TinyCol","props":{"span":"8"},"id":"b9d051a5","children":[{"componentName":"TinyRow","props":{"style":"border-radius: 0px;"},"children":[{"componentName":"TinyCol","props":{"span":"5","style":"display: flex;"},"id":"02352776","children":[{"componentName":"Text","props":{"text":"购买量","style":"margin-right: 10px;"},"id":"0cd9ed5c"},{"componentName":"TinyInput","props":{"placeholder":"请输入","modelValue":"","style":"width: 120px; margin-right: 10px;"},"id":"2f9cf442"},{"componentName":"Text","props":{"text":"台"},"id":"facd4481"}]},{"componentName":"TinyCol","props":{"span":"7"},"id":"82b6c659","children":[{"componentName":"div","props":{},"id":"9cd65874","children":[{"componentName":"Text","props":{"text":"配置费用","style":"font-size: 12px;"},"id":"b5a0a0da"},{"componentName":"Text","props":{"text":"¥1.5776","style":"padding-left: 10px; padding-right: 10px; color: #de504e;"},"id":"d9464214"},{"componentName":"Text","props":{"text":"/小时","style":"font-size: 12px;"},"id":"af7cc5e6"}]},{"componentName":"div","props":{},"id":"89063830","children":[{"componentName":"Text","props":{"text":"参考价格,具体扣费请以账单为准。","style":"font-size: 12px; border-radius: 0px;"},"id":"d8995fbc"},{"componentName":"Text","props":{"text":"了解计费详情","style":"font-size: 12px; color: #344899;"},"id":"b383c3e2"}]}]}],"id":"94fc0e43"}]},{"componentName":"TinyCol","props":{"span":"4","style":"display: flex; flex-direction: row-reverse; border-radius: 0px; height: 100%; justify-content: flex-start; align-items: center;"},"id":"10b73009","children":[{"componentName":"TinyButton","props":{"text":"下一步: 网络配置","type":"danger","style":"max-width: unset;"},"id":"0b584011"}]}],"id":"d414a473"}],"id":"e8ec029b"}],"fileName":"CreateVm"},"tenant":1,"isBody":false,"parentId":"0","group":"staticPages","depth":0,"isPage":true,"isDefault":false,"occupier":null,"isHome":false,"_id":"1"}
{"name":"DemoPage","id":"5bhD7p5FUsUOTFRN","app":"1","route":"demopage","page_content":{"state":{},"methods":{},"componentName":"Page","css":"","props":{},"lifeCycles":{},"children":[{"componentName":"div","props":{},"id":"85375559","children":[{"componentName":"TinySwitch","props":{"modelValue":""},"id":"33433546"}]}],"dataSource":{"list":[]},"utils":[],"bridge":[],"inputs":[],"outputs":[],"fileName":"DemoPage"},"tenant":1,"isBody":false,"parentId":"0","group":"staticPages","depth":0,"isPage":true,"isDefault":false,"occupier":{"id":86,"username":"开发者","email":"developer@lowcode.com","confirmationToken":"dfb2c162-351f-4f44-ad5f-8998","is_admin":true},"isHome":false,"message":"Page auto save","_id":"5bhD7p5FUsUOTFRN"}
-{"$$indexCreated":{"fieldName":"route","unique":true,"sparse":false}}
-{"$$indexCreated":{"fieldName":"route","unique":true}}
+{"$$indexCreated":{"fieldName":"_id","unique":true}}
diff --git a/mockServer/src/mock/get/app-center/v1/apps/schema/1.json b/mockServer/src/mock/get/app-center/v1/apps/schema/1.json
index 9240b466b8..8a00903ea7 100644
--- a/mockServer/src/mock/get/app-center/v1/apps/schema/1.json
+++ b/mockServer/src/mock/get/app-center/v1/apps/schema/1.json
@@ -1854,6 +1854,13 @@
"destructuring": true,
"version": "0.1.16"
},
+ {
+ "componentName": "TinyActionMenu",
+ "package": "@opentiny/vue",
+ "exportName": "ActionMenu",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
{
"componentName": "TinyDialogBox",
"package": "@opentiny/vue",
@@ -2211,6 +2218,27 @@
"destructuring": true,
"version": "3.22.0"
},
+ {
+ "componentName": "TinyHuichartsGraph",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsGraph",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsProcess",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsProcess",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsGauge",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsGauge",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
{
"componentName": "PortalHome",
"main": "common/components/home",
diff --git a/mockServer/src/mock/get/app-center/v1/apps/schema/16.json b/mockServer/src/mock/get/app-center/v1/apps/schema/16.json
index 95402dd374..0e7d227952 100644
--- a/mockServer/src/mock/get/app-center/v1/apps/schema/16.json
+++ b/mockServer/src/mock/get/app-center/v1/apps/schema/16.json
@@ -1,1364 +1,1391 @@
{
- "data": {
- "meta": {
- "name": "dashboard",
- "tenant": 1,
- "git_group": "",
- "project_name": "",
- "description": "数据看板",
- "branch": "develop",
- "is_demo": null,
- "global_state": [],
- "appId": "16",
- "creator": "",
- "gmt_create": "2022-06-08 03:19:01",
- "gmt_modified": "2023-08-23 10:22:28"
- },
- "dataSource": {
- "list": [
- {
- "id": 132,
- "name": "getAllComponent",
- "data": {
- "data": [],
- "type": "array"
+ "data": {
+ "meta": {
+ "name": "dashboard",
+ "tenant": 1,
+ "git_group": "",
+ "project_name": "",
+ "description": "数据看板",
+ "branch": "develop",
+ "is_demo": null,
+ "global_state": [],
+ "appId": "16",
+ "creator": "",
+ "gmt_create": "2022-06-08 03:19:01",
+ "gmt_modified": "2023-08-23 10:22:28"
+ },
+ "dataSource": {
+ "list": [
+ {
+ "id": 132,
+ "name": "getAllComponent",
+ "data": {
+ "data": [],
+ "type": "array"
+ },
+ "tpl": null,
+ "app": "1",
+ "desc": null,
+ "created_at": "2022-06-28T06:26:26.000Z",
+ "updated_at": "2022-06-28T07:02:30.000Z"
+ },
+ {
+ "id": 133,
+ "name": "getAllList",
+ "data": {
+ "columns": [
+ {
+ "name": "test",
+ "title": "测试",
+ "field": "test",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "test1",
+ "title": "测试1",
+ "field": "test1",
+ "type": "string",
+ "format": {}
+ }
+ ],
+ "type": "array",
+ "data": [
+ {
+ "test": "test1",
+ "test1": "test1",
+ "_id": "341efc48"
+ },
+ {
+ "test": "test2",
+ "test1": "test1",
+ "_id": "b86b516c"
+ },
+ {
+ "test": "test3",
+ "test1": "test1",
+ "_id": "f680cd78"
+ }
+ ],
+ "options": {
+ "uri": "",
+ "method": "GET"
+ },
+ "dataHandler": {
+ "type": "JSFunction",
+ "value": "function dataHandler(data) { \n return data \n}"
},
- "tpl": null,
- "app": "1",
- "desc": null,
- "created_at": "2022-06-28T06:26:26.000Z",
- "updated_at": "2022-06-28T07:02:30.000Z"
+ "willFetch": {
+ "type": "JSFunction",
+ "value": "function willFetch(option) {\n return option \n}"
+ },
+ "shouldFetch": {
+ "type": "JSFunction",
+ "value": "function shouldFetch(option) {\n return true \n}"
+ },
+ "errorHandler": {
+ "type": "JSFunction",
+ "value": "function errorHandler(err) {}"
+ }
},
- {
- "id": 133,
- "name": "getAllList",
- "data": {
- "columns": [
- {
- "name": "test",
- "title": "测试",
- "field": "test",
- "type": "string",
- "format": {}
- },
- {
- "name": "test1",
- "title": "测试1",
- "field": "test1",
- "type": "string",
- "format": {}
- }
- ],
- "type": "array",
- "data": [
- {
- "test": "test1",
- "test1": "test1",
- "_id": "341efc48"
- },
- {
- "test": "test2",
- "test1": "test1",
- "_id": "b86b516c"
- },
- {
- "test": "test3",
- "test1": "test1",
- "_id": "f680cd78"
+ "tpl": null,
+ "app": "1",
+ "desc": null,
+ "created_at": "2022-06-28T07:32:16.000Z",
+ "updated_at": "2023-01-19T03:29:11.000Z"
+ },
+ {
+ "id": 135,
+ "name": "getAllMaterialList",
+ "data": {
+ "columns": [
+ {
+ "name": "id",
+ "title": "id",
+ "field": "id",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "name",
+ "title": "name",
+ "field": "name",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "framework",
+ "title": "framework",
+ "field": "framework",
+ "type": "string",
+ "format": {
+ "required": true
}
- ],
- "options": {
- "uri": "",
- "method": "GET"
},
- "dataHandler": {
- "type": "JSFunction",
- "value": "function dataHandler(data) { \n return data \n}"
+ {
+ "name": "components",
+ "title": "components",
+ "field": "components",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "content",
+ "title": "content",
+ "field": "content",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "url",
+ "title": "url",
+ "field": "url",
+ "type": "string",
+ "format": {}
},
- "willFetch": {
- "type": "JSFunction",
- "value": "function willFetch(option) {\n return option \n}"
+ {
+ "name": "published_at",
+ "title": "published_at",
+ "field": "published_at",
+ "type": "string",
+ "format": {}
},
- "shouldFetch": {
- "type": "JSFunction",
- "value": "function shouldFetch(option) {\n return true \n}"
+ {
+ "name": "created_at",
+ "title": "created_at",
+ "field": "created_at",
+ "type": "string",
+ "format": {}
},
- "errorHandler": {
- "type": "JSFunction",
- "value": "function errorHandler(err) {}"
+ {
+ "name": "updated_at",
+ "title": "updated_at",
+ "field": "updated_at",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "published",
+ "title": "published",
+ "field": "published",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "last_build_info",
+ "title": "last_build_info",
+ "field": "last_build_info",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "tenant",
+ "title": "tenant",
+ "field": "tenant",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "version",
+ "title": "version",
+ "field": "version",
+ "type": "string",
+ "format": {}
+ },
+ {
+ "name": "description",
+ "title": "description",
+ "field": "description",
+ "type": "string",
+ "format": {}
+ }
+ ],
+ "type": "array",
+ "data": [
+ {
+ "id": "f37123ec",
+ "url": "",
+ "name": "ng-material",
+ "tenant": "",
+ "content": "",
+ "version": "1.0.0",
+ "framework": "Angular",
+ "published": "",
+ "components": "",
+ "created_at": "2021-11-02T11:32:22.000Z",
+ "updated_at": "2021-11-02T11:32:22.000Z",
+ "description": "angular组件库物料",
+ "published_at": "2021-11-02T11:32:22.000Z",
+ "last_build_info": "",
+ "_id": "2a23e653"
+ },
+ {
+ "id": "f37123ec",
+ "url": "",
+ "name": "ng-material",
+ "tenant": "",
+ "content": "",
+ "version": "1.0.0",
+ "framework": "Angular",
+ "published": "",
+ "components": "",
+ "created_at": "2021-11-02T11:32:22.000Z",
+ "updated_at": "2021-11-02T11:32:22.000Z",
+ "description": "angular组件库物料",
+ "published_at": "2021-11-02T11:32:22.000Z",
+ "last_build_info": "",
+ "_id": "06b253be"
+ },
+ {
+ "id": "f37123ec",
+ "url": "",
+ "name": "ng-material",
+ "tenant": "",
+ "content": "",
+ "version": "1.0.0",
+ "framework": "Angular",
+ "published": "",
+ "components": "",
+ "created_at": "2021-11-02T11:32:22.000Z",
+ "updated_at": "2021-11-02T11:32:22.000Z",
+ "description": "angular组件库物料",
+ "published_at": "2021-11-02T11:32:22.000Z",
+ "last_build_info": "",
+ "_id": "c55a41ed"
+ },
+ {
+ "id": "f37123ec",
+ "url": "",
+ "name": "ng-material",
+ "tenant": "",
+ "content": "",
+ "version": "1.0.0",
+ "framework": "Angular",
+ "published": "",
+ "components": "",
+ "created_at": "2021-11-02T11:32:22.000Z",
+ "updated_at": "2021-11-02T11:32:22.000Z",
+ "description": "angular组件库物料",
+ "published_at": "2021-11-02T11:32:22.000Z",
+ "last_build_info": "",
+ "_id": "f37123ec"
+ },
+ {
+ "id": "7a63c1a2",
+ "url": "",
+ "name": "tiny-vue",
+ "tenant": "",
+ "content": "Tiny Vue物料",
+ "version": "1.0.0",
+ "framework": "Vue",
+ "published": "",
+ "components": "",
+ "created_at": "",
+ "updated_at": "",
+ "description": "Tiny Vue物料",
+ "published_at": "",
+ "last_build_info": "",
+ "_id": "7a63c1a2"
}
+ ],
+ "options": {
+ "uri": "",
+ "method": "GET"
+ },
+ "willFetch": {
+ "type": "JSFunction",
+ "value": "function willFetch(option) {\n return option \n}"
},
- "tpl": null,
- "app": "1",
- "desc": null,
- "created_at": "2022-06-28T07:32:16.000Z",
- "updated_at": "2023-01-19T03:29:11.000Z"
+ "dataHandler": {
+ "type": "JSFunction",
+ "value": "function dataHandler(data) { \n return data \n}"
+ },
+ "shouldFetch": {
+ "type": "JSFunction",
+ "value": "function shouldFetch(option) {\n return true \n}"
+ },
+ "errorHandler": {
+ "type": "JSFunction",
+ "value": "function errorHandler(err) {}"
+ }
},
- {
- "id": 135,
- "name": "getAllMaterialList",
- "data": {
- "columns": [
- {
- "name": "id",
- "title": "id",
- "field": "id",
- "type": "string",
- "format": {}
- },
- {
- "name": "name",
- "title": "name",
- "field": "name",
- "type": "string",
- "format": {}
- },
- {
- "name": "framework",
- "title": "framework",
- "field": "framework",
- "type": "string",
- "format": {
- "required": true
- }
- },
- {
- "name": "components",
- "title": "components",
- "field": "components",
- "type": "string",
- "format": {}
- },
- {
- "name": "content",
- "title": "content",
- "field": "content",
- "type": "string",
- "format": {}
- },
- {
- "name": "url",
- "title": "url",
- "field": "url",
- "type": "string",
- "format": {}
- },
- {
- "name": "published_at",
- "title": "published_at",
- "field": "published_at",
- "type": "string",
- "format": {}
- },
- {
- "name": "created_at",
- "title": "created_at",
- "field": "created_at",
- "type": "string",
- "format": {}
- },
- {
- "name": "updated_at",
- "title": "updated_at",
- "field": "updated_at",
- "type": "string",
- "format": {}
- },
- {
- "name": "published",
- "title": "published",
- "field": "published",
- "type": "string",
- "format": {}
- },
- {
- "name": "last_build_info",
- "title": "last_build_info",
- "field": "last_build_info",
- "type": "string",
- "format": {}
- },
- {
- "name": "tenant",
- "title": "tenant",
- "field": "tenant",
- "type": "string",
- "format": {}
- },
- {
- "name": "version",
- "title": "version",
- "field": "version",
- "type": "string",
- "format": {}
- },
- {
- "name": "description",
- "title": "description",
- "field": "description",
- "type": "string",
- "format": {}
- }
- ],
- "type": "array",
- "data": [
- {
- "id": "f37123ec",
- "url": "",
- "name": "ng-material",
- "tenant": "",
- "content": "",
- "version": "1.0.0",
- "framework": "Angular",
- "published": "",
- "components": "",
- "created_at": "2021-11-02T11:32:22.000Z",
- "updated_at": "2021-11-02T11:32:22.000Z",
- "description": "angular组件库物料",
- "published_at": "2021-11-02T11:32:22.000Z",
- "last_build_info": "",
- "_id": "2a23e653"
- },
- {
- "id": "f37123ec",
- "url": "",
- "name": "ng-material",
- "tenant": "",
- "content": "",
- "version": "1.0.0",
- "framework": "Angular",
- "published": "",
- "components": "",
- "created_at": "2021-11-02T11:32:22.000Z",
- "updated_at": "2021-11-02T11:32:22.000Z",
- "description": "angular组件库物料",
- "published_at": "2021-11-02T11:32:22.000Z",
- "last_build_info": "",
- "_id": "06b253be"
- },
- {
- "id": "f37123ec",
- "url": "",
- "name": "ng-material",
- "tenant": "",
- "content": "",
- "version": "1.0.0",
- "framework": "Angular",
- "published": "",
- "components": "",
- "created_at": "2021-11-02T11:32:22.000Z",
- "updated_at": "2021-11-02T11:32:22.000Z",
- "description": "angular组件库物料",
- "published_at": "2021-11-02T11:32:22.000Z",
- "last_build_info": "",
- "_id": "c55a41ed"
- },
- {
- "id": "f37123ec",
- "url": "",
- "name": "ng-material",
- "tenant": "",
- "content": "",
- "version": "1.0.0",
- "framework": "Angular",
- "published": "",
- "components": "",
- "created_at": "2021-11-02T11:32:22.000Z",
- "updated_at": "2021-11-02T11:32:22.000Z",
- "description": "angular组件库物料",
- "published_at": "2021-11-02T11:32:22.000Z",
- "last_build_info": "",
- "_id": "f37123ec"
- },
- {
- "id": "7a63c1a2",
- "url": "",
- "name": "tiny-vue",
- "tenant": "",
- "content": "Tiny Vue物料",
- "version": "1.0.0",
- "framework": "Vue",
- "published": "",
- "components": "",
- "created_at": "",
- "updated_at": "",
- "description": "Tiny Vue物料",
- "published_at": "",
- "last_build_info": "",
- "_id": "7a63c1a2"
- }
- ],
- "options": {
- "uri": "",
- "method": "GET"
+ "tpl": null,
+ "app": "1",
+ "desc": null,
+ "created_at": "2022-06-29T00:57:50.000Z",
+ "updated_at": "2023-05-15T02:37:12.000Z"
+ },
+ {
+ "id": 139,
+ "name": "treedata",
+ "data": {
+ "data": [
+ {
+ "label": "level111",
+ "value": "111",
+ "id": "f6609643",
+ "pid": "",
+ "_RID": "row_4"
+ },
+ {
+ "label": "level1-son",
+ "value": "111-1",
+ "id": "af1f937f",
+ "pid": "f6609643",
+ "_RID": "row_5"
},
- "willFetch": {
- "type": "JSFunction",
- "value": "function willFetch(option) {\n return option \n}"
+ {
+ "label": "level222",
+ "value": "222",
+ "id": "28e3709c",
+ "pid": "",
+ "_RID": "row_6"
},
- "dataHandler": {
- "type": "JSFunction",
- "value": "function dataHandler(data) { \n return data \n}"
+ {
+ "label": "level2-son",
+ "value": "222-1",
+ "id": "6b571bef",
+ "pid": "28e3709c",
+ "_RID": "row_5"
},
- "shouldFetch": {
- "type": "JSFunction",
- "value": "function shouldFetch(option) {\n return true \n}"
+ {
+ "id": "6317c2cc",
+ "pid": "fdfa",
+ "label": "fsdfaa",
+ "value": "fsadf",
+ "_RID": "row_6"
},
- "errorHandler": {
- "type": "JSFunction",
- "value": "function errorHandler(err) {}"
+ {
+ "id": "9cce369f",
+ "pid": "test",
+ "label": "test1",
+ "value": "001"
}
- },
- "tpl": null,
- "app": "1",
- "desc": null,
- "created_at": "2022-06-29T00:57:50.000Z",
- "updated_at": "2023-05-15T02:37:12.000Z"
+ ],
+ "type": "tree"
},
- {
- "id": 139,
- "name": "treedata",
- "data": {
- "data": [
- {
- "label": "level111",
- "value": "111",
- "id": "f6609643",
- "pid": "",
- "_RID": "row_4"
- },
- {
- "label": "level1-son",
- "value": "111-1",
- "id": "af1f937f",
- "pid": "f6609643",
- "_RID": "row_5"
- },
- {
- "label": "level222",
- "value": "222",
- "id": "28e3709c",
- "pid": "",
- "_RID": "row_6"
- },
- {
- "label": "level2-son",
- "value": "222-1",
- "id": "6b571bef",
- "pid": "28e3709c",
- "_RID": "row_5"
- },
- {
- "id": "6317c2cc",
- "pid": "fdfa",
- "label": "fsdfaa",
- "value": "fsadf",
- "_RID": "row_6"
- },
- {
- "id": "9cce369f",
- "pid": "test",
- "label": "test1",
- "value": "001"
+ "tpl": null,
+ "app": "1",
+ "desc": null,
+ "created_at": "2022-06-30T06:13:57.000Z",
+ "updated_at": "2022-07-29T03:14:55.000Z"
+ },
+ {
+ "id": 150,
+ "name": "componentList",
+ "data": {
+ "data": [
+ {
+ "_RID": "row_1",
+ "name": "表单",
+ "isSelected": "true",
+ "description": "由按钮、输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据"
+ },
+ {
+ "name": "按钮",
+ "isSelected": "false",
+ "description": "常用的操作按钮,提供包括默认按钮、图标按钮、图片按钮、下拉按钮等类型"
+ },
+ {
+ "id": "490f8a00",
+ "_RID": "row_3",
+ "name": "表单项",
+ "framework": "",
+ "materials": "",
+ "description": "Form 组件下的 FormItem 配置"
+ },
+ {
+ "id": "c259b8b3",
+ "_RID": "row_4",
+ "name": "开关",
+ "framework": "",
+ "materials": "",
+ "description": "关闭或打开"
+ },
+ {
+ "id": "083ed9c7",
+ "_RID": "row_5",
+ "name": "互斥按钮组",
+ "framework": "",
+ "materials": "",
+ "description": "以按钮组的方式出现,常用于多项类似操作"
+ },
+ {
+ "id": "09136cea",
+ "_RID": "row_6",
+ "name": "提示框",
+ "framework": "",
+ "materials": "",
+ "description": "Popover可通过对一个触发源操作触发弹出框,支持自定义弹出内容,延迟触发和渐变动画"
+ },
+ {
+ "id": "a63b57d5",
+ "_RID": "row_7",
+ "name": "文字提示框",
+ "framework": "",
+ "materials": "",
+ "description": "动态显示提示信息,一般通过鼠标事件进行响应;提供 warning、error、info、success 四种类型显示不同类别的信"
+ },
+ {
+ "id": "a0f6e8a3",
+ "_RID": "row_8",
+ "name": "树",
+ "framework": "",
+ "materials": "",
+ "description": "可进行展示有父子层级的数据,支持选择,异步加载等功能。但不推荐用它来展示菜单,展示菜单推荐使用树菜单"
+ },
+ {
+ "id": "d1aa18fc",
+ "_RID": "row_9",
+ "name": "分页",
+ "framework": "",
+ "materials": "",
+ "description": "当数据量过多时,使用分页分解数据,常用于 Grid 和 Repeater 组件"
+ },
+ {
+ "id": "ca49cc52",
+ "_RID": "row_10",
+ "name": "表格",
+ "framework": "",
+ "materials": "",
+ "description": "提供了非常强大数据表格功能,可以展示数据列表,可以对数据列表进行选择、编辑等"
+ },
+ {
+ "id": "4e20ecc9",
+ "name": "搜索框",
+ "framework": "",
+ "materials": "",
+ "description": "指定条件对象进行搜索数据"
+ },
+ {
+ "id": "6b093ee5",
+ "name": "折叠面板",
+ "framework": "",
+ "materials": "",
+ "description": "内容区可指定动态页面或自定义 html 等,支持展开收起操作"
+ },
+ {
+ "id": "0a09abc0",
+ "name": "对话框",
+ "framework": "",
+ "materials": "",
+ "description": "模态对话框,在浮层中显示,引导用户进行相关操作"
+ },
+ {
+ "id": "f814b901",
+ "name": "标签页签项",
+ "framework": "",
+ "materials": "",
+ "description": "tab页签"
+ },
+ {
+ "id": "c5ae797c",
+ "name": "单选",
+ "framework": "",
+ "materials": "",
+ "description": "用于配置不同场景的选项,在一组备选项中进行单选"
+ },
+ {
+ "id": "33d0c590",
+ "_RID": "row_13",
+ "name": "弹出编辑",
+ "framework": "",
+ "materials": "",
+ "description": "该组件只能在弹出的面板中选择数据,不能手动输入数据;弹出面板中显示为 Tree 组件或者 Grid 组件"
+ },
+ {
+ "id": "16711dfa",
+ "_RID": "row_14",
+ "name": "下拉框",
+ "framework": "",
+ "materials": "",
+ "description": "Select 选择器是一种通过点击弹出下拉列表展示数据并进行选择的 UI 组件"
+ },
+ {
+ "id": "a9fd190a",
+ "_RID": "row_15",
+ "name": "折叠面板项",
+ "framework": "",
+ "materials": "",
+ "description": "内容区可指定动态页面或自定义 html 等,支持展开收起操作"
+ },
+ {
+ "id": "a7dfa9ec",
+ "_RID": "row_16",
+ "name": "复选框",
+ "framework": "",
+ "materials": "",
+ "description": "用于配置不同场景的选项,提供用户可在一组选项中进行多选"
+ },
+ {
+ "id": "d4bb8330",
+ "name": "输入框",
+ "framework": "",
+ "materials": "",
+ "description": "通过鼠标或键盘输入字符"
+ },
+ {
+ "id": "ced3dc83",
+ "name": "时间线",
+ "framework": "",
+ "materials": "",
+ "description": "时间线"
+ }
+ ],
+ "type": "array",
+ "columns": [
+ {
+ "name": "name",
+ "type": "string",
+ "field": "name",
+ "title": "name",
+ "format": {
+ "max": 0,
+ "min": 0,
+ "dateTime": false,
+ "required": false,
+ "stringType": ""
+ }
+ },
+ {
+ "name": "description",
+ "type": "string",
+ "field": "description",
+ "title": "description",
+ "format": {
+ "max": 0,
+ "min": 0,
+ "dateTime": false,
+ "required": false,
+ "stringType": ""
+ }
+ },
+ {
+ "name": "isSelected",
+ "type": "string",
+ "field": "isSelected",
+ "title": "isSelected",
+ "format": {
+ "max": 0,
+ "min": 0,
+ "dateTime": false,
+ "required": false,
+ "stringType": ""
}
- ],
- "type": "tree"
+ }
+ ],
+ "options": {
+ "uri": "http://localhost:9090/assets/json/bundle.json",
+ "method": "GET"
+ },
+ "willFetch": {
+ "type": "JSFunction",
+ "value": "function willFetch(option) {\n return option \n}"
+ },
+ "dataHandler": {
+ "type": "JSFunction",
+ "value": "function dataHandler(data) { \n return data \n}"
+ },
+ "shouldFetch": {
+ "type": "JSFunction",
+ "value": "function shouldFetch(option) {\n return true \n}"
},
- "tpl": null,
- "app": "1",
- "desc": null,
- "created_at": "2022-06-30T06:13:57.000Z",
- "updated_at": "2022-07-29T03:14:55.000Z"
+ "errorHandler": {
+ "type": "JSFunction",
+ "value": "function errorHandler(err) {}"
+ }
},
- {
- "id": 150,
- "name": "componentList",
- "data": {
- "data": [
- {
- "_RID": "row_1",
- "name": "表单",
- "isSelected": "true",
- "description": "由按钮、输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据"
- },
- {
- "name": "按钮",
- "isSelected": "false",
- "description": "常用的操作按钮,提供包括默认按钮、图标按钮、图片按钮、下拉按钮等类型"
- },
- {
- "id": "490f8a00",
- "_RID": "row_3",
- "name": "表单项",
- "framework": "",
- "materials": "",
- "description": "Form 组件下的 FormItem 配置"
- },
- {
- "id": "c259b8b3",
- "_RID": "row_4",
- "name": "开关",
- "framework": "",
- "materials": "",
- "description": "关闭或打开"
- },
- {
- "id": "083ed9c7",
- "_RID": "row_5",
- "name": "互斥按钮组",
- "framework": "",
- "materials": "",
- "description": "以按钮组的方式出现,常用于多项类似操作"
- },
- {
- "id": "09136cea",
- "_RID": "row_6",
- "name": "提示框",
- "framework": "",
- "materials": "",
- "description": "Popover可通过对一个触发源操作触发弹出框,支持自定义弹出内容,延迟触发和渐变动画"
- },
- {
- "id": "a63b57d5",
- "_RID": "row_7",
- "name": "文字提示框",
- "framework": "",
- "materials": "",
- "description": "动态显示提示信息,一般通过鼠标事件进行响应;提供 warning、error、info、success 四种类型显示不同类别的信"
- },
- {
- "id": "a0f6e8a3",
- "_RID": "row_8",
- "name": "树",
- "framework": "",
- "materials": "",
- "description": "可进行展示有父子层级的数据,支持选择,异步加载等功能。但不推荐用它来展示菜单,展示菜单推荐使用树菜单"
- },
- {
- "id": "d1aa18fc",
- "_RID": "row_9",
- "name": "分页",
- "framework": "",
- "materials": "",
- "description": "当数据量过多时,使用分页分解数据,常用于 Grid 和 Repeater 组件"
- },
- {
- "id": "ca49cc52",
- "_RID": "row_10",
- "name": "表格",
- "framework": "",
- "materials": "",
- "description": "提供了非常强大数据表格功能,可以展示数据列表,可以对数据列表进行选择、编辑等"
- },
- {
- "id": "4e20ecc9",
- "name": "搜索框",
- "framework": "",
- "materials": "",
- "description": "指定条件对象进行搜索数据"
- },
- {
- "id": "6b093ee5",
- "name": "折叠面板",
- "framework": "",
- "materials": "",
- "description": "内容区可指定动态页面或自定义 html 等,支持展开收起操作"
- },
- {
- "id": "0a09abc0",
- "name": "对话框",
- "framework": "",
- "materials": "",
- "description": "模态对话框,在浮层中显示,引导用户进行相关操作"
- },
- {
- "id": "f814b901",
- "name": "标签页签项",
- "framework": "",
- "materials": "",
- "description": "tab页签"
- },
- {
- "id": "c5ae797c",
- "name": "单选",
- "framework": "",
- "materials": "",
- "description": "用于配置不同场景的选项,在一组备选项中进行单选"
- },
- {
- "id": "33d0c590",
- "_RID": "row_13",
- "name": "弹出编辑",
- "framework": "",
- "materials": "",
- "description": "该组件只能在弹出的面板中选择数据,不能手动输入数据;弹出面板中显示为 Tree 组件或者 Grid 组件"
- },
- {
- "id": "16711dfa",
- "_RID": "row_14",
- "name": "下拉框",
- "framework": "",
- "materials": "",
- "description": "Select 选择器是一种通过点击弹出下拉列表展示数据并进行选择的 UI 组件"
- },
- {
- "id": "a9fd190a",
- "_RID": "row_15",
- "name": "折叠面板项",
- "framework": "",
- "materials": "",
- "description": "内容区可指定动态页面或自定义 html 等,支持展开收起操作"
- },
- {
- "id": "a7dfa9ec",
- "_RID": "row_16",
- "name": "复选框",
- "framework": "",
- "materials": "",
- "description": "用于配置不同场景的选项,提供用户可在一组选项中进行多选"
- },
- {
- "id": "d4bb8330",
- "name": "输入框",
- "framework": "",
- "materials": "",
- "description": "通过鼠标或键盘输入字符"
- },
- {
- "id": "ced3dc83",
- "name": "时间线",
- "framework": "",
- "materials": "",
- "description": "时间线"
+ "tpl": null,
+ "app": "1",
+ "desc": null,
+ "created_at": "2022-07-04T02:20:07.000Z",
+ "updated_at": "2022-07-04T06:25:29.000Z"
+ },
+ {
+ "id": 151,
+ "name": "selectedComponents",
+ "data": {
+ "columns": [
+ {
+ "name": "name",
+ "title": "name",
+ "field": "name",
+ "type": "string",
+ "format": {
+ "required": false,
+ "stringType": "",
+ "min": 0,
+ "max": 0,
+ "dateTime": false
}
- ],
- "type": "array",
- "columns": [
- {
- "name": "name",
- "type": "string",
- "field": "name",
- "title": "name",
- "format": {
- "max": 0,
- "min": 0,
- "dateTime": false,
- "required": false,
- "stringType": ""
- }
- },
- {
- "name": "description",
- "type": "string",
- "field": "description",
- "title": "description",
- "format": {
- "max": 0,
- "min": 0,
- "dateTime": false,
- "required": false,
- "stringType": ""
- }
- },
- {
- "name": "isSelected",
- "type": "string",
- "field": "isSelected",
- "title": "isSelected",
- "format": {
- "max": 0,
- "min": 0,
- "dateTime": false,
- "required": false,
- "stringType": ""
- }
+ },
+ {
+ "name": "description",
+ "title": "description",
+ "field": "description",
+ "type": "string",
+ "format": {
+ "required": false,
+ "stringType": "",
+ "min": 0,
+ "max": 0,
+ "dateTime": false
}
- ],
- "options": {
- "uri": "http://localhost:9090/assets/json/bundle.json",
- "method": "GET"
},
- "willFetch": {
- "type": "JSFunction",
- "value": "function willFetch(option) {\n return option \n}"
+ {
+ "name": "isSelected",
+ "title": "isSelected",
+ "field": "isSelected",
+ "type": "string",
+ "format": {
+ "required": false,
+ "stringType": "",
+ "min": 0,
+ "max": 0,
+ "dateTime": false
+ }
+ }
+ ],
+ "type": "array",
+ "data": [
+ {
+ "name": "标签页",
+ "description": "分隔内容上有关联但属于不同类别的数据集合",
+ "isSelected": "true",
+ "_RID": "row_2"
},
- "dataHandler": {
- "type": "JSFunction",
- "value": "function dataHandler(data) { \n return data \n}"
+ {
+ "name": "布局列",
+ "description": "列配置信息",
+ "isSelected": "true",
+ "id": "76a7080a",
+ "_RID": "row_4"
},
- "shouldFetch": {
- "type": "JSFunction",
- "value": "function shouldFetch(option) {\n return true \n}"
+ {
+ "name": "日期选择器",
+ "description": "用于设置/选择日期,包括年月/年月日/年月日时分/年月日时分秒日期格式",
+ "isSelected": "true",
+ "id": "76b20d73",
+ "_RID": "row_1"
},
- "errorHandler": {
- "type": "JSFunction",
- "value": "function errorHandler(err) {}"
+ {
+ "name": "走马灯",
+ "description": "常用于一组图片或卡片轮播,当内容空间不足时,可以用走马灯的形式进行收纳,进行轮播展现",
+ "isSelected": "true",
+ "id": "4c884c3d"
}
- },
- "tpl": null,
- "app": "1",
- "desc": null,
- "created_at": "2022-07-04T02:20:07.000Z",
- "updated_at": "2022-07-04T06:25:29.000Z"
+ ]
},
- {
- "id": 151,
- "name": "selectedComponents",
- "data": {
- "columns": [
- {
- "name": "name",
- "title": "name",
- "field": "name",
- "type": "string",
- "format": {
- "required": false,
- "stringType": "",
- "min": 0,
- "max": 0,
- "dateTime": false
- }
- },
- {
- "name": "description",
- "title": "description",
- "field": "description",
- "type": "string",
- "format": {
- "required": false,
- "stringType": "",
- "min": 0,
- "max": 0,
- "dateTime": false
- }
- },
- {
- "name": "isSelected",
- "title": "isSelected",
- "field": "isSelected",
- "type": "string",
- "format": {
- "required": false,
- "stringType": "",
- "min": 0,
- "max": 0,
- "dateTime": false
- }
- }
- ],
- "type": "array",
- "data": [
- {
- "name": "标签页",
- "description": "分隔内容上有关联但属于不同类别的数据集合",
- "isSelected": "true",
- "_RID": "row_2"
- },
- {
- "name": "布局列",
- "description": "列配置信息",
- "isSelected": "true",
- "id": "76a7080a",
- "_RID": "row_4"
- },
- {
- "name": "日期选择器",
- "description": "用于设置/选择日期,包括年月/年月日/年月日时分/年月日时分秒日期格式",
- "isSelected": "true",
- "id": "76b20d73",
- "_RID": "row_1"
- },
- {
- "name": "走马灯",
- "description": "常用于一组图片或卡片轮播,当内容空间不足时,可以用走马灯的形式进行收纳,进行轮播展现",
- "isSelected": "true",
- "id": "4c884c3d"
- }
- ]
- },
- "tpl": null,
- "app": "1",
- "desc": null,
- "created_at": "2022-07-04T03:04:05.000Z",
- "updated_at": "2022-07-04T03:43:40.000Z"
- }
- ],
- "dataHandler": {
- "type": "JSFunction",
- "value": "function dataHanlder(res){\n return res;\n}"
+ "tpl": null,
+ "app": "1",
+ "desc": null,
+ "created_at": "2022-07-04T03:04:05.000Z",
+ "updated_at": "2022-07-04T03:43:40.000Z"
}
+ ],
+ "dataHandler": {
+ "type": "JSFunction",
+ "value": "function dataHanlder(res){\n return res;\n}"
+ }
+ },
+ "i18n": {
+ "zh_CN": {
+ "lowcode.cca8d0ea": "应用",
+ "lowcode.c257d5e8": "查询",
+ "lowcode.61c8ac8c": "地方",
+ "lowcode.f53187a0": "测试",
+ "lowcode.97ad00dd": "创建物料资产包",
+ "lowcode.61dcef52": "terterere",
+ "lowcode.45f4c42a": "gdfgdf",
+ "lowcode.c6f5a652": "fsdaf",
+ "lowcode.34923432": "fdsafdsa",
+ "lowcode.48521e45": "fdsfds",
+ "lowcode.6534943e": "fdsafds",
+ "lowcode.44252642": "fdsafds",
+ "lowcode.2a743651": "sda",
+ "lowcode.24315357": "fdsafds",
+ "lowcode.44621691": "fdsafsd",
+ "lowcode.65636226": "fdsaf",
+ "lowcode.6426a4e2": "sd",
+ "lowcode.e41c6636": "aa",
+ "lowcode.51c23164": "aa",
+ "lowcode.17245b46": "aa",
+ "lowcode.4573143c": "aa",
+ "lowcode.56432442": "aa",
+ "lowcode.33566643": "aa",
+ "lowcode.565128f3": "aa",
+ "lowcode.56643835": "aa",
+ "lowcode.33311134": "aa",
+ "lowcode.44326643": "aa",
+ "lowcode.36223242": "aa"
},
- "i18n": {
- "zh_CN": {
- "lowcode.cca8d0ea": "应用",
- "lowcode.c257d5e8": "查询",
- "lowcode.61c8ac8c": "地方",
- "lowcode.f53187a0": "测试",
- "lowcode.97ad00dd": "创建物料资产包",
- "lowcode.61dcef52": "terterere",
- "lowcode.45f4c42a": "gdfgdf",
- "lowcode.c6f5a652": "fsdaf",
- "lowcode.34923432": "fdsafdsa",
- "lowcode.48521e45": "fdsfds",
- "lowcode.6534943e": "fdsafds",
- "lowcode.44252642": "fdsafds",
- "lowcode.2a743651": "sda",
- "lowcode.24315357": "fdsafds",
- "lowcode.44621691": "fdsafsd",
- "lowcode.65636226": "fdsaf",
- "lowcode.6426a4e2": "sd",
- "lowcode.e41c6636": "aa",
- "lowcode.51c23164": "aa",
- "lowcode.17245b46": "aa",
- "lowcode.4573143c": "aa",
- "lowcode.56432442": "aa",
- "lowcode.33566643": "aa",
- "lowcode.565128f3": "aa",
- "lowcode.56643835": "aa",
- "lowcode.33311134": "aa",
- "lowcode.44326643": "aa",
- "lowcode.36223242": "aa"
- },
- "en_US": {
- "lowcode.cca8d0ea": "app",
- "lowcode.c257d5e8": "search",
- "lowcode.61c8ac8c": "dsdsa",
- "lowcode.f53187a0": "test",
- "lowcode.97ad00dd": "createMaterial",
- "lowcode.61dcef52": "sadasda",
- "lowcode.45f4c42a": "gfdgfd",
- "lowcode.c6f5a652": "fsdafds",
- "lowcode.34923432": "fdsafds",
- "lowcode.6534943e": "fdsafdsa",
- "lowcode.44252642": "aaaa",
- "lowcode.2a743651": "fdsaf",
- "lowcode.24315357": "fsdafds",
- "lowcode.44621691": "sd",
- "lowcode.65636226": "fdsfsd",
- "lowcode.6426a4e2": "fdsafsd",
- "lowcode.e41c6636": "aa",
- "lowcode.51c23164": "aa",
- "lowcode.17245b46": "aa",
- "lowcode.4573143c": "a",
- "lowcode.56432442": "aa",
- "lowcode.33566643": "aa",
- "lowcode.565128f3": "aa",
- "lowcode.56643835": "aa",
- "lowcode.33311134": "aa",
- "lowcode.44326643": "aa",
- "lowcode.36223242": "aa"
+ "en_US": {
+ "lowcode.cca8d0ea": "app",
+ "lowcode.c257d5e8": "search",
+ "lowcode.61c8ac8c": "dsdsa",
+ "lowcode.f53187a0": "test",
+ "lowcode.97ad00dd": "createMaterial",
+ "lowcode.61dcef52": "sadasda",
+ "lowcode.45f4c42a": "gfdgfd",
+ "lowcode.c6f5a652": "fsdafds",
+ "lowcode.34923432": "fdsafds",
+ "lowcode.6534943e": "fdsafdsa",
+ "lowcode.44252642": "aaaa",
+ "lowcode.2a743651": "fdsaf",
+ "lowcode.24315357": "fsdafds",
+ "lowcode.44621691": "sd",
+ "lowcode.65636226": "fdsfsd",
+ "lowcode.6426a4e2": "fdsafsd",
+ "lowcode.e41c6636": "aa",
+ "lowcode.51c23164": "aa",
+ "lowcode.17245b46": "aa",
+ "lowcode.4573143c": "a",
+ "lowcode.56432442": "aa",
+ "lowcode.33566643": "aa",
+ "lowcode.565128f3": "aa",
+ "lowcode.56643835": "aa",
+ "lowcode.33311134": "aa",
+ "lowcode.44326643": "aa",
+ "lowcode.36223242": "aa"
+ }
+ },
+ "componentsTree": [],
+ "componentsMap": [
+ {
+ "componentName": "TinyCarouselItem",
+ "package": "@opentiny/vue",
+ "exportName": "CarouselItem",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyCheckboxButton",
+ "package": "@opentiny/vue",
+ "exportName": "CheckboxButton",
+ "destructuring": true,
+ "version": "0.1.17"
+ },
+ {
+ "componentName": "TinyTree",
+ "package": "@opentiny/vue",
+ "exportName": "Tree",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyPopover",
+ "package": "@opentiny/vue",
+ "exportName": "Popover",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyTooltip",
+ "package": "@opentiny/vue",
+ "exportName": "Tooltip",
+ "destructuring": true,
+ "version": "3.2.0"
+ },
+ {
+ "componentName": "TinyCol",
+ "package": "@opentiny/vue",
+ "exportName": "Col",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyDropdownItem",
+ "package": "@opentiny/vue",
+ "exportName": "DropdownItem",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyPager",
+ "package": "@opentiny/vue",
+ "exportName": "Pager",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyPlusAccessdeclined",
+ "package": "@opentiny/vue",
+ "exportName": "AccessDeclined",
+ "destructuring": true,
+ "version": "3.4.1"
+ },
+ {
+ "componentName": "TinyPlusFrozenPage",
+ "package": "@opentiny/vue",
+ "exportName": "FrozenPage",
+ "destructuring": true,
+ "version": "3.4.1"
+ },
+ {
+ "componentName": "TinyPlusNonSupportRegion",
+ "package": "@opentiny/vue",
+ "exportName": "NonSupportRegion",
+ "destructuring": true,
+ "version": "3.4.1"
+ },
+ {
+ "componentName": "TinyPlusBeta",
+ "package": "@opentiny/vue",
+ "exportName": "Beta",
+ "destructuring": true,
+ "version": "3.4.1"
+ },
+ {
+ "componentName": "TinySearch",
+ "package": "@opentiny/vue",
+ "exportName": "Search",
+ "destructuring": true,
+ "version": "0.1.13"
+ },
+ {
+ "componentName": "TinyRow",
+ "package": "@opentiny/vue",
+ "exportName": "Row",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyFormItem",
+ "package": "@opentiny/vue",
+ "exportName": "FormItem",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyAlert",
+ "package": "@opentiny/vue",
+ "exportName": "Alert",
+ "destructuring": true,
+ "version": "3.2.0"
+ },
+ {
+ "componentName": "TinyInput",
+ "package": "@opentiny/vue",
+ "exportName": "Input",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyTabs",
+ "package": "@opentiny/vue",
+ "exportName": "Tabs",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyDropdownMenu",
+ "package": "@opentiny/vue",
+ "exportName": "DropdownMenu",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyActionMenu",
+ "package": "@opentiny/vue",
+ "exportName": "ActionMenu",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyDialogBox",
+ "package": "@opentiny/vue",
+ "exportName": "DialogBox",
+ "destructuring": true,
+ "version": "3.2.0"
+ },
+ {
+ "componentName": "TinySwitch",
+ "package": "@opentiny/vue",
+ "exportName": "Switch",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyTimeLine",
+ "package": "@opentiny/vue",
+ "exportName": "TimeLine",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyTabItem",
+ "package": "@opentiny/vue",
+ "exportName": "TabItem",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyRadio",
+ "package": "@opentiny/vue",
+ "exportName": "Radio",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyForm",
+ "package": "@opentiny/vue",
+ "exportName": "Form",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyGrid",
+ "package": "@opentiny/vue",
+ "exportName": "Grid",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyGridColumn",
+ "package": "@opentiny/vue",
+ "exportName": "TinyGridColumn",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyNumeric",
+ "package": "@opentiny/vue",
+ "exportName": "Numeric",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyCheckboxGroup",
+ "package": "@opentiny/vue",
+ "exportName": "CheckboxGroup",
+ "destructuring": true,
+ "version": "0.1.17"
+ },
+ {
+ "componentName": "TinyCheckbox",
+ "package": "@opentiny/vue",
+ "exportName": "Checkbox",
+ "destructuring": true,
+ "version": "3.20.0"
+ },
+ {
+ "componentName": "TinySelect",
+ "package": "@opentiny/vue",
+ "exportName": "Select",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyButton",
+ "package": "@opentiny/vue",
+ "exportName": "Button",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyButtonGroup",
+ "package": "@opentiny/vue",
+ "exportName": "ButtonGroup",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyCarousel",
+ "package": "@opentiny/vue",
+ "exportName": "Carousel",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyPopeditor",
+ "package": "@opentiny/vue",
+ "exportName": "Popeditor",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyDatePicker",
+ "package": "@opentiny/vue",
+ "exportName": "DatePicker",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyDropdown",
+ "package": "@opentiny/vue",
+ "exportName": "Dropdown",
+ "destructuring": true,
+ "version": "0.1.20"
+ },
+ {
+ "componentName": "TinyChartHistogram",
+ "package": "@opentiny/vue",
+ "exportName": "ChartHistogram",
+ "destructuring": true,
+ "version": "0.1.16"
+ },
+ {
+ "componentName": "TinyCollapse",
+ "package": "@opentiny/vue",
+ "exportName": "Collapse",
+ "destructuring": true,
+ "version": "3.20.0"
+ },
+ {
+ "componentName": "TinyCollapseItem",
+ "package": "@opentiny/vue",
+ "exportName": "CollapseItem",
+ "destructuring": true,
+ "version": "3.20.0"
+ },
+ {
+ "componentName": "TinyBreadcrumb",
+ "package": "@opentiny/vue",
+ "exportName": "Breadcrumb",
+ "destructuring": true,
+ "version": "3.20.0"
+ },
+ {
+ "componentName": "TinyBreadcrumbItem",
+ "package": "@opentiny/vue",
+ "exportName": "BreadcrumbItem",
+ "destructuring": true,
+ "version": "3.20.0"
+ },
+ {
+ "componentName": "TinyRate",
+ "package": "@opentiny/vue",
+ "exportName": "TinyRate",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinySlider",
+ "package": "@opentiny/vue",
+ "exportName": "TinySlider",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyCascader",
+ "package": "@opentiny/vue",
+ "exportName": "TinyCascader",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinySteps",
+ "package": "@opentiny/vue",
+ "exportName": "TinySteps",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyTreeMenu",
+ "package": "@opentiny/vue",
+ "exportName": "TinyTreeMenu",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyRadioGroup",
+ "package": "@opentiny/vue",
+ "exportName": "TinyRadioGroup",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "ElInput",
+ "package": "element-plus",
+ "exportName": "ElInput",
+ "destructuring": true,
+ "version": "2.4.2"
+ },
+ {
+ "componentName": "ElButton",
+ "package": "element-plus",
+ "exportName": "ElButton",
+ "destructuring": true,
+ "version": "2.4.2"
+ },
+ {
+ "componentName": "ElForm",
+ "package": "element-plus",
+ "exportName": "ElForm",
+ "destructuring": true,
+ "version": "2.4.2"
+ },
+ {
+ "componentName": "ElFormItem",
+ "package": "element-plus",
+ "exportName": "ElFormItem",
+ "destructuring": true,
+ "version": "2.4.2"
+ },
+ {
+ "componentName": "ElTable",
+ "package": "element-plus",
+ "exportName": "ElTable",
+ "destructuring": true,
+ "version": "2.4.2"
+ },
+ {
+ "componentName": "ElTableColumn",
+ "package": "element-plus",
+ "exportName": "ElTableColumn",
+ "destructuring": true,
+ "version": "2.4.2"
+ },
+ {
+ "componentName": "TinyProgress",
+ "package": "@opentiny/vue",
+ "exportName": "TinyProgress",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinySkeleton",
+ "package": "@opentiny/vue",
+ "exportName": "TinySkeleton",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyCard",
+ "package": "@opentiny/vue",
+ "exportName": "TinyCard",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyCalendar",
+ "package": "@opentiny/vue",
+ "exportName": "TinyCalendar",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyBadge",
+ "package": "@opentiny/vue",
+ "exportName": "TinyBadge",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyTag",
+ "package": "@opentiny/vue",
+ "exportName": "TinyTag",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyStatistic",
+ "package": "@opentiny/vue",
+ "exportName": "TinyStatistic",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsFunnel",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsFunnel",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsScatter",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsScatter",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsWaterfall",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsWaterfall",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsLine",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsLine",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsHistogram",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsHistogram",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsPie",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsPie",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsBar",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsBar",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsRing",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsRing",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsRadar",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsRadar",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsGraph",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsGraph",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsProcess",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsProcess",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "TinyHuichartsGauge",
+ "package": "@opentiny/vue-huicharts",
+ "exportName": "TinyHuichartsGauge",
+ "destructuring": true,
+ "version": "3.22.0"
+ },
+ {
+ "componentName": "PortalHome",
+ "main": "common/components/home",
+ "destructuring": false,
+ "version": "1.0.0"
+ },
+ {
+ "componentName": "PreviewBlock1",
+ "main": "preview",
+ "destructuring": false,
+ "version": "1.0.0"
+ },
+ {
+ "componentName": "PortalHeader",
+ "main": "common",
+ "destructuring": false,
+ "version": "1.0.0"
+ },
+ {
+ "componentName": "PortalBlock",
+ "main": "portal",
+ "destructuring": false,
+ "version": "1.0.0"
+ },
+ {
+ "componentName": "PortalPermissionBlock",
+ "main": "",
+ "destructuring": false,
+ "version": "1.0.0"
+ }
+ ],
+ "bridge": [],
+ "utils": [
+ {
+ "name": "axios",
+ "type": "npm",
+ "content": {
+ "type": "JSFunction",
+ "value": "",
+ "package": "axios",
+ "destructuring": false,
+ "exportName": "axios",
+ "cdnLink": "https://registry.npmmirror.com/axios/1.7.9/files/dist/esm/axios.min.js"
}
},
- "componentsTree": [],
- "componentsMap": [
- {
- "componentName": "TinyCarouselItem",
- "package": "@opentiny/vue",
- "exportName": "CarouselItem",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyCheckboxButton",
- "package": "@opentiny/vue",
- "exportName": "CheckboxButton",
- "destructuring": true,
- "version": "0.1.17"
- },
- {
- "componentName": "TinyTree",
- "package": "@opentiny/vue",
- "exportName": "Tree",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyPopover",
- "package": "@opentiny/vue",
- "exportName": "Popover",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyTooltip",
- "package": "@opentiny/vue",
- "exportName": "Tooltip",
- "destructuring": true,
- "version": "3.2.0"
- },
- {
- "componentName": "TinyCol",
- "package": "@opentiny/vue",
- "exportName": "Col",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyDropdownItem",
- "package": "@opentiny/vue",
- "exportName": "DropdownItem",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyPager",
- "package": "@opentiny/vue",
- "exportName": "Pager",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyPlusAccessdeclined",
- "package": "@opentiny/vue",
- "exportName": "AccessDeclined",
- "destructuring": true,
- "version": "3.4.1"
- },
- {
- "componentName": "TinyPlusFrozenPage",
- "package": "@opentiny/vue",
- "exportName": "FrozenPage",
- "destructuring": true,
- "version": "3.4.1"
- },
- {
- "componentName": "TinyPlusNonSupportRegion",
- "package": "@opentiny/vue",
- "exportName": "NonSupportRegion",
- "destructuring": true,
- "version": "3.4.1"
- },
- {
- "componentName": "TinyPlusBeta",
- "package": "@opentiny/vue",
- "exportName": "Beta",
- "destructuring": true,
- "version": "3.4.1"
- },
- {
- "componentName": "TinySearch",
- "package": "@opentiny/vue",
- "exportName": "Search",
- "destructuring": true,
- "version": "0.1.13"
- },
- {
- "componentName": "TinyRow",
- "package": "@opentiny/vue",
- "exportName": "Row",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyFormItem",
- "package": "@opentiny/vue",
- "exportName": "FormItem",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyAlert",
- "package": "@opentiny/vue",
- "exportName": "Alert",
- "destructuring": true,
- "version": "3.2.0"
- },
- {
- "componentName": "TinyInput",
- "package": "@opentiny/vue",
- "exportName": "Input",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyTabs",
- "package": "@opentiny/vue",
- "exportName": "Tabs",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyDropdownMenu",
- "package": "@opentiny/vue",
- "exportName": "DropdownMenu",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyDialogBox",
- "package": "@opentiny/vue",
- "exportName": "DialogBox",
- "destructuring": true,
- "version": "3.2.0"
- },
- {
- "componentName": "TinySwitch",
- "package": "@opentiny/vue",
- "exportName": "Switch",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyTimeLine",
- "package": "@opentiny/vue",
- "exportName": "TimeLine",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyTabItem",
- "package": "@opentiny/vue",
- "exportName": "TabItem",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyRadio",
- "package": "@opentiny/vue",
- "exportName": "Radio",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyForm",
- "package": "@opentiny/vue",
- "exportName": "Form",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyGrid",
- "package": "@opentiny/vue",
- "exportName": "Grid",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyGridColumn",
- "package": "@opentiny/vue",
- "exportName": "TinyGridColumn",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyNumeric",
- "package": "@opentiny/vue",
- "exportName": "Numeric",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyCheckboxGroup",
- "package": "@opentiny/vue",
- "exportName": "CheckboxGroup",
- "destructuring": true,
- "version": "0.1.17"
- },
- {
- "componentName": "TinyCheckbox",
- "package": "@opentiny/vue",
- "exportName": "Checkbox",
- "destructuring": true,
- "version": "3.20.0"
- },
- {
- "componentName": "TinySelect",
- "package": "@opentiny/vue",
- "exportName": "Select",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyButton",
+ {
+ "name": "Button",
+ "type": "npm",
+ "content": {
"package": "@opentiny/vue",
+ "version": "",
"exportName": "Button",
+ "subName": "",
"destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyButtonGroup",
- "package": "@opentiny/vue",
- "exportName": "ButtonGroup",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyCarousel",
- "package": "@opentiny/vue",
- "exportName": "Carousel",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyPopeditor",
- "package": "@opentiny/vue",
- "exportName": "Popeditor",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyDatePicker",
- "package": "@opentiny/vue",
- "exportName": "DatePicker",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyDropdown",
- "package": "@opentiny/vue",
- "exportName": "Dropdown",
- "destructuring": true,
- "version": "0.1.20"
- },
- {
- "componentName": "TinyChartHistogram",
- "package": "@opentiny/vue",
- "exportName": "ChartHistogram",
- "destructuring": true,
- "version": "0.1.16"
- },
- {
- "componentName": "TinyCollapse",
- "package": "@opentiny/vue",
- "exportName": "Collapse",
- "destructuring": true,
- "version": "3.20.0"
- },
- {
- "componentName": "TinyCollapseItem",
- "package": "@opentiny/vue",
- "exportName": "CollapseItem",
- "destructuring": true,
- "version": "3.20.0"
- },
- {
- "componentName": "TinyBreadcrumb",
- "package": "@opentiny/vue",
- "exportName": "Breadcrumb",
- "destructuring": true,
- "version": "3.20.0"
- },
- {
- "componentName": "TinyBreadcrumbItem",
- "package": "@opentiny/vue",
- "exportName": "BreadcrumbItem",
- "destructuring": true,
- "version": "3.20.0"
- },
- {
- "componentName": "TinyRate",
- "package": "@opentiny/vue",
- "exportName": "TinyRate",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinySlider",
- "package": "@opentiny/vue",
- "exportName": "TinySlider",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyCascader",
- "package": "@opentiny/vue",
- "exportName": "TinyCascader",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinySteps",
- "package": "@opentiny/vue",
- "exportName": "TinySteps",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyTreeMenu",
- "package": "@opentiny/vue",
- "exportName": "TinyTreeMenu",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyRadioGroup",
- "package": "@opentiny/vue",
- "exportName": "TinyRadioGroup",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "ElInput",
- "package": "element-plus",
- "exportName": "ElInput",
- "destructuring": true,
- "version": "2.4.2"
- },
- {
- "componentName": "ElButton",
- "package": "element-plus",
- "exportName": "ElButton",
- "destructuring": true,
- "version": "2.4.2"
- },
- {
- "componentName": "ElForm",
- "package": "element-plus",
- "exportName": "ElForm",
- "destructuring": true,
- "version": "2.4.2"
- },
- {
- "componentName": "ElFormItem",
- "package": "element-plus",
- "exportName": "ElFormItem",
- "destructuring": true,
- "version": "2.4.2"
- },
- {
- "componentName": "ElTable",
- "package": "element-plus",
- "exportName": "ElTable",
- "destructuring": true,
- "version": "2.4.2"
- },
- {
- "componentName": "ElTableColumn",
- "package": "element-plus",
- "exportName": "ElTableColumn",
- "destructuring": true,
- "version": "2.4.2"
- },
- {
- "componentName": "TinyProgress",
- "package": "@opentiny/vue",
- "exportName": "TinyProgress",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinySkeleton",
- "package": "@opentiny/vue",
- "exportName": "TinySkeleton",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyCard",
- "package": "@opentiny/vue",
- "exportName": "TinyCard",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyCalendar",
- "package": "@opentiny/vue",
- "exportName": "TinyCalendar",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyBadge",
+ "main": ""
+ }
+ },
+ {
+ "name": "Menu",
+ "type": "npm",
+ "content": {
+ "type": "JSFunction",
+ "value": "",
"package": "@opentiny/vue",
- "exportName": "TinyBadge",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyTag",
+ "exportName": "NavMenu",
+ "destructuring": true
+ }
+ },
+ {
+ "name": "Modal ",
+ "type": "npm",
+ "content": {
"package": "@opentiny/vue",
- "exportName": "TinyTag",
+ "version": "",
+ "exportName": "Modal ",
+ "subName": "",
"destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyStatistic",
+ "main": ""
+ }
+ },
+ {
+ "name": "Pager",
+ "type": "npm",
+ "content": {
"package": "@opentiny/vue",
- "exportName": "TinyStatistic",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsFunnel",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsFunnel",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsScatter",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsScatter",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsWaterfall",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsWaterfall",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsLine",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsLine",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsHistogram",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsHistogram",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsPie",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsPie",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsBar",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsBar",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsRing",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsRing",
- "destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "TinyHuichartsRadar",
- "package": "@opentiny/vue-huicharts",
- "exportName": "TinyHuichartsRadar",
+ "version": "",
+ "exportName": "Pager",
+ "subName": "",
"destructuring": true,
- "version": "3.22.0"
- },
- {
- "componentName": "PortalHome",
- "main": "common/components/home",
- "destructuring": false,
- "version": "1.0.0"
- },
- {
- "componentName": "PreviewBlock1",
- "main": "preview",
- "destructuring": false,
- "version": "1.0.0"
- },
- {
- "componentName": "PortalHeader",
- "main": "common",
- "destructuring": false,
- "version": "1.0.0"
- },
- {
- "componentName": "PortalBlock",
- "main": "portal",
- "destructuring": false,
- "version": "1.0.0"
- },
- {
- "componentName": "PortalPermissionBlock",
- "main": "",
- "destructuring": false,
- "version": "1.0.0"
+ "main": ""
}
- ],
- "bridge": [],
- "utils": [
- {
- "name": "axios",
- "type": "npm",
- "content": {
- "type": "JSFunction",
- "value": "",
- "package": "axios",
- "destructuring": false,
- "exportName": "axios",
- "cdnLink": "https://registry.npmmirror.com/axios/1.7.9/files/dist/esm/axios.min.js"
- }
- },
- {
- "name": "Button",
- "type": "npm",
- "content": {
- "package": "@opentiny/vue",
- "version": "",
- "exportName": "Button",
- "subName": "",
- "destructuring": true,
- "main": ""
- }
- },
- {
- "name": "Menu",
- "type": "npm",
- "content": {
- "type": "JSFunction",
- "value": "",
- "package": "@opentiny/vue",
- "exportName": "NavMenu",
- "destructuring": true
- }
- },
- {
- "name": "Modal ",
- "type": "npm",
- "content": {
- "package": "@opentiny/vue",
- "version": "",
- "exportName": "Modal ",
- "subName": "",
- "destructuring": true,
- "main": ""
- }
- },
- {
- "name": "Pager",
- "type": "npm",
- "content": {
- "package": "@opentiny/vue",
- "version": "",
- "exportName": "Pager",
- "subName": "",
- "destructuring": true,
- "main": ""
- }
- },
- {
- "name": "test",
- "type": "function",
- "content": {
- "type": "JSFunction",
- "value": "function test() {\r\n return 'test'\r\n}"
- }
- },
- {
- "name": "util",
- "type": "function",
- "content": {
- "type": "JSFunction",
- "value": "function util () {\r\n console.log(321)\r\n}"
- }
+ },
+ {
+ "name": "test",
+ "type": "function",
+ "content": {
+ "type": "JSFunction",
+ "value": "function test() {\r\n return 'test'\r\n}"
}
- ],
- "config": {
- "sdkVersion": "1.0.3",
- "historyMode": "hash",
- "targetRootID": "app"
- },
- "constants": "",
- "css": "",
- "version": ""
+ },
+ {
+ "name": "util",
+ "type": "function",
+ "content": {
+ "type": "JSFunction",
+ "value": "function util () {\r\n console.log(321)\r\n}"
+ }
+ }
+ ],
+ "config": {
+ "sdkVersion": "1.0.3",
+ "historyMode": "hash",
+ "targetRootID": "app"
},
- "locale": "zh-cn"
- }
-
\ No newline at end of file
+ "constants": "",
+ "css": "",
+ "version": ""
+ },
+ "locale": "zh-cn"
+}
diff --git a/mockServer/src/services/model.js b/mockServer/src/services/model.js
index debb6493dd..e1d2e838f2 100644
--- a/mockServer/src/services/model.js
+++ b/mockServer/src/services/model.js
@@ -10,22 +10,51 @@
*
*/
-import { getResponseData } from '../tool/Common'
-import modelList from '../assets/json/model.json'
+import DateStore from '@seald-io/nedb'
+import { getDatabasePath, getResponseData } from '../tool/Common'
const defaultModel = {
- createdBy: '86',
- lastUpdatedBy: '86',
+ createdBy: '1',
+ lastUpdatedBy: '1',
tenantId: null,
renterId: null,
siteId: null,
appId: null,
platformId: 1,
- nameCn: 'test',
- nameEn: 'test',
+ nameCn: '',
+ nameEn: '',
version: '1.0.0',
- modelUrl: '1',
- parameters: [],
+ modelUrl: 'https://agent-alpha.opentiny.design/platform-center/api/model-data',
+ parameters: [
+ {
+ prop: 'id',
+ isModel: false,
+ type: 'Number',
+ required: true,
+ description: '主键'
+ },
+ {
+ prop: 'name',
+ isModel: false,
+ type: 'String',
+ required: true,
+ description: '姓名'
+ },
+ {
+ prop: 'status',
+ isModel: false,
+ type: 'Enum',
+ options: '[{"value":"1","label":"已转正"},{"value":"0","label":"未转正"}]',
+ required: true,
+ description: '状态'
+ },
+ {
+ prop: 'test',
+ type: 'String',
+ required: false,
+ description: ''
+ }
+ ],
method: [
{
name: '新增方法',
@@ -33,13 +62,41 @@ const defaultModel = {
requestParameters: [
{
prop: 'nameEn',
- type: 'String',
- children: null
+ type: 'String'
},
{
prop: 'params',
type: 'Object',
- children: []
+ children: [
+ {
+ prop: 'id',
+ isModel: false,
+ type: 'Number',
+ required: true,
+ description: '主键'
+ },
+ {
+ prop: 'name',
+ isModel: false,
+ type: 'String',
+ required: true,
+ description: '姓名'
+ },
+ {
+ prop: 'status',
+ isModel: false,
+ type: 'Enum',
+ options: '[{"value":"1","label":"已转正"},{"value":"0","label":"未转正"}]',
+ required: true,
+ description: '状态'
+ },
+ {
+ prop: 'test',
+ type: 'String',
+ required: false,
+ description: ''
+ }
+ ]
}
],
responseParameters: [
@@ -63,18 +120,75 @@ const defaultModel = {
requestParameters: [
{
prop: 'nameEn',
- type: 'String',
- children: null
+ type: 'String'
},
{
prop: 'data',
type: 'Object',
- children: []
+ children: [
+ {
+ prop: 'id',
+ isModel: false,
+ type: 'Number',
+ required: true,
+ description: '主键'
+ },
+ {
+ prop: 'name',
+ isModel: false,
+ type: 'String',
+ required: true,
+ description: '姓名'
+ },
+ {
+ prop: 'status',
+ isModel: false,
+ type: 'Enum',
+ options: '[{"value":"1","label":"已转正"},{"value":"0","label":"未转正"}]',
+ required: true,
+ description: '状态'
+ },
+ {
+ prop: 'test',
+ type: 'String',
+ required: false,
+ description: ''
+ }
+ ]
},
{
prop: 'params',
type: 'Object',
- children: []
+ children: [
+ {
+ prop: 'id',
+ isModel: false,
+ type: 'Number',
+ required: true,
+ description: '主键'
+ },
+ {
+ prop: 'name',
+ isModel: false,
+ type: 'String',
+ required: true,
+ description: '姓名'
+ },
+ {
+ prop: 'status',
+ isModel: false,
+ type: 'Enum',
+ options: '[{"value":"1","label":"已转正"},{"value":"0","label":"未转正"}]',
+ required: true,
+ description: '状态'
+ },
+ {
+ prop: 'test',
+ type: 'String',
+ required: false,
+ description: ''
+ }
+ ]
}
],
responseParameters: [
@@ -98,28 +212,53 @@ const defaultModel = {
requestParameters: [
{
prop: 'nameEn',
- type: 'String',
- children: null
+ type: 'String'
},
{
prop: 'currentPage',
- type: 'Number',
- children: null
+ type: 'Number'
},
{
prop: 'pageSize',
- type: 'Number',
- children: null
+ type: 'Number'
},
{
prop: 'nameCn',
- type: 'String',
- children: null
+ type: 'String'
},
{
prop: 'params',
type: 'Object',
- children: []
+ children: [
+ {
+ prop: 'id',
+ isModel: false,
+ type: 'Number',
+ required: true,
+ description: '主键'
+ },
+ {
+ prop: 'name',
+ isModel: false,
+ type: 'String',
+ required: true,
+ description: '姓名'
+ },
+ {
+ prop: 'status',
+ isModel: false,
+ type: 'Enum',
+ options: '[{"value":"1","label":"已转正"},{"value":"0","label":"未转正"}]',
+ required: true,
+ description: '状态'
+ },
+ {
+ prop: 'test',
+ type: 'String',
+ required: false,
+ description: ''
+ }
+ ]
}
],
responseParameters: [
@@ -147,13 +286,11 @@ const defaultModel = {
requestParameters: [
{
prop: 'nameEn',
- type: 'String',
- children: null
+ type: 'String'
},
{
prop: 'id',
- type: 'Number',
- children: null
+ type: 'Number'
}
],
responseParameters: [
@@ -172,49 +309,56 @@ const defaultModel = {
]
}
],
- description: '',
- created_at: '2026-01-30 04:34:25',
- updated_at: '2026-01-30 04:34:25'
+ description: ''
}
-export default class AppsService {
+export default class ModelService {
constructor() {
- this.modelList = modelList
+ this.db = new DateStore({
+ filename: getDatabasePath('model.db'),
+ autoload: true
+ })
+
+ this.db.ensureIndex({
+ fieldName: '_id',
+ unique: true
+ })
+ this.modelList = []
}
async create(params) {
- let mockId =
- this.modelList.data.records.length > 0 ? Math.max(...this.modelList.data.records.map((item) => item.id)) + 1 : 3
+ let mockId = this.modelList.length > 0 ? Math.max(...this.modelList.map((item) => item.id)) + 1 : 3
const newModel = {
...defaultModel,
id: mockId++,
+ created_at: new Date().toISOString(),
+ updated_at: new Date().toISOString(),
...params
}
- this.modelList.data.records.push(newModel)
- return getResponseData(newModel)
+
+ this.db.insert(newModel)
+ this.modelList.push(newModel)
+
+ return getResponseData({ records: this.modelList })
}
async delete(id) {
- this.modelList.data.records = this.modelList.data.records.filter((item) => Number(item.id) !== Number(id))
+ const result = await this.db.findOneAsync({ id: Number(id) })
+ await this.db.removeAsync({ id: Number(id) })
- return getResponseData(this.modelList.data)
+ return getResponseData(result)
}
async list() {
- return getResponseData(this.modelList.data)
+ this.modelList = await this.db.findAsync()
+
+ return getResponseData({ records: this.modelList })
}
async update(id, params) {
- const index = this.modelList.data.records.findIndex((item) => Number(item.id) === Number(id))
- if (index === -1) {
- return getResponseData({ success: false, message: '未找到应用' })
- }
-
- this.modelList.data.records[index] = {
- ...this.modelList.data.records[index],
- ...params
- }
+ await this.db.updateAsync({ id: Number(id) }, { $set: params })
+ const result = await this.db.findOneAsync({ id: Number(id) })
- return getResponseData(this.modelList.data.records[index])
+ return getResponseData(result)
}
}
diff --git a/mockServer/src/services/pages.js b/mockServer/src/services/pages.js
index c4d40e68f3..c1a71dcaad 100644
--- a/mockServer/src/services/pages.js
+++ b/mockServer/src/services/pages.js
@@ -13,6 +13,17 @@
import DateStore from '@seald-io/nedb'
import { getDatabasePath, getResponseData } from '../tool/Common'
+const parsePageContent = (item) => {
+ if (item && item.page_content && typeof item.page_content === 'string') {
+ try {
+ item.page_content = JSON.parse(item.page_content)
+ } catch (e) {
+ // ignore
+ }
+ }
+ return item
+}
+
export default class PageService {
constructor() {
this.db = new DateStore({
@@ -21,7 +32,7 @@ export default class PageService {
})
this.db.ensureIndex({
- fieldName: 'route',
+ fieldName: '_id',
unique: true
})
@@ -68,32 +79,64 @@ export default class PageService {
async create(params) {
const model = params.isPage ? this.pageModel : this.folderModel
const pageData = { ...model, ...params }
+
+ if (!pageData.route) {
+ pageData.route = pageData.name || 'Untitled'
+ }
+
+ const existing = await this.db.findOneAsync({
+ app: pageData.app.toString(),
+ route: pageData.route
+ })
+
+ if (existing) {
+ return getResponseData(null, {
+ code: 'ROUTE_CONFLICT',
+ message: `Route "${pageData.route}" already exists in app "${pageData.app}"`,
+ status: 409
+ })
+ }
+
+ if (pageData.page_content && typeof pageData.page_content === 'object') {
+ pageData.page_content = JSON.stringify(pageData.page_content)
+ }
+
const result = await this.db.insertAsync(pageData)
const { _id } = result
await this.db.updateAsync({ _id }, { $set: { id: _id } })
result.id = result._id
- return getResponseData(result)
+ return getResponseData(parsePageContent(result))
}
async update(id, params) {
- await this.db.updateAsync({ _id: id }, { $set: params })
+ const updateData = { ...params }
+ if (updateData.page_content && typeof updateData.page_content === 'object') {
+ updateData.page_content = JSON.stringify(updateData.page_content)
+ }
+
+ await this.db.updateAsync({ _id: id }, { $set: updateData })
const result = await this.db.findOneAsync({ _id: id })
- return getResponseData(result)
+ return getResponseData(parsePageContent(result))
}
async list(appId) {
const result = await this.db.findAsync({ app: appId.toString() })
+ if (Array.isArray(result)) {
+ result.forEach(parsePageContent)
+ }
return getResponseData(result)
}
async detail(pageId) {
const result = await this.db.findOneAsync({ _id: pageId })
- return getResponseData(result)
+
+ return getResponseData(parsePageContent(result))
}
async delete(pageId) {
const result = await this.db.findOneAsync({ _id: pageId })
+
await this.db.removeAsync({ _id: pageId })
- return getResponseData(result)
+ return getResponseData(parsePageContent(result))
}
}
diff --git a/packages/block-compiler/package.json b/packages/block-compiler/package.json
index 79f11f0ba1..34a34d5608 100644
--- a/packages/block-compiler/package.json
+++ b/packages/block-compiler/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentiny/tiny-engine-block-compiler",
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"publishConfig": {
"access": "public"
},
diff --git a/packages/build/vite-config/package.json b/packages/build/vite-config/package.json
index cfae6a23da..8f86fa7dae 100644
--- a/packages/build/vite-config/package.json
+++ b/packages/build/vite-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentiny/tiny-engine-vite-config",
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"description": "",
"type": "module",
"main": "./index.js",
diff --git a/packages/build/vite-plugin-meta-comments/package.json b/packages/build/vite-plugin-meta-comments/package.json
index 8eeedb386d..95c76b0a3a 100644
--- a/packages/build/vite-plugin-meta-comments/package.json
+++ b/packages/build/vite-plugin-meta-comments/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentiny/tiny-engine-vite-plugin-meta-comments",
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"description": "",
"type": "module",
"main": "dist/index.cjs",
diff --git a/packages/builtinComponent/package.json b/packages/builtinComponent/package.json
index 698cb422d8..67631de957 100644
--- a/packages/builtinComponent/package.json
+++ b/packages/builtinComponent/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentiny/tiny-engine-builtin-component",
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"description": "",
"main": "dist/index.mjs",
"module": "dist/index.mjs",
diff --git a/packages/canvas/DesignCanvas/src/api/types.ts b/packages/canvas/DesignCanvas/src/api/types.ts
index bb2a826645..4ba9f5be09 100644
--- a/packages/canvas/DesignCanvas/src/api/types.ts
+++ b/packages/canvas/DesignCanvas/src/api/types.ts
@@ -2,6 +2,28 @@ import type { Node, RootNode } from '../../../types'
export type PageSchema = RootNode
+export type AIHelperState = 'hidden' | 'chat' | 'loading' | 'confirm' | 'completed'
+
+export interface NodeAIStatus {
+ state: AIHelperState
+ collapsed?: boolean // 面板是否收起(收起时保留原状态,重新打开可恢复)
+ aiContext?: any
+ lastAIAction?: string
+ aiHistory?: Array<{
+ timestamp: number
+ action: string
+ content: any
+ }>
+ chatContent?: string // 聊天内容
+ // AI采纳状态相关字段
+ originalNodeData?: any // AI修改前的节点数据备份
+ aiModifiedNodeData?: any // AI修改后的节点数据
+}
+
+export interface NodeStatus {
+ [key: string]: any
+}
+
export interface PageState {
currentVm?: unknown
currentSchema?: { [x: string]: any; id: string }
@@ -17,7 +39,8 @@ export interface PageState {
isSaved: boolean
isLock: boolean
isBlock: boolean
- nodesStatus: Record
+ nodesStatus: Record
+ aiNodesStatus: Record // AI状态独立存储,避免与nodesStatus的可见性(false)冲突
loading: boolean
}
diff --git a/packages/canvas/DesignCanvas/src/api/useCanvas.ts b/packages/canvas/DesignCanvas/src/api/useCanvas.ts
index 1c64aefc78..30d2c430af 100644
--- a/packages/canvas/DesignCanvas/src/api/useCanvas.ts
+++ b/packages/canvas/DesignCanvas/src/api/useCanvas.ts
@@ -21,6 +21,7 @@ import type {
ChangePropsOperation,
DeleteOperation,
InsertOperation,
+ NodeAIStatus,
NodeOperation,
PageSchema,
PageState,
@@ -43,6 +44,7 @@ const defaultPageState: PageState = {
isLock: false,
isBlock: false,
nodesStatus: {},
+ aiNodesStatus: {},
loading: false
}
@@ -84,6 +86,39 @@ const rootSchema = ref([
}
])
+// 初始化单个节点的AI状态(使用独立的aiNodesStatus,避免与nodesStatus可见性冲突)
+const initializeNodeAIStatus = (node: Node, initialStatus: Partial = {}) => {
+ pageState.aiNodesStatus[node.id] = {
+ state: 'hidden',
+ originalNodeData: deepClone(node),
+ aiModifiedNodeData: undefined,
+ aiContext: null,
+ lastAIAction: '',
+ aiHistory: [],
+ ...initialStatus
+ }
+}
+
+// 初始化所有现有节点的AI状态
+const initializeAllNodesAIStatus = () => {
+ // 递归遍历 pageSchema 的 children 来初始化所有节点的AI状态
+ const traverseNodes = (nodes: any[]) => {
+ if (!nodes) return
+ nodes.forEach((node) => {
+ if (node.id && !pageState.aiNodesStatus[node.id]) {
+ initializeNodeAIStatus(node)
+ }
+ if (Array.isArray(node.children) && node.children.length) {
+ traverseNodes(node.children)
+ }
+ })
+ }
+
+ if (pageState.pageSchema?.children) {
+ traverseNodes(pageState.pageSchema.children)
+ }
+}
+
const handleTinyGridColumnsSlots = (node: Node) => {
const columns = Array.isArray(node.props?.columns) ? node.props.columns : []
for (const columnItem of columns) {
@@ -176,13 +211,26 @@ const jsonDiffPatchInstance = jsonDiffPatch.create({
const { publish } = useMessage()
// 重置画布数据
-const resetCanvasState = async (state: Partial = {}) => {
+// preserveAINodeStatus: 为true时保留aiNodesStatus并为新增节点补初始化(适用于AI/robot等schema热更新场景)
+const resetCanvasState = async (state: Partial = {}, options?: { preserveAINodeStatus?: boolean }) => {
const previousSchema = JSON.parse(JSON.stringify(pageState.pageSchema))
+ const preserveAINodeStatus = options?.preserveAINodeStatus ?? false
+
+ // 保留旧aiNodesStatus快照,用于后续diff补初始化
+ const oldAINodesStatus: Record = preserveAINodeStatus ? { ...pageState.aiNodesStatus } : {}
Object.assign(pageState, defaultPageState, state)
nodesMap.value.clear()
+ if (preserveAINodeStatus) {
+ // 保留aiNodesStatus,后续只为新增节点补初始化
+ pageState.aiNodesStatus = oldAINodesStatus
+ } else {
+ // 切换页面时清空所有节点的AI状态,避免旧页面的AI状态残留
+ pageState.aiNodesStatus = {}
+ }
+
if (pageState.pageSchema) {
if (!pageState.pageSchema.children) {
pageState.pageSchema.children = []
@@ -200,14 +248,34 @@ const resetCanvasState = async (state: Partial = {}) => {
nodesMap.value.set(0, { node: rootSchema.value, parent: pageState.pageSchema })
generateNodesMap(pageState.pageSchema.children, pageState.pageSchema)
+
+ if (preserveAINodeStatus) {
+ // 为新增的节点初始化AI状态(已存在的不覆盖)
+ nodesMap.value.forEach(({ node }) => {
+ if (node.id && !pageState.aiNodesStatus[node.id]) {
+ initializeNodeAIStatus(node)
+ }
+ })
+ } else {
+ // 初始化所有节点的AI状态
+ initializeAllNodesAIStatus()
+ }
}
const diffPatch = jsonDiffPatchInstance.diff(previousSchema, pageState.pageSchema)
- canvasApi.value?.clearSelect?.()
+ if (!preserveAINodeStatus) {
+ canvasApi.value?.clearSelect?.()
+ }
+
publish({ topic: 'schemaImport', data: { current: pageState.pageSchema, previous: previousSchema, diffPatch } })
}
+// 更新页面schema,保留AI状态(委托resetCanvasState + preserveAINodeStatus)
+const updatePageSchema = (newPageSchema: any) => {
+ resetCanvasState({ ...pageState, pageSchema: newPageSchema }, { preserveAINodeStatus: true })
+}
+
// 页面重置画布数据
const resetPageCanvasState = (state: Partial = {}) => {
state.isBlock = false
@@ -383,10 +451,28 @@ const operationTypeMap = {
setNode(newNodeData, parentNode)
+ // 初始化新节点的AI状态
+ if (newNodeData.id) {
+ initializeNodeAIStatus(newNodeData)
+ }
+
// 6. 如果新节点有子节点,递归构建 nodeMap
if (Array.isArray(newNodeData?.children) && newNodeData.children.length > 0) {
const newNode = getNode(newNodeData.id)
generateNodesMap(newNodeData.children, newNode)
+
+ // 递归初始化所有子节点的AI状态
+ const initChildrenAIStatus = (children: Node[]) => {
+ children.forEach((child) => {
+ if (child.id) {
+ initializeNodeAIStatus(child)
+ }
+ if (Array.isArray(child?.children) && child.children.length > 0) {
+ initChildrenAIStatus(child.children)
+ }
+ })
+ }
+ initChildrenAIStatus(newNodeData.children)
}
// 7. 返回插入结果
@@ -410,16 +496,18 @@ const operationTypeMap = {
if (index > -1) {
parent.children.splice(index, 1)
nodesMap.value.delete(node.id)
+ delete pageState.aiNodesStatus[node.id]
}
let children = [...(node.children || [])]
- // 递归清理 nodesMap
+ // 递归清理 nodesMap 和 aiNodesStatus
while (children?.length) {
const len = children.length
children.forEach((item) => {
const nodeItem = getNode(item.id)
nodesMap.value.delete(item.id)
+ delete pageState.aiNodesStatus[item.id]
if (Array.isArray(nodeItem?.children) && nodeItem?.children.length) {
children.push(...nodeItem.children)
@@ -597,7 +685,7 @@ const patchLatestSchema = (schema: unknown) => {
}
}
-const importSchema = (data: any) => {
+const importSchema = (data: any, options?: { preserveAINodeStatus?: boolean }) => {
let importData = data
if (typeof data === 'string') {
@@ -609,11 +697,7 @@ const importSchema = (data: any) => {
}
}
- // JSON 格式校验
- resetCanvasState({
- ...pageState,
- pageSchema: importData
- })
+ resetCanvasState({ ...pageState, pageSchema: importData }, options)
}
const exportSchema = () => {
@@ -650,6 +734,49 @@ const updateSchema = (data: Partial) => {
publish({ topic: 'schemaChange', data: {} })
}
+/**
+ * 恢复节点子树数据并重建nodesMap
+ * 用于AI回滚场景:恢复originalNodeData后需要同步清理/重建nodesMap
+ * @param nodeId 要恢复的节点ID
+ * @param restoredData 恢复后的节点数据(deepClone后的originalNodeData)
+ */
+const restoreNodeSubtree = (nodeId: string, restoredData: any) => {
+ // 1. 收集恢复前该节点子树中的所有ID(这些是需要从nodesMap中清理的)
+ const collectSubtreeIds = (node: any): string[] => {
+ const ids: string[] = []
+ if (node?.id) ids.push(node.id)
+ if (Array.isArray(node?.children)) {
+ node.children.forEach((child: any) => ids.push(...collectSubtreeIds(child)))
+ }
+ return ids
+ }
+
+ const currentNode = getNode(nodeId)
+ const oldIds = currentNode ? collectSubtreeIds(currentNode) : []
+ // 获取当前节点的parent信息(在清理前保存)
+ const parentEntry = nodesMap.value.get(nodeId)
+ const parentNode = parentEntry?.parent
+
+ // 2. 清理旧子树的nodesMap
+ oldIds.forEach((id) => nodesMap.value.delete(id))
+
+ // 3. 用恢复后的数据覆盖当前节点
+ if (currentNode) {
+ Object.keys(currentNode).forEach((key) => delete currentNode[key])
+ Object.assign(currentNode, restoredData)
+ }
+
+ // 4. 重建该节点自身的nodesMap条目
+ if (currentNode && parentNode) {
+ nodesMap.value.set(nodeId, { node: currentNode, parent: parentNode })
+ }
+
+ // 5. 重建子节点的nodesMap
+ if (Array.isArray(restoredData?.children) && restoredData.children.length && currentNode) {
+ generateNodesMap(restoredData.children, currentNode)
+ }
+}
+
export default function () {
return {
pageState,
@@ -684,6 +811,8 @@ export default function () {
exportSchema,
getSchema,
getNodePath,
- updateSchema
+ updateSchema,
+ updatePageSchema,
+ restoreNodeSubtree
}
}
diff --git a/packages/canvas/container/assets/loading.webp b/packages/canvas/container/assets/loading.webp
new file mode 100644
index 0000000000..ed71b43597
Binary files /dev/null and b/packages/canvas/container/assets/loading.webp differ
diff --git a/packages/canvas/container/src/components/AIConfirmDialog.vue b/packages/canvas/container/src/components/AIConfirmDialog.vue
new file mode 100644
index 0000000000..f3af12e385
--- /dev/null
+++ b/packages/canvas/container/src/components/AIConfirmDialog.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
diff --git a/packages/canvas/container/src/components/AILoadingDialog.vue b/packages/canvas/container/src/components/AILoadingDialog.vue
new file mode 100644
index 0000000000..192d005451
--- /dev/null
+++ b/packages/canvas/container/src/components/AILoadingDialog.vue
@@ -0,0 +1,93 @@
+
+
+
+
+
+
diff --git a/packages/canvas/container/src/components/CanvasAIChat.vue b/packages/canvas/container/src/components/CanvasAIChat.vue
new file mode 100644
index 0000000000..75bce3508c
--- /dev/null
+++ b/packages/canvas/container/src/components/CanvasAIChat.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/canvas/container/src/components/CanvasAction.vue b/packages/canvas/container/src/components/CanvasAction.vue
index 9df3bc0cac..f3cd4a50ea 100644
--- a/packages/canvas/container/src/components/CanvasAction.vue
+++ b/packages/canvas/container/src/components/CanvasAction.vue
@@ -91,6 +91,39 @@
+
+
@@ -136,6 +169,14 @@ import {
import { useLayout, useMaterial, useCanvas, useMessage } from '@opentiny/tiny-engine-meta-register'
import { Popover } from '@opentiny/vue'
import shortCutPopover from './shortCutPopover.vue'
+import CanvasAIChat from './CanvasAIChat.vue'
+import AIConfirmDialog from './AIConfirmDialog.vue'
+import AILoadingDialog from './AILoadingDialog.vue'
+import { chat } from '../services/agentServices'
+import { utils } from '@opentiny/tiny-engine-utils'
+import useAIChat from '../composables/useAIChat'
+
+const { deepClone } = utils
// 工具操作条高度
const OPTION_BAR_HEIGHT = 24
@@ -155,6 +196,9 @@ const STYLE_UNSET = 'unset'
export default {
components: {
+ AILoadingDialog,
+ CanvasAIChat,
+ AIConfirmDialog,
IconDel: IconDel(),
IconSetting: IconSetting(),
IconChevronLeft: IconChevronLeft(),
@@ -198,6 +242,29 @@ export default {
},
emits: ['remove', 'selectSlot', 'setting'],
setup(props) {
+ const { pageState: _pageState, getNode } = useCanvas()
+
+ const {
+ getNodeAIStatus,
+ openNodeAIChat,
+ closeNodeAIHelper,
+ startNodeAILoading,
+ cancelNodeAILoading,
+ shouldShowNodeAIChat,
+ shouldShowNodeAILoading,
+ shouldShowNodeAIConfirm,
+ confirmNodeAIAction,
+ updateNodeAIStatus,
+ cancelNodeAIAction,
+ applyAIPatches,
+ buildAIChatRequest
+ } = useAIChat()
+
+ // AI请求的AbortController,用于取消正在进行的请求
+ let aiChatAbortController = null
+ // 递增token,用于防止并发请求的响应竞争
+ let aiChatRequestToken = 0
+
const remove = () => {
removeNodeById(getCurrent().schema?.id)
}
@@ -283,6 +350,89 @@ export default {
return config?.configure?.isModal
})
+ // 是否显示AI聊天界面
+ const shouldShowAIChat = computed(() => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return false
+ }
+
+ return shouldShowNodeAIChat(currentSchema.id)
+ })
+
+ // 是否显示确认弹窗
+ const shouldShowAIConfirm = computed(() => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return false
+ }
+
+ return shouldShowNodeAIConfirm(currentSchema.id)
+ })
+
+ // 是否显示AI加载状态
+ const shouldShowAILoading = computed(() => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return false
+ }
+
+ return shouldShowNodeAILoading(currentSchema.id)
+ })
+
+ const showAIPopover = ref(false)
+ watch(
+ () => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return false
+ }
+ const status = getNodeAIStatus(currentSchema?.id)
+ return status?.state !== 'hidden' && !status?.collapsed
+ },
+ (val) => {
+ showAIPopover.value = val
+ }
+ )
+
+ // 切换AI助手显示/隐藏
+ const openAIHelper = () => {
+ const currentSchema = getCurrent().schema
+
+ if (!currentSchema?.id) {
+ return
+ }
+
+ const currentStatus = getNodeAIStatus(currentSchema.id)
+
+ if (currentStatus && currentStatus.collapsed) {
+ // 面板已收起,重新展开恢复原状态
+ updateNodeAIStatus(currentSchema.id, { collapsed: false })
+ } else if (currentStatus && currentStatus.state !== 'hidden') {
+ // 面板当前可见,收起面板但保留业务状态
+ updateNodeAIStatus(currentSchema.id, { collapsed: true })
+ } else {
+ // hidden状态,进入chat
+ openNodeAIChat(currentSchema.id)
+ }
+ }
+
+ // 关闭AI助手(由其他组件调用,如AI聊天界面的关闭按钮)
+ const closeAIHelper = () => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return
+ }
+
+ const currentStatus = getNodeAIStatus(currentSchema.id)
+ // loading/confirm状态下只收起面板,保留状态以便重新打开恢复
+ if (currentStatus && (currentStatus.state === 'loading' || currentStatus.state === 'confirm')) {
+ updateNodeAIStatus(currentSchema.id, { collapsed: true })
+ } else {
+ closeNodeAIHelper(currentSchema.id)
+ }
+ }
+
const optionRef = ref(null)
const fixStyle = ref('')
@@ -633,6 +783,166 @@ export default {
fixStyle.value = optionStyleValue
})
+ // AI聊天完成处理
+ const handleAIChatComplete = async (content) => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return
+ }
+
+ // 先进入加载状态
+ startNodeAILoading(currentSchema.id, 'AI正在处理您的请求...')
+
+ // 在AI修改节点前,先刷新originalNodeData为当前最新节点数据
+ // 避免取消/重新生成时回滚到过期的快照,丢失用户之前的普通编辑
+ const currentNode = getNode(currentSchema.id)
+ if (currentNode) {
+ const currentStatus = getNodeAIStatus(currentSchema.id)
+ if (currentStatus) {
+ currentStatus.originalNodeData = deepClone(currentNode)
+ }
+ }
+
+ // 创建新的AbortController用于取消请求,递增token防止响应竞争
+ aiChatAbortController = new AbortController()
+ const currentToken = ++aiChatRequestToken
+
+ try {
+ const params = await buildAIChatRequest(content)
+ const response = await chat(params, aiChatAbortController.signal)
+
+ // 响应到达后校验token:如果有更新的请求已经发出,丢弃本次响应
+ if (currentToken !== aiChatRequestToken) {
+ return
+ }
+
+ // 响应到达后再次检查:如果用户已经取消,不应用AI补丁
+ const status = getNodeAIStatus(currentSchema.id)
+ if (!status || status.state !== 'loading') {
+ return
+ }
+
+ // AI运行完:设置chatContent、aiModifiedNodeData,修改画布schema为AI的schema
+ // 应用失败则取消loading,避免UI永久转圈
+ if (!applyAIPatches(currentSchema.id, response, content)) {
+ cancelNodeAILoading(currentSchema.id)
+ }
+ } catch (error) {
+ // 请求被取消时不再应用补丁
+ if (error.name === 'AbortError' || error.name === 'CanceledError') {
+ return
+ }
+ // 其他错误:取消loading状态,避免UI永久转圈
+ cancelNodeAILoading(currentSchema.id)
+ }
+ }
+
+ // AI加载取消处理
+ const handleAILoadingCancel = () => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return
+ }
+
+ // 中止正在进行的AI请求
+ if (aiChatAbortController) {
+ aiChatAbortController.abort()
+ aiChatAbortController = null
+ // 递增token,使任何未完成的请求响应失效
+ aiChatRequestToken++
+ }
+
+ // 取消加载状态
+ cancelNodeAILoading(currentSchema.id)
+ }
+
+ // 刷新AI操作(重新生成)
+ // 逻辑:修改画布节点schema为originalNodeData,设置aiModifiedNodeData为空,重新发起请求
+ const handleAIRefresh = async () => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return
+ }
+
+ const nodeId = currentSchema.id
+ const currentAIStatus = getNodeAIStatus(nodeId)
+ if (!currentAIStatus) {
+ return
+ }
+
+ // 恢复画布节点schema为originalNodeData,同步重建nodesMap
+ if (currentAIStatus.originalNodeData) {
+ const { restoreNodeSubtree } = useCanvas()
+ restoreNodeSubtree(nodeId, deepClone(currentAIStatus.originalNodeData))
+ useMessage().publish({ topic: 'schemaChange', data: { nodeId } })
+ }
+
+ // 设置aiModifiedNodeData为空
+ updateNodeAIStatus(nodeId, {
+ aiModifiedNodeData: undefined
+ })
+
+ // 重新进入加载状态
+ startNodeAILoading(nodeId, 'AI正在重新生成...')
+
+ // 使用上次的聊天消息重新发起请求
+ const chatContent = currentAIStatus.chatContent
+ if (!chatContent) {
+ cancelNodeAILoading(nodeId)
+ return
+ }
+
+ try {
+ const params = await buildAIChatRequest(chatContent)
+ // 创建新的AbortController用于重新生成的请求,递增token防止响应竞争
+ const refreshToken = ++aiChatRequestToken
+ aiChatAbortController = new AbortController()
+ const response = await chat(params, aiChatAbortController.signal)
+
+ // 响应到达后校验token:如果有更新的请求已经发出,丢弃本次响应
+ if (refreshToken !== aiChatRequestToken) {
+ return
+ }
+
+ // 响应到达后检查是否已被取消
+ const status = getNodeAIStatus(nodeId)
+ if (!status || status.state !== 'loading') {
+ return
+ }
+
+ // AI运行完操作和 handleAIChatComplete 一样,应用失败则取消loading
+ if (!applyAIPatches(nodeId, response, chatContent)) {
+ cancelNodeAILoading(nodeId)
+ }
+ } catch (error) {
+ // 请求被取消时不做额外处理
+ if (error.name === 'AbortError' || error.name === 'CanceledError') {
+ return
+ }
+ cancelNodeAILoading(nodeId)
+ }
+ }
+
+ // 确认AI操作
+ const handleAIConfirm = () => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return
+ }
+
+ confirmNodeAIAction(currentSchema.id)
+ }
+
+ // 取消AI操作
+ const handleAICancel = () => {
+ const currentSchema = getCurrent().schema
+ if (!currentSchema?.id) {
+ return
+ }
+
+ cancelNodeAIAction(currentSchema.id)
+ }
+
return {
remove,
moveUp,
@@ -646,11 +956,22 @@ export default {
showQuickAction,
showPopover,
showToParent,
+ showAIPopover,
activeSetting,
isModal,
onMousedown,
labelStyle,
- labelRef
+ labelRef,
+ openAIHelper,
+ shouldShowAIChat,
+ shouldShowAILoading,
+ shouldShowAIConfirm,
+ closeAIHelper,
+ handleAIChatComplete,
+ handleAILoadingCancel,
+ handleAIConfirm,
+ handleAICancel,
+ handleAIRefresh
}
}
}
@@ -942,4 +1263,34 @@ export default {
cursor: se-resize;
}
}
+
+.ai-helper {
+ position: relative;
+ .ai-component,
+ .ai-component-loading {
+ position: absolute;
+ right: 0;
+ width: 360px;
+ opacity: 0;
+ transform: translateY(-10px);
+ animation: slideIn 0.2s ease-in-out forwards;
+ }
+ .ai-component-loading {
+ width: 270px;
+ }
+}
+@keyframes slideIn {
+ from {
+ opacity: 0;
+ transform: translateY(-10px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(10px);
+ }
+}
+.ai-popper.ai-popper.tiny-popper.tiny-popover {
+ padding: 0;
+ border-radius: 40px;
+}
diff --git a/packages/canvas/container/src/composables/useAIChat.ts b/packages/canvas/container/src/composables/useAIChat.ts
new file mode 100644
index 0000000000..f3cac5d227
--- /dev/null
+++ b/packages/canvas/container/src/composables/useAIChat.ts
@@ -0,0 +1,701 @@
+/**
+ * Copyright (c) 2023 - present TinyEngine Authors.
+ * Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
+ *
+ * Use of this source code is governed by an MIT-style license.
+ *
+ * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
+ * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
+ * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
+ *
+ */
+
+import { utils } from '@opentiny/tiny-engine-utils'
+import * as jsonpatch from 'fast-json-patch'
+import { jsonrepair } from 'jsonrepair'
+import {
+ useCanvas,
+ useMaterial,
+ getMetaApi,
+ META_SERVICE,
+ useMessage,
+ useHistory
+} from '@opentiny/tiny-engine-meta-register'
+import type { NodeAIStatus } from '../../../DesignCanvas/src/api/types'
+import { search, fetchAssets } from '../services/agentServices'
+import { getCurrent } from '../container'
+
+const { deepClone } = utils
+
+// ==================== AI助手状态管理 ====================
+
+const updateNodeAIStatus = (nodeId: string, aiStatus: Partial
) => {
+ const { pageState } = useCanvas()
+ const { publish } = useMessage()
+
+ if (!pageState.aiNodesStatus[nodeId]) {
+ pageState.aiNodesStatus[nodeId] = {
+ state: 'hidden', // 默认隐藏
+ aiContext: null,
+ lastAIAction: '',
+ aiHistory: []
+ }
+ }
+
+ Object.assign(pageState.aiNodesStatus[nodeId], aiStatus)
+
+ // 发布状态更新事件
+ publish({ topic: 'nodeAIStatusUpdate', data: { nodeId, aiStatus: pageState.aiNodesStatus[nodeId] } })
+}
+
+const getNodeAIStatus = (nodeId: string): NodeAIStatus | null => {
+ const { pageState } = useCanvas()
+ return pageState.aiNodesStatus[nodeId] || null
+}
+
+// 添加AI操作历史记录
+const addNodeAIActionHistory = (nodeId: string, action: string, content: any) => {
+ const currentStatus = getNodeAIStatus(nodeId)
+ if (!currentStatus) {
+ updateNodeAIStatus(nodeId, {
+ state: 'hidden',
+ aiHistory: [{ timestamp: Date.now(), action, content }]
+ })
+ return
+ }
+
+ const aiHistory = currentStatus.aiHistory || []
+ aiHistory.push({ timestamp: Date.now(), action, content })
+
+ updateNodeAIStatus(nodeId, {
+ aiHistory,
+ lastAIAction: action
+ })
+}
+
+// 打开AI助手聊天界面
+const openNodeAIChat = (nodeId: string, initialContent: string = '') => {
+ updateNodeAIStatus(nodeId, {
+ state: 'chat',
+ collapsed: false,
+ chatContent: initialContent,
+ lastAIAction: 'open_chat'
+ })
+
+ addNodeAIActionHistory(nodeId, 'open_chat', {
+ timestamp: Date.now(),
+ initialContent
+ })
+}
+
+// 关闭AI助手
+const closeNodeAIHelper = (nodeId: string) => {
+ updateNodeAIStatus(nodeId, {
+ state: 'hidden',
+ lastAIAction: 'close'
+ })
+
+ addNodeAIActionHistory(nodeId, 'close', {
+ timestamp: Date.now()
+ })
+}
+
+// 确认AI助手操作(采纳)
+// 逻辑:设置originalNodeData为AI修改后的schema,设置aiModifiedNodeData为空
+const confirmNodeAIAction = (nodeId: string) => {
+ const currentStatus = getNodeAIStatus(nodeId)
+ if (!currentStatus || currentStatus.state !== 'confirm') {
+ return
+ }
+
+ // 采纳后直接回到hidden,completed无对应UI,避免需要点击两次才能重新打开
+ updateNodeAIStatus(nodeId, {
+ state: 'hidden',
+ collapsed: false,
+ originalNodeData: deepClone(currentStatus.aiModifiedNodeData),
+ aiModifiedNodeData: undefined,
+ lastAIAction: 'confirm'
+ })
+}
+
+// 取消AI助手操作
+// 逻辑:设置aiModifiedNodeData为空,修改画布节点schema为originalNodeData
+const cancelNodeAIAction = (nodeId: string) => {
+ const currentStatus = getNodeAIStatus(nodeId)
+ if (!currentStatus) {
+ return
+ }
+
+ // 恢复画布节点schema为originalNodeData,同步重建nodesMap
+ if (currentStatus.originalNodeData && currentStatus.state === 'confirm') {
+ const { restoreNodeSubtree } = useCanvas()
+ const { publish } = useMessage()
+ restoreNodeSubtree(nodeId, deepClone(currentStatus.originalNodeData))
+ publish({ topic: 'schemaChange', data: { nodeId } })
+ }
+
+ const newState = currentStatus.chatContent ? 'chat' : 'hidden'
+
+ updateNodeAIStatus(nodeId, {
+ state: newState,
+ collapsed: false,
+ aiModifiedNodeData: undefined,
+ lastAIAction: 'cancel'
+ })
+}
+
+/**
+ * 设置AI修改后的节点数据(AI运行完调用)
+ * @param nodeId 节点ID
+ * @param aiModifiedNodeData AI修改后的节点数据
+ */
+const setNodeAIModifiedData = (nodeId: string, aiModifiedNodeData: any) => {
+ const currentAIStatus = getNodeAIStatus(nodeId)
+ if (!currentAIStatus) {
+ return
+ }
+
+ updateNodeAIStatus(nodeId, {
+ aiModifiedNodeData: deepClone(aiModifiedNodeData)
+ })
+}
+
+/**
+ * 采纳AI修改
+ * 逻辑:设置originalNodeData为AI修改后的schema,设置aiModifiedNodeData为空
+ * @param nodeId 节点ID
+ */
+const adoptNodeAIModification = (nodeId: string) => {
+ const currentAIStatus = getNodeAIStatus(nodeId)
+ if (!currentAIStatus || currentAIStatus.state !== 'confirm') {
+ return false
+ }
+
+ updateNodeAIStatus(nodeId, {
+ state: 'completed',
+ originalNodeData: deepClone(currentAIStatus.aiModifiedNodeData),
+ aiModifiedNodeData: undefined
+ })
+
+ return true
+}
+
+/**
+ * 拒绝AI修改
+ * 逻辑:设置aiModifiedNodeData为空,修改画布节点schema为originalNodeData
+ * @param nodeId 节点ID
+ */
+const rejectNodeAIModification = (nodeId: string) => {
+ const currentAIStatus = getNodeAIStatus(nodeId)
+ if (!currentAIStatus || currentAIStatus.state !== 'confirm') {
+ return false
+ }
+
+ // 恢复画布节点schema为originalNodeData,同步重建nodesMap
+ if (currentAIStatus.originalNodeData) {
+ const { restoreNodeSubtree } = useCanvas()
+ const { publish } = useMessage()
+ restoreNodeSubtree(nodeId, deepClone(currentAIStatus.originalNodeData))
+ publish({ topic: 'schemaChange', data: { nodeId } })
+ }
+
+ const newState = currentAIStatus.chatContent ? 'chat' : 'hidden'
+
+ updateNodeAIStatus(nodeId, {
+ state: newState,
+ aiModifiedNodeData: undefined
+ })
+
+ return true
+}
+
+/**
+ * 重置节点AI采纳状态
+ * @param nodeId 节点ID
+ */
+const resetNodeAIAdoptionStatus = (nodeId: string) => {
+ const currentAIStatus = getNodeAIStatus(nodeId)
+ if (currentAIStatus) {
+ updateNodeAIStatus(nodeId, {
+ originalNodeData: undefined,
+ aiModifiedNodeData: undefined
+ })
+ }
+}
+
+/**
+ * 检查节点是否有待处理的AI修改
+ * @param nodeId 节点ID
+ */
+const hasNodePendingAIModification = (nodeId: string): boolean => {
+ const aiStatus = getNodeAIStatus(nodeId)
+ return aiStatus?.state === 'confirm'
+}
+// ==================== AI助手状态函数 ====================
+
+// 获取当前节点是否应该显示AI聊天界面
+const shouldShowNodeAIChat = (nodeId: string): boolean => {
+ const status = getNodeAIStatus(nodeId)
+ return status?.state === 'chat' && !status?.collapsed
+}
+
+// 获取当前节点是否应该显示确认弹窗
+const shouldShowNodeAIConfirm = (nodeId: string): boolean => {
+ const status = getNodeAIStatus(nodeId)
+ return status?.state === 'confirm' && !status?.collapsed
+}
+
+// 开始AI加载状态
+const startNodeAILoading = (nodeId: string, loadingMessage: string = 'AI处理中...') => {
+ updateNodeAIStatus(nodeId, {
+ state: 'loading',
+ collapsed: false,
+ lastAIAction: 'start_loading',
+ aiContext: {
+ loadingMessage,
+ startTime: Date.now()
+ }
+ })
+
+ addNodeAIActionHistory(nodeId, 'start_loading', {
+ timestamp: Date.now(),
+ loadingMessage
+ })
+}
+
+// 完成AI加载,进入确认状态
+const completeNodeAILoading = (nodeId: string) => {
+ updateNodeAIStatus(nodeId, {
+ state: 'confirm',
+ collapsed: false,
+ lastAIAction: 'complete_loading'
+ })
+
+ addNodeAIActionHistory(nodeId, 'complete_loading', {
+ timestamp: Date.now()
+ })
+}
+
+// 取消AI加载
+const cancelNodeAILoading = (nodeId: string) => {
+ const currentStatus = getNodeAIStatus(nodeId)
+ if (!currentStatus || currentStatus.state !== 'loading') {
+ return
+ }
+
+ // 返回到聊天状态或隐藏状态
+ const newState = currentStatus.chatContent ? 'chat' : 'hidden'
+
+ updateNodeAIStatus(nodeId, {
+ state: newState,
+ collapsed: false,
+ aiContext: undefined,
+ lastAIAction: 'cancel_loading'
+ })
+
+ addNodeAIActionHistory(nodeId, 'cancel_loading', {
+ timestamp: Date.now(),
+ previousState: currentStatus.state,
+ loadingDuration: Date.now() - (currentStatus.aiContext?.startTime || Date.now())
+ })
+}
+
+// 获取当前节点是否应该显示AI加载状态
+const shouldShowNodeAILoading = (nodeId: string): boolean => {
+ const status = getNodeAIStatus(nodeId)
+ return status?.state === 'loading' && !status?.collapsed
+}
+
+/**
+ * 逐个解析 JSON Patch 数组中的顶级 patch 对象
+ * 当整个数组因括号不匹配等原因无法解析时,通过顶层 `{"op":` 模式分割后分别解析
+ * 对每个单独的对象尝试 JSON.parse → jsonrepair → 修复多余括号
+ */
+const parseIndividualPatches = (jsonStr: string): any[] => {
+ const patches: any[] = []
+
+ // 移除外层数组的 [ ] 包裹
+ let str = jsonStr.trim()
+ if (str.startsWith('[')) str = str.slice(1)
+ if (str.endsWith(']')) str = str.slice(0, -1)
+
+ // 通过顶层 {"op": 模式分割各个 patch 对象
+ const segments: string[] = []
+ let depth = 0
+ let inString = false
+ let escape = false
+ let segStart = -1
+
+ for (let i = 0; i < str.length; i++) {
+ const ch = str[i]
+
+ if (escape) {
+ escape = false
+ continue
+ }
+ if (ch === '\\' && inString) {
+ escape = true
+ continue
+ }
+ if (ch === '"') {
+ inString = !inString
+ continue
+ }
+ if (inString) continue
+
+ if (ch === '{') {
+ if (depth === 0) segStart = i
+ depth++
+ } else if (ch === '}') {
+ depth--
+ if (depth === 0 && segStart >= 0) {
+ segments.push(str.slice(segStart, i + 1))
+ segStart = -1
+ }
+ }
+ }
+
+ // 对每个 segment 尝试解析,逐步增强容错
+ for (const seg of segments) {
+ let patch = null
+ try {
+ patch = JSON.parse(seg)
+ } catch {
+ try {
+ patch = JSON.parse(jsonrepair(seg))
+ } catch {
+ // 尝试修复多余的尾部 }
+ // 找到最后一个合法的 } 位置(通过从后往前逐步移除多余的 })
+ let fixed = seg
+ for (let trim = 0; trim < 5; trim++) {
+ fixed = fixed.replace(/\}(\}*)$/, '$1') // 移除最末尾的一个 }
+ try {
+ patch = JSON.parse(fixed)
+ break
+ } catch {
+ // 继续尝试
+ }
+ }
+ }
+ }
+ if (patch && patch.op && patch.path) {
+ patches.push(patch)
+ }
+ }
+
+ return patches
+}
+
+const findJsonPatchPath = (node, targetId, path = []) => {
+ if (!node || typeof node !== 'object') return null
+
+ if (node.id === targetId) {
+ return '/' + path.join('/')
+ }
+
+ if (Array.isArray(node.children)) {
+ for (let i = 0; i < node.children.length; i++) {
+ const result = findJsonPatchPath(node.children[i], targetId, [...path, 'children', i])
+ if (result) return result
+ }
+ }
+
+ // 如果不是数组也不是目标,继续搜索其他属性
+ for (const key in node) {
+ if (key !== 'children' && Object.hasOwn(node, key)) {
+ const value = node[key]
+ if (value && typeof value === 'object') {
+ const result = findJsonPatchPath(value, targetId, [...path, key])
+ if (result) return result
+ }
+ }
+ }
+
+ return null
+}
+
+/**
+ * 解析 AI 返回的 JSON Patch 字符串,逐步增强容错:
+ * 1. 剥离 Markdown 代码块包裹
+ * 2. 直接 JSON.parse
+ * 3. 修复未转义换行符后再 parse
+ * 4. jsonrepair 修复
+ * 5. 逐个 patch 解析(跳过损坏的单个 patch)
+ */
+const parseJsonPatches = (content: string): any[] | null => {
+ let jsonStr = content
+ // 剥离 Markdown 代码块
+ const codeBlockMatch = jsonStr.match(/```(?:json|schema)?([\s\S]*?)```/)
+ if (codeBlockMatch) {
+ jsonStr = codeBlockMatch[1].trim()
+ }
+
+ let patches: any[] = []
+ try {
+ // 策略1:直接解析
+ try {
+ patches = JSON.parse(jsonStr)
+ } catch {
+ // 策略2:修复 JSON 字符串值中未转义的换行符
+ try {
+ const fixedStr = jsonStr.replace(
+ /"((?:[^"\\]|\\.)*)"/g,
+ (match, inner) => '"' + inner.replace(/\n/g, '\\n').replace(/\r/g, '\\r') + '"'
+ )
+ patches = JSON.parse(fixedStr)
+ } catch {
+ // 策略3:使用 jsonrepair 修复
+ try {
+ patches = JSON.parse(jsonrepair(jsonStr))
+ } catch {
+ // 策略4:逐个 patch 解析 — AI 常在深层嵌套的 children 中产生多余的括号,
+ // 导致整个数组解析失败。逐个提取顶级 patch 对象分别解析,跳过损坏的。
+ patches = parseIndividualPatches(jsonStr)
+ }
+ }
+ }
+ } catch (error) {
+ return null
+ }
+
+ if (!Array.isArray(patches)) {
+ patches = [patches]
+ }
+ return patches
+}
+
+/**
+ * 辅助函数:根据路径段从对象中安全取值
+ */
+const getValueBySegments = (obj: any, segments: string[]): any => {
+ return segments.reduce((o, key) => (o !== null ? o[key] : undefined), obj)
+}
+
+/**
+ * 辅助函数:将路径段拼接为 JSON Pointer 格式(以 / 开头)
+ */
+const toPointer = (segments: string[]): string => '/' + segments.filter(Boolean).join('/')
+
+/**
+ * 将 JSON Patch 数组应用到页面 schema 上
+ * 按操作类型分步应用:先 replace/remove,再 add,最后其他
+ * add 操作会自动处理:目标数组不存在时初始化、索引越界时追加到末尾
+ * @param patches JSON Patch 数组
+ * @param pageSchema 当前页面 schema
+ * @param parentPath 当前节点在 schema 中的路径
+ * @returns 应用后的新 schema
+ */
+const applyPatchesToSchema = (patches: any[], pageSchema: object, parentPath: string): object => {
+ // 分离操作类型
+ const replacePatches = patches.filter((p) => p.op === 'replace' || p.op === 'remove')
+ const addPatches = patches.filter((p) => p.op === 'add')
+ const otherPatches = patches.filter((p) => p.op !== 'replace' && p.op !== 'remove' && p.op !== 'add')
+
+ // 先应用 replace/remove 操作
+ let newSchema = replacePatches.reduce((acc, patch) => {
+ try {
+ const fullPatch = {
+ ...patch,
+ path: parentPath + patch.path
+ }
+ return jsonpatch.applyPatch(acc, [fullPatch], false, false).newDocument
+ } catch (error) {
+ return acc
+ }
+ }, pageSchema)
+
+ // 再应用 add 操作
+ // 需要处理的情况:
+ // 1. 目标数组不存在 → 先初始化空数组,再追加
+ // 2. 索引超出数组长度 → 降级为追加到末尾(/-)
+ // 3. 最后一段不是数字索引且目标是数组 → 追加到末尾(/-)
+ newSchema = addPatches.reduce((acc, patch) => {
+ try {
+ const pathSegments = patch.path.split('/').filter(Boolean)
+ const lastSegment = pathSegments[pathSegments.length - 1]
+
+ if (!lastSegment) {
+ return acc
+ }
+
+ const parentSegments = pathSegments.slice(0, -1)
+ const fullParentSegments = (parentPath + '/' + parentSegments.join('/')).split('/').filter(Boolean)
+ let parentValue = getValueBySegments(acc, fullParentSegments)
+ let fixedPath = patch.path
+
+ // 父路径对应的值不是数组但路径暗示要往数组中插入(如 /children/0),
+ // 需要先初始化空数组
+ if (!Array.isArray(parentValue) && /^\d+$/.test(lastSegment)) {
+ const arrayPath = toPointer(parentPath.split('/').filter(Boolean).concat(parentSegments))
+ try {
+ const patched = jsonpatch.applyPatch(
+ acc,
+ [{ op: 'add', path: arrayPath, value: [] }],
+ false,
+ false
+ ).newDocument
+ acc = patched
+ parentValue = getValueBySegments(acc, fullParentSegments)
+ } catch {
+ // 路径已存在或初始化失败,尝试继续
+ }
+ }
+
+ // 根据目标数组的状态修正路径
+ if (Array.isArray(parentValue)) {
+ const index = Number(lastSegment)
+ if (Number.isNaN(index)) {
+ fixedPath = toPointer(pathSegments) + '/-'
+ } else if (index >= parentValue.length) {
+ fixedPath = toPointer(parentSegments) + '/-'
+ }
+ }
+
+ const fullPatch = {
+ ...patch,
+ path: parentPath + fixedPath
+ }
+ return jsonpatch.applyPatch(acc, [fullPatch], false, false).newDocument
+ } catch (error) {
+ return acc
+ }
+ }, newSchema)
+
+ // 最后应用其他操作(move, copy, test 等)
+ newSchema = otherPatches.reduce((acc, patch) => {
+ try {
+ const fullPatch = {
+ ...patch,
+ path: parentPath + patch.path
+ }
+ return jsonpatch.applyPatch(acc, [fullPatch], false, false).newDocument
+ } catch (error) {
+ return acc
+ }
+ }, newSchema)
+
+ return newSchema
+}
+
+/**
+ * 应用AI返回的JSON Patch到页面schema,完成画布更新
+ * 逻辑:设置chatContent、设置aiModifiedNodeData为AI修改后的节点schema、修改画布节点schema为AI的schema
+ * @param nodeId 当前节点ID
+ * @param chatResponse AI聊天接口返回的响应对象
+ * @param chatContent 用户发送的聊天消息
+ * @returns 应用成功返回 true,失败返回 false
+ */
+const applyAIPatches = (nodeId: string, chatResponse: any, chatContent?: string): boolean => {
+ if (!chatResponse?.choices?.[0]?.message?.content) {
+ return false
+ }
+
+ const { fixMethods, schemaAutoFix } = getMetaApi('engine.service.robot')
+ const { getPageSchema, getNode, updatePageSchema, setSaved } = useCanvas()
+
+ const content = chatResponse.choices[0].message.content
+ const validJsonPatches = parseJsonPatches(content)
+ if (!validJsonPatches) {
+ return false
+ }
+
+ const parentPath = findJsonPatchPath(getPageSchema(), nodeId)
+ const newSchema = applyPatchesToSchema(validJsonPatches, getPageSchema(), parentPath)
+
+ fixMethods(newSchema.methods)
+ schemaAutoFix(newSchema.children)
+
+ // 使用 updatePageSchema 更新画布(保留 nodesStatus 不清空)
+ updatePageSchema(newSchema)
+
+ // 设置 AI 状态:chatContent、aiModifiedNodeData
+ const modifiedNode = getNode(nodeId)
+ const modifiedNodeData = modifiedNode ? deepClone(modifiedNode) : validJsonPatches[0]?.value
+
+ updateNodeAIStatus(nodeId, {
+ state: 'confirm',
+ collapsed: false,
+ chatContent,
+ aiModifiedNodeData: modifiedNodeData
+ })
+
+ setSaved(false)
+ useHistory().addHistory()
+ completeNodeAILoading(nodeId)
+ return true
+}
+
+// ==================== AI聊天请求构建 ====================
+
+/**
+ * 构建AI聊天请求参数
+ * @param content 用户输入的消息文本
+ * @returns 请求参数对象
+ */
+const buildAIChatRequest = async (content: string) => {
+ const { getRobotServiceOptions, formatComponents, getAgentSystemPrompt, getSelectedModelInfo } =
+ getMetaApi('engine.service.robot')
+
+ const currentSchema = getCurrent().schema
+ const modelInfo = getSelectedModelInfo()
+ let referenceContext = ''
+ let imageAssets: any[] = []
+
+ if (getRobotServiceOptions()?.enableRagContext) {
+ referenceContext = await search(content)
+ }
+ if (getRobotServiceOptions()?.enableResourceContext) {
+ const appId = getMetaApi(META_SERVICE.GlobalService).getBaseInfo().id
+ imageAssets = await fetchAssets(appId)
+ }
+
+ const { materialState, getComponentDetail } = useMaterial()
+ const components = formatComponents(materialState.components, getComponentDetail)
+ const messages = [
+ { role: 'system', content: getAgentSystemPrompt(components, currentSchema, referenceContext, imageAssets) },
+ { role: 'user', content: [{ type: 'text', text: content }] }
+ ]
+
+ return {
+ body: {
+ baseUrl: modelInfo.baseUrl,
+ model: modelInfo.model,
+ apiKey: modelInfo.apiKey,
+ messages
+ },
+ headers: {
+ Authorization: `Bearer ${modelInfo.apiKey}`,
+ 'Content-Type': 'application/json'
+ }
+ }
+}
+
+export default function () {
+ return {
+ // AI助手状态管理
+ updateNodeAIStatus,
+ getNodeAIStatus,
+ addNodeAIActionHistory,
+ // AI助手状态机函数
+ openNodeAIChat,
+ closeNodeAIHelper,
+ startNodeAILoading,
+ completeNodeAILoading,
+ cancelNodeAILoading,
+ confirmNodeAIAction,
+ cancelNodeAIAction,
+ shouldShowNodeAIChat,
+ shouldShowNodeAILoading,
+ shouldShowNodeAIConfirm,
+ // 节点级AI采纳状态管理
+ setNodeAIModifiedData,
+ adoptNodeAIModification,
+ rejectNodeAIModification,
+ resetNodeAIAdoptionStatus,
+ hasNodePendingAIModification,
+ findJsonPatchPath,
+ applyAIPatches,
+ // AI聊天请求构建
+ buildAIChatRequest
+ }
+}
diff --git a/packages/canvas/container/src/services/agentServices.ts b/packages/canvas/container/src/services/agentServices.ts
new file mode 100644
index 0000000000..3f9361cb1d
--- /dev/null
+++ b/packages/canvas/container/src/services/agentServices.ts
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2023 - present TinyEngine Authors.
+ * Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
+ *
+ * Use of this source code is governed by an MIT-style license.
+ *
+ * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
+ * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
+ * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
+ *
+ */
+
+import { getMetaApi, META_SERVICE } from '@opentiny/tiny-engine-meta-register'
+
+/**
+ * AI搜索功能
+ * @param content 搜索内容
+ * @returns 搜索结果字符串
+ */
+export const search = async (content: string): Promise => {
+ let result = ''
+ const MAX_SEARCH_LENGTH = 8000
+
+ try {
+ const res = await getMetaApi(META_SERVICE.Http).post('app-center/api/ai/search', { content })
+
+ res.forEach((item: { content: string }) => {
+ if (result.length + item.content.length > MAX_SEARCH_LENGTH) {
+ return
+ }
+ result += item.content
+ })
+ } catch (error) {
+ return ''
+ }
+
+ return result
+}
+
+/**
+ * 获取资源列表
+ * @returns 格式化的资源列表
+ */
+export const fetchAssets = async (appId: string) => {
+ try {
+ const res = (await getMetaApi(META_SERVICE.Http).get(`material-center/api/resource/find/${appId}`)) || []
+ return res
+ .map((group: any) => group.resources)
+ .flat()
+ .filter((item: any) => item.description)
+ .map((item: any) => ({
+ url: item.resourceUrl,
+ describe: item.description
+ }))
+ } catch (error) {
+ return []
+ }
+}
+
+export const chat = async (params, signal?: AbortSignal) => {
+ const response = await getMetaApi(META_SERVICE.Http).request({
+ url: 'app-center/api/ai/chat',
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ ...params.headers
+ },
+ data: params.body,
+ signal
+ })
+
+ return response
+}
diff --git a/packages/canvas/package.json b/packages/canvas/package.json
index 092e104b35..d3ed66ef19 100644
--- a/packages/canvas/package.json
+++ b/packages/canvas/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentiny/tiny-engine-canvas",
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"publishConfig": {
"access": "public"
},
@@ -42,6 +42,11 @@
"@opentiny/tiny-engine-i18n-host": "workspace:*",
"@opentiny/tiny-engine-meta-register": "workspace:*",
"@opentiny/tiny-engine-utils": "workspace:*",
+ "@opentiny/tiny-robot": "0.4.0",
+ "@opentiny/tiny-robot-kit": "0.4.0",
+ "@opentiny/tiny-robot-svgs": "0.4.0",
+ "fast-json-patch": "~3.1.1",
+ "jsonrepair": "3.13.0",
"@vue/babel-plugin-jsx": "^1.2.5",
"@vue/shared": "^3.3.4",
"@vueuse/core": "^9.6.0",
diff --git a/packages/common/component/LifeCycles.vue b/packages/common/component/LifeCycles.vue
index 8dcde96417..2bfa55fa6a 100644
--- a/packages/common/component/LifeCycles.vue
+++ b/packages/common/component/LifeCycles.vue
@@ -277,7 +277,7 @@ export default {
.life-cycle-tips {
color: var(--te-component-common-text-color-weaken);
margin: 4px 0 0;
- height: 16px;
+ height: 30px;
line-height: 16px;
}
.life-cycle-content-list {
diff --git a/packages/common/composable/generateCode/index.ts b/packages/common/composable/generateCode/index.ts
index 505a9e1acb..0b27a5daef 100644
--- a/packages/common/composable/generateCode/index.ts
+++ b/packages/common/composable/generateCode/index.ts
@@ -1,6 +1,7 @@
import { generateApp, type IAppSchema } from '@opentiny/tiny-engine-dsl-vue'
import * as dslVue from '@opentiny/tiny-engine-dsl-vue'
import { getMergeMeta } from '@opentiny/tiny-engine-meta-register'
+import { formatString } from '../../js/ast'
import defaultPrettierConfig from '../../js/config-files/prettierrc'
// 应用出码默认配置
@@ -42,7 +43,7 @@ const generateAppCode = async (appSchema: IAppSchema, options = {}) => {
const { parseRequiredBlocks, genSFCWithDefaultPlugin } = dslVue as any
const generatePageCode = (...args: any[]) => {
- return genSFCWithDefaultPlugin(...args)
+ return formatString(genSFCWithDefaultPlugin(...args), 'vue')
}
/**
diff --git a/packages/common/js/ast.ts b/packages/common/js/ast.ts
index 55ff615e7d..0c4cc40051 100644
--- a/packages/common/js/ast.ts
+++ b/packages/common/js/ast.ts
@@ -38,12 +38,23 @@ export const string2Ast = (string = ''): BabelAst =>
export const ast2String = (ast: GeneratorInput): string => generate(ast, { retainLines: true }).code // 将 AST 再转回字符串
type FormatterFn = (input: string) => string
-type SupportedLanguage = 'json' | 'typescript' | 'javascript' | 'html' | 'css'
+type SupportedLanguage = 'json' | 'typescript' | 'javascript' | 'html' | 'css' | 'vue' | 'less'
+type SupportedPrettierParser = 'json' | 'babel' | 'babel-ts' | 'html' | 'css' | 'less' | 'vue'
-const formatScript: FormatterFn = (string) => {
+const PRETTIER_PLUGINS = [parserBabel, parseCss, parserHtml]
+
+const formatWithParser = (string: string, parser: SupportedPrettierParser, options: PrettierOptions = {}): string =>
+ prettier.format(string, {
+ parser,
+ plugins: PRETTIER_PLUGINS,
+ ...basePrettierConfig,
+ ...options
+ })
+
+const formatScript = (string: string, parser: 'babel' | 'babel-ts' = 'babel'): string => {
let newStr = string
const options: PrettierOptions = {
- parser: 'babel',
+ parser,
plugins: [parserBabel],
...basePrettierConfig
}
@@ -72,34 +83,49 @@ const formatScript: FormatterFn = (string) => {
return newStr
}
-const formatJson: FormatterFn = (string) =>
- prettier.format(string, {
- parser: 'json',
- plugins: [parserBabel],
- trailingComma: 'es5',
- ...basePrettierConfig
- })
+const formatJson: FormatterFn = (string) => formatWithParser(string, 'json')
-const formatHtml: FormatterFn = (string) =>
- prettier.format(string, {
- parser: 'html',
- plugins: [parserBabel, parserHtml],
- ...basePrettierConfig
- })
+const formatHtml: FormatterFn = (string) => formatWithParser(string, 'html')
-const formatCss: FormatterFn = (string) =>
- prettier.format(string, {
- parser: 'css',
- plugins: [parseCss],
- ...basePrettierConfig
- })
+const formatCss: FormatterFn = (string) => formatWithParser(string, 'css')
+
+const formatVue: FormatterFn = (string) => formatWithParser(string, 'vue')
+
+const formatLess: FormatterFn = (string) => formatWithParser(string, 'less')
const formatterMap: Record = {
json: formatJson,
- typescript: formatScript,
+ typescript: (str) => formatScript(str, 'babel-ts'),
javascript: formatScript,
html: formatHtml,
- css: formatCss
+ css: formatCss,
+ vue: formatVue,
+ less: formatLess
+}
+
+const parserMap: Record = {
+ json: 'json',
+ js: 'babel',
+ jsx: 'babel',
+ mjs: 'babel',
+ cjs: 'babel',
+ ts: 'babel-ts',
+ tsx: 'babel-ts',
+ css: 'css',
+ less: 'less',
+ html: 'html',
+ vue: 'vue'
+}
+
+export const getPrettierParserByFileName = (fileName = ''): SupportedPrettierParser | undefined => {
+ const pureFileName = fileName.split('?')[0].split('#')[0].toLowerCase()
+ const extension = pureFileName.split('.').at(-1)
+
+ if (!extension || extension === pureFileName) {
+ return undefined
+ }
+
+ return parserMap[extension]
}
export const formatString = (str: string, language: string): string => {
@@ -115,6 +141,27 @@ export const formatString = (str: string, language: string): string => {
return result
}
+export const formatStringByFileName = (str: string, fileName: string): string => {
+ const parser = getPrettierParserByFileName(fileName)
+
+ if (!parser) {
+ return str
+ }
+
+ try {
+ if (parser === 'babel' || parser === 'babel-ts') {
+ return formatScript(str, parser)
+ }
+
+ return formatWithParser(str, parser)
+ } catch (error) {
+ const printer: Console = console
+ printer.log(error)
+
+ return str
+ }
+}
+
export { parse, parseExpression, traverse, generate }
export const includedExpression = (code: string, expression: string): boolean => {
diff --git a/packages/common/js/import-map.json b/packages/common/js/import-map.json
index 347291c38b..1fc71a5cef 100644
--- a/packages/common/js/import-map.json
+++ b/packages/common/js/import-map.json
@@ -9,7 +9,7 @@
"@vueuse/shared": "${VITE_CDN_DOMAIN}/@vueuse/shared${versionDelimiter}9.6.0${fileDelimiter}/index.mjs",
"axios": "${VITE_CDN_DOMAIN}/axios${versionDelimiter}1.0.0${fileDelimiter}/dist/esm/axios.js",
"@opentiny/tiny-engine-i18n-host": "${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-i18n-host${versionDelimiter}^2${fileDelimiter}/dist/lowcode-design-i18n-host.es.js",
- "@opentiny/tiny-engine-builtin-component": "${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-builtin-component${versionDelimiter}^2.10.0-rc.0${fileDelimiter}/dist/index.mjs",
+ "@opentiny/tiny-engine-builtin-component": "${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-builtin-component${versionDelimiter}^2.10.0${fileDelimiter}/dist/index.mjs",
"vue-demi": "${VITE_CDN_DOMAIN}/vue-demi${versionDelimiter}0.13.11${fileDelimiter}/lib/index.mjs",
"pinia": "${VITE_CDN_DOMAIN}/pinia${versionDelimiter}2.0.22${fileDelimiter}/dist/pinia.esm-browser.js",
"@opentiny/vue": "${VITE_CDN_DOMAIN}/@opentiny/vue-runtime${versionDelimiter}~3.20${fileDelimiter}/dist3/tiny-vue-pc.mjs",
diff --git a/packages/common/js/verification.ts b/packages/common/js/verification.ts
index 32264ac2be..dccfb0d245 100644
--- a/packages/common/js/verification.ts
+++ b/packages/common/js/verification.ts
@@ -11,6 +11,7 @@
*/
export const REGEXP_EVENT_NAME = /^[a-z]+([A-Z][a-z]*)*$/
+export const REGEXP_UPDATE_EVENT_NAME = /^onUpdate:[a-zA-Z_$][\w$]*$/
export const verifyEventName = (name: string) => REGEXP_EVENT_NAME.test(name)
diff --git a/packages/common/package.json b/packages/common/package.json
index ddf48bece6..062c342440 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentiny/tiny-engine-common",
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"publishConfig": {
"access": "public"
},
diff --git a/packages/configurator/package.json b/packages/configurator/package.json
index fc70381c73..b0bbc36bf3 100644
--- a/packages/configurator/package.json
+++ b/packages/configurator/package.json
@@ -1,6 +1,6 @@
{
"name": "@opentiny/tiny-engine-configurator",
- "version": "2.10.0-rc.0",
+ "version": "2.10.0",
"description": "",
"main": "dist/index.js",
"module": "dist/index.js",
diff --git a/packages/configurator/src/model-api-configurator/ModelApiConfigurator.vue b/packages/configurator/src/model-api-configurator/ModelApiConfigurator.vue
index b6b4a79a01..335a50c64c 100644
--- a/packages/configurator/src/model-api-configurator/ModelApiConfigurator.vue
+++ b/packages/configurator/src/model-api-configurator/ModelApiConfigurator.vue
@@ -4,7 +4,7 @@
trigger="manual"
v-model="isShow"
:visible-arrow="false"
- :popper-class="['option-popper', 'fixed-left']"
+ :popper-class="['option-popper', 'fixed-left', 'model-function-popper']"
:offset="isSecond ? 652 : 0"
width="600"
>
@@ -230,7 +230,7 @@ onMounted(() => {
display: flex;
justify-content: space-between;
align-items: center;
- margin: 8px 0 20px 0;
+ margin: 8px 16px 20px 16px;
.right {
svg {
margin-left: 10px;
@@ -286,7 +286,10 @@ onMounted(() => {
.model-param-wrap {
.tiny-form {
- padding: 12px;
+ padding: 12px 28px;
+ }
+ .tiny-collapse.tiny-collapse .tiny-collapse-item {
+ padding: 0 12px;
}
}
}
@@ -318,3 +321,10 @@ onMounted(() => {
color: var(--te-common-text-secondary);
}
+
diff --git a/packages/configurator/src/model-configurator/ModelConfigurator.vue b/packages/configurator/src/model-configurator/ModelConfigurator.vue
index 04e313e2e1..9380ec97ed 100644
--- a/packages/configurator/src/model-configurator/ModelConfigurator.vue
+++ b/packages/configurator/src/model-configurator/ModelConfigurator.vue
@@ -6,7 +6,7 @@
trigger="manual"
v-model="isShow"
:visible-arrow="false"
- :popper-class="['option-popper', 'fixed-left']"
+ :popper-class="['option-popper', 'fixed-left', 'model-popper']"
>
绑定模型数据
@@ -424,19 +424,15 @@ onMounted(() => {
.model-container {
width: 100%;
line-height: 28px;
- background-color: var(--ti-lowcode-input-bg);
&:hover {
cursor: pointer;
}
- .model-name-warp {
- border: 1px solid var(--ti-lowcode-component-input-border-color);
- }
.meta-model-title {
- color: #808080;
+ color: var(--te-configurator-common-text-color-weaken);
}
.meta-array-wrap {
font-size: 12px;
- border: 1px solid #dbdbdb;
+ border: 1px solid var(--te-configurator-common-border-color);
border-radius: 4px;
display: block;
:deep(.tiny-search) {
@@ -444,7 +440,7 @@ onMounted(() => {
.tiny-search__line {
border: none;
border-radius: 0;
- border-bottom: 1px solid var(--ti-search-input-border-color);
+ border-bottom: 1px solid var(--te-configurator-common-border-color);
}
}
.meta-array-header {
@@ -567,3 +563,9 @@ onMounted(() => {
}
}
+
diff --git a/packages/configurator/src/source-select-configurator/SourceSelectConfigurator.vue b/packages/configurator/src/source-select-configurator/SourceSelectConfigurator.vue
index 1c27755939..ce4f341974 100644
--- a/packages/configurator/src/source-select-configurator/SourceSelectConfigurator.vue
+++ b/packages/configurator/src/source-select-configurator/SourceSelectConfigurator.vue
@@ -204,12 +204,11 @@ export default {
.source-container {
width: 100%;
line-height: 28px;
- background-color: var(--ti-lowcode-input-bg);
.source-img-wrap {
position: relative;
width: 150px;
height: 96px;
- background-color: var(--te-common-bg-container);
+ background-color: var(--te-configurator-container-bg-color);
img {
width: 100%;
height: 100%;
@@ -232,7 +231,7 @@ export default {
width: 70px;
height: 22px;
line-height: 22px;
- border: 1px solid var(--te-common-bg-popover);
+ border: 1px solid var(--te-configurator-common-border-color);
border-radius: 4px;
text-align: center;
color: var(--te-common-text-inverse);
diff --git a/packages/configurator/src/styles/vars.less b/packages/configurator/src/styles/vars.less
index d628d7fe0e..b4b2526d1f 100644
--- a/packages/configurator/src/styles/vars.less
+++ b/packages/configurator/src/styles/vars.less
@@ -21,6 +21,8 @@
--te-configurator-common-border-color-divider: var(--te-common-border-divider);
--te-configurator-common-border-color: var(--te-common-border-default);
+ --te-configurator-common-panel-shadow-color: var(--te-common-shadow-panel);
+
--te-configurator-button-group-bg-color-active: var(--te-common-bg-prompt);
--te-configurator-button-group-bg-color: var(--te-common-bg-container);
diff --git a/packages/design-core/assets/chat.svg b/packages/design-core/assets/chat.svg
index 29d05ff782..0d086bbb7c 100644
--- a/packages/design-core/assets/chat.svg
+++ b/packages/design-core/assets/chat.svg
@@ -1,13 +1,16 @@
-
+
\ No newline at end of file
diff --git a/packages/design-core/assets/generate-code.svg b/packages/design-core/assets/generate-code.svg
index 9ef86cf4b8..8450940c9c 100644
--- a/packages/design-core/assets/generate-code.svg
+++ b/packages/design-core/assets/generate-code.svg
@@ -1,12 +1,24 @@
-