forked from opentiny/tiny-engine
Compare commits
106 Commits
1.0.0-beta
...
develop
| Author | SHA1 | Date |
|---|---|---|
|
|
e651dffa2b | |
|
|
91d3ae108c | |
|
|
277be2f11e | |
|
|
2c478ce391 | |
|
|
c341f4c2c5 | |
|
|
858e178af6 | |
|
|
4bfba8ca40 | |
|
|
07b0245fa0 | |
|
|
a0a4e293d8 | |
|
|
ffd0280877 | |
|
|
47c71d1129 | |
|
|
0d36df07a7 | |
|
|
6d9241ed6a | |
|
|
899d616f7e | |
|
|
3a66996fae | |
|
|
aa8d361bd2 | |
|
|
30cfeb19df | |
|
|
c271054870 | |
|
|
e9961aaba8 | |
|
|
c36cc66f59 | |
|
|
e98994f8d9 | |
|
|
0afdf2fcae | |
|
|
7bb3adfcba | |
|
|
3107621129 | |
|
|
50b62373a7 | |
|
|
0818d1656a | |
|
|
56907693f6 | |
|
|
4fd55d4261 | |
|
|
d613b4e8f6 | |
|
|
ade2d93331 | |
|
|
7d965fceee | |
|
|
4864fb66c5 | |
|
|
eafe3df2c6 | |
|
|
005f36af3c | |
|
|
a69082f518 | |
|
|
e54edca915 | |
|
|
681a6fa612 | |
|
|
259ef69ba3 | |
|
|
8e89cc47e7 | |
|
|
da8f58b0d9 | |
|
|
f7980d8c83 | |
|
|
e94b9674aa | |
|
|
c55397928a | |
|
|
852217f711 | |
|
|
e9d6d7e3f9 | |
|
|
0e6d30183a | |
|
|
68838ed5f9 | |
|
|
a010bfa4d6 | |
|
|
6c92ffefec | |
|
|
e961e0638f | |
|
|
8c09632e9c | |
|
|
e9a67b9de0 | |
|
|
6a59dacfd6 | |
|
|
d0241a9972 | |
|
|
13db22af27 | |
|
|
030497fbad | |
|
|
68637db8db | |
|
|
38c89a856c | |
|
|
99d0e47c29 | |
|
|
731a8536aa | |
|
|
913f40c4d2 | |
|
|
e88b254683 | |
|
|
7d967777d8 | |
|
|
bf2bc188a5 | |
|
|
683fc51d52 | |
|
|
96def94945 | |
|
|
52037fdf78 | |
|
|
491c01092e | |
|
|
9bccbfacb6 | |
|
|
34dfbc624e | |
|
|
3e1cb599d7 | |
|
|
5e43b79922 | |
|
|
4d247ef406 | |
|
|
f26456bbb5 | |
|
|
caeb540d19 | |
|
|
3875e16e87 | |
|
|
422c62dbdb | |
|
|
e79853cb09 | |
|
|
b726219668 | |
|
|
7ea6ebcbbd | |
|
|
f843d121fa | |
|
|
a192280fc4 | |
|
|
6ca84ee6f2 | |
|
|
93263b5298 | |
|
|
fb2e2f1207 | |
|
|
c3c2e2e714 | |
|
|
9e57be080c | |
|
|
28ee851b2a | |
|
|
dec9334eb8 | |
|
|
91ff6aed55 | |
|
|
9c72525db6 | |
|
|
35c7e91a4c | |
|
|
12b7a11280 | |
|
|
435f81708f | |
|
|
421dda28be | |
|
|
236445e7ff | |
|
|
3c2e14d4de | |
|
|
7b9ff6cfd5 | |
|
|
00160f92df | |
|
|
1cbecd2497 | |
|
|
9b96d10fb2 | |
|
|
2b5fe014f9 | |
|
|
38762017ff | |
|
|
fe477ad74c | |
|
|
47be96756c | |
|
|
919f06e89d |
|
|
@ -8,4 +8,4 @@ tool_params:
|
|||
secsolar:
|
||||
source_dir: ./
|
||||
cmetrics:
|
||||
exclude: vite.config.js|package.json|index.js|mockServer/assets
|
||||
exclude: vite.config.js|package.json|index.js|mockServer/assets|packages/vue-generator/test
|
||||
|
|
|
|||
|
|
@ -64,6 +64,14 @@ body:
|
|||
attributes:
|
||||
label: What is actually happening
|
||||
placeholder: Please Input
|
||||
- type: input
|
||||
id: project-name
|
||||
attributes:
|
||||
label: What is your project name
|
||||
description: We also welcome you to fill in more detailed project information in the following issue [#334](https://github.com/opentiny/tiny-engine/issues/334).
|
||||
placeholder: Please Input
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: additional-comments
|
||||
attributes:
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@ blank_issues_enabled: true
|
|||
contact_links:
|
||||
- name: Questions or need help
|
||||
url: https://github.com/opentiny/tiny-engine/discussions
|
||||
about: Add this WeChat(opentiny), we will invite you to the WeChat discussion group later.
|
||||
about: Add this WeChat(opentiny-official), we will invite you to the WeChat discussion group later.
|
||||
|
|
|
|||
|
|
@ -21,3 +21,11 @@ body:
|
|||
placeholder: Please Input
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: project-name
|
||||
attributes:
|
||||
label: What is your project name
|
||||
description: We also welcome you to fill in more detailed project information in the following issue [#334](https://github.com/opentiny/tiny-engine/issues/334).
|
||||
placeholder: Please Input
|
||||
validations:
|
||||
required: true
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 18
|
||||
|
||||
- name: Install pnpm
|
||||
run: npm i -g pnpm
|
||||
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
|
||||
- name: Get changed files
|
||||
id: get_changed_files
|
||||
uses: tj-actions/changed-files@v40
|
||||
uses: tj-actions/changed-files@v41
|
||||
with:
|
||||
files: |
|
||||
**.js
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ package-lock.json
|
|||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
lerna-debug.log
|
||||
packages/design-core/bundle-deps
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@ pnpm build:plugin
|
|||
pnpm build:alpha or build:prod
|
||||
|
||||
```
|
||||
The folder where the product is located after building
|
||||
```
|
||||
tiny-engine/packages/design-core/dist/
|
||||
```
|
||||
|
||||
## Milestones
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@ pnpm run build:plugin
|
|||
pnpm run build:alpha 或 build:prod
|
||||
|
||||
```
|
||||
构建后产物所在文件夹
|
||||
```
|
||||
tiny-engine/packages/design-core/dist/
|
||||
```
|
||||
|
||||
## 里程碑
|
||||
|
||||
|
|
|
|||
|
|
@ -6065,7 +6065,7 @@
|
|||
"devMode": "proCode",
|
||||
"npm": {
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "TinyTabItem",
|
||||
"exportName": "TabItem",
|
||||
"version": "",
|
||||
"destructuring": true
|
||||
},
|
||||
|
|
@ -6314,7 +6314,7 @@
|
|||
"devMode": "proCode",
|
||||
"npm": {
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "TinyBreadcrumbItem",
|
||||
"exportName": "BreadcrumbItem",
|
||||
"version": "",
|
||||
"destructuring": true
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
port: process.env.MOCK_PORT || 9090,
|
||||
env: process.env.NODE_ENV || 'development' // Current mode
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-mock",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.3",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
"lint": "eslint --fix ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentiny/tiny-engine-dsl-vue": "~1.0.0",
|
||||
"@opentiny/tiny-engine-dsl-vue": "^1.0.3",
|
||||
"@seald-io/nedb": "^4.0.2",
|
||||
"fs-extra": "^11.1.1",
|
||||
"glob": "^10.3.4",
|
||||
|
|
|
|||
|
|
@ -14,13 +14,12 @@ import Koa2 from 'koa'
|
|||
import KoaBody from 'koa-body'
|
||||
import KoaStatic from 'koa-static2'
|
||||
import path from 'path'
|
||||
import MainRoutes from './routes/main-routes'
|
||||
import { env, port } from '../config/config'
|
||||
import ErrorRoutesCatch from './middleware/ErrorRoutesCatch'
|
||||
import ErrorRoutes from './routes/error-routes'
|
||||
import MainRoutes from './routes/main-routes'
|
||||
|
||||
const app = new Koa2()
|
||||
const env = process.env.NODE_ENV || 'development' // Current mode
|
||||
const PORT = 9090
|
||||
app
|
||||
.use((ctx, next) => {
|
||||
ctx.set('Access-Control-Allow-Origin', '*')
|
||||
|
|
@ -57,6 +56,6 @@ if (env === 'development') {
|
|||
})
|
||||
}
|
||||
|
||||
app.listen(PORT)
|
||||
app.listen(port)
|
||||
|
||||
export default app
|
||||
|
|
|
|||
|
|
@ -15,7 +15,674 @@
|
|||
"gmt_modified": "2023-08-23 10:22:28"
|
||||
},
|
||||
"dataSource": {
|
||||
"list": [],
|
||||
"list": [
|
||||
{
|
||||
"id": 132,
|
||||
"name": "getAllComponent",
|
||||
"data": {
|
||||
"data": [],
|
||||
"type": "array"
|
||||
},
|
||||
"tpl": null,
|
||||
"app": "918",
|
||||
"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}"
|
||||
},
|
||||
"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) {}"
|
||||
}
|
||||
},
|
||||
"tpl": null,
|
||||
"app": "918",
|
||||
"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
|
||||
}
|
||||
},
|
||||
{
|
||||
"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"
|
||||
},
|
||||
"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}"
|
||||
},
|
||||
"errorHandler": {
|
||||
"type": "JSFunction",
|
||||
"value": "function errorHandler(err) {}"
|
||||
}
|
||||
},
|
||||
"tpl": null,
|
||||
"app": "918",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"type": "tree"
|
||||
},
|
||||
"tpl": null,
|
||||
"app": "918",
|
||||
"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": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"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}"
|
||||
},
|
||||
"errorHandler": {
|
||||
"type": "JSFunction",
|
||||
"value": "function errorHandler(err) {}"
|
||||
}
|
||||
},
|
||||
"tpl": null,
|
||||
"app": "918",
|
||||
"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": "918",
|
||||
"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}"
|
||||
|
|
@ -102,7 +769,7 @@
|
|||
{
|
||||
"componentName": "TinyTimeLine",
|
||||
"props": {
|
||||
"active": "2",
|
||||
"active": 2,
|
||||
"data": [
|
||||
{
|
||||
"name": "基础配置"
|
||||
|
|
@ -858,7 +1525,7 @@
|
|||
{
|
||||
"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;"
|
||||
"style": "border-width: 1px;z-index:1;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": [
|
||||
{
|
||||
|
|
@ -883,7 +1550,7 @@
|
|||
{
|
||||
"componentName": "TinyCol",
|
||||
"props": {
|
||||
"span": "8"
|
||||
"span": 8
|
||||
},
|
||||
"id": "b9d051a5",
|
||||
"children": [
|
||||
|
|
@ -896,7 +1563,7 @@
|
|||
{
|
||||
"componentName": "TinyCol",
|
||||
"props": {
|
||||
"span": "5",
|
||||
"span": 5,
|
||||
"style": "display: flex;"
|
||||
},
|
||||
"id": "02352776",
|
||||
|
|
@ -930,7 +1597,7 @@
|
|||
{
|
||||
"componentName": "TinyCol",
|
||||
"props": {
|
||||
"span": "7"
|
||||
"span": 7
|
||||
},
|
||||
"id": "82b6c659",
|
||||
"children": [
|
||||
|
|
@ -998,7 +1665,7 @@
|
|||
{
|
||||
"componentName": "TinyCol",
|
||||
"props": {
|
||||
"span": "4",
|
||||
"span": 4,
|
||||
"style": "display: flex; flex-direction: row-reverse; border-radius: 0px; height: 100%; justify-content: flex-start; align-items: center;"
|
||||
},
|
||||
"id": "10b73009",
|
||||
|
|
@ -1023,7 +1690,7 @@
|
|||
],
|
||||
"fileName": "createVm",
|
||||
"meta": {
|
||||
"id": 1977,
|
||||
"id": "NTJ4MjvqoVj8OVsc",
|
||||
"parentId": "0",
|
||||
"group": "staticPages",
|
||||
"occupier": {
|
||||
|
|
@ -1120,7 +1787,7 @@
|
|||
},
|
||||
{
|
||||
"componentName": "TinyPlusFrozenPage",
|
||||
"package": "@opentiny/vuee",
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "FrozenPage",
|
||||
"destructuring": true,
|
||||
"version": "3.4.1"
|
||||
|
|
@ -1258,6 +1925,13 @@
|
|||
"destructuring": true,
|
||||
"version": "0.1.16"
|
||||
},
|
||||
{
|
||||
"componentName": "TinyButton",
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "Button",
|
||||
"destructuring": true,
|
||||
"version": "0.1.16"
|
||||
},
|
||||
{
|
||||
"componentName": "TinyButtonGroup",
|
||||
"package": "@opentiny/vue",
|
||||
|
|
@ -1300,6 +1974,48 @@
|
|||
"destructuring": true,
|
||||
"version": "0.1.16"
|
||||
},
|
||||
{
|
||||
"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": "PortalHome",
|
||||
"main": "common/components/home",
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import KoaRouter from 'koa-router'
|
||||
import * as glob from 'glob'
|
||||
import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
import * as glob from 'glob'
|
||||
import KoaRouter from 'koa-router'
|
||||
import path from 'path'
|
||||
import MockService from '../services/mockService'
|
||||
|
||||
import { getResponseData } from '../tool/Common'
|
||||
|
||||
const router = new KoaRouter()
|
||||
export const mockService = new MockService()
|
||||
const getJsonPathData = (jpath, method = 'get') => {
|
||||
|
|
@ -140,7 +140,9 @@ router.get('/material-center/api/block-groups/delete/:id', async (ctx) => {
|
|||
router.get('/material-center/api/block-groups', async (ctx) => {
|
||||
const result = await mockService.blockGroupService.find(ctx.query)
|
||||
let blockGroup
|
||||
if (result.data.length > 1) {
|
||||
if (result.data.length === 0) {
|
||||
ctx.body = result
|
||||
} else if (result.data.length > 1) {
|
||||
blockGroup = await Promise.all(
|
||||
result.data.map(async (group) => {
|
||||
group.blocks = await Promise.all(
|
||||
|
|
@ -153,7 +155,7 @@ router.get('/material-center/api/block-groups', async (ctx) => {
|
|||
})
|
||||
)
|
||||
ctx.body = getResponseData(blockGroup)
|
||||
} else {
|
||||
} else if (result.data.length === 1) {
|
||||
blockGroup = result.data[0]
|
||||
const blocks = await Promise.all(
|
||||
blockGroup.blocks.map(async (item) => {
|
||||
|
|
|
|||
|
|
@ -25459,7 +25459,7 @@
|
|||
"devMode": "proCode",
|
||||
"npm": {
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "TinyTabItem",
|
||||
"exportName": "TabItem",
|
||||
"version": "",
|
||||
"destructuring": true
|
||||
},
|
||||
|
|
@ -25708,7 +25708,7 @@
|
|||
"devMode": "proCode",
|
||||
"npm": {
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "TinyBreadcrumbItem",
|
||||
"exportName": "BreadcrumbItem",
|
||||
"version": "",
|
||||
"destructuring": true
|
||||
},
|
||||
|
|
@ -28769,6 +28769,867 @@
|
|||
"disable": ["copy", "remove"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"zh_CN": "日期选择"
|
||||
},
|
||||
"component": "TinyDatePicker",
|
||||
"icon": "datepick",
|
||||
"description": "用于输入或选择日期",
|
||||
"docUrl": "",
|
||||
"screenshot": "",
|
||||
"tags": "",
|
||||
"keywords": "",
|
||||
"devMode": "proCode",
|
||||
"npm": {
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "DatePicker",
|
||||
"version": "",
|
||||
"destructuring": true
|
||||
},
|
||||
"group": "component",
|
||||
"priority": 1,
|
||||
"schema": {
|
||||
"properties": [
|
||||
{
|
||||
"label": {
|
||||
"zh_CN": "基础信息"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "基础信息"
|
||||
},
|
||||
"collapse": {
|
||||
"number": 6,
|
||||
"text": {
|
||||
"zh_CN": "显示更多"
|
||||
}
|
||||
},
|
||||
"content": [
|
||||
{
|
||||
"property": "modelValue",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "绑定值"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaBindI18n",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "双向绑定值"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "type",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "类型"
|
||||
}
|
||||
},
|
||||
"widget": {
|
||||
"component": "MetaSelect",
|
||||
"props": {
|
||||
"options": [
|
||||
{
|
||||
"label": "日期",
|
||||
"value": "date"
|
||||
},
|
||||
{
|
||||
"label": "日期时间",
|
||||
"value": "datetime"
|
||||
},
|
||||
{
|
||||
"label": "周",
|
||||
"value": "week"
|
||||
},
|
||||
{
|
||||
"label": "月份",
|
||||
"value": "month"
|
||||
},
|
||||
{
|
||||
"label": "年份",
|
||||
"value": "year"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "设置日期框的type属性"
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "placeholder",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "占位文本"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaBindI18n",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "输入框占位文本"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "clearable",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "清除按钮"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSwitch",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "是否显示清除按钮"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "disabled",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "禁用"
|
||||
}
|
||||
},
|
||||
"required": false,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSwitch",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "禁用"
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "readonly",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "是否只读"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSwitch",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "size",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "尺寸"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSelect",
|
||||
"props": {
|
||||
"options": [
|
||||
{
|
||||
"label": "medium",
|
||||
"value": "medium"
|
||||
},
|
||||
{
|
||||
"label": "small",
|
||||
"value": "small"
|
||||
},
|
||||
{
|
||||
"label": "mini",
|
||||
"value": "mini"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "日期框尺寸。该属性的可选值为 medium / small / mini"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "1",
|
||||
"label": {
|
||||
"zh_CN": "其他"
|
||||
},
|
||||
"content": [
|
||||
{
|
||||
"property": "maxlength",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "最大长度"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaNumber",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "设置 input 框的maxLength"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "autofocus",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "聚焦"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSwitch",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "自动获取焦点"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
}
|
||||
],
|
||||
"description": {
|
||||
"zh_CN": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"events": {
|
||||
"onChange": {
|
||||
"label": {
|
||||
"zh_CN": "值改变时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 值改变时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "输入框改变后的值"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onInput": {
|
||||
"label": {
|
||||
"zh_CN": "输入值改变时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 输入值改变时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "输入框输入的值"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onUpdate:modelValue": {
|
||||
"label": {
|
||||
"zh_CN": "双向绑定的值改变时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 输入值改变时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "双向绑定的值"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onBlur": {
|
||||
"label": {
|
||||
"zh_CN": "失去焦点时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 失去焦点时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "event",
|
||||
"type": "Object",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "原生 event"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onFocus": {
|
||||
"label": {
|
||||
"zh_CN": "获取焦点时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 获取焦点时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "event",
|
||||
"type": "Object",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "原生 event"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onClear": {
|
||||
"label": {
|
||||
"zh_CN": "点击清空按钮时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "点击清空按钮时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"configure": {
|
||||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": true,
|
||||
"isModal": false,
|
||||
"nestingRule": {
|
||||
"childWhitelist": "",
|
||||
"parentWhitelist": "",
|
||||
"descendantBlacklist": "",
|
||||
"ancestorWhitelist": ""
|
||||
},
|
||||
"isNullNode": false,
|
||||
"isLayout": false,
|
||||
"rootSelector": "",
|
||||
"shortcuts": {
|
||||
"properties": ["value", "disabled"]
|
||||
},
|
||||
"contextMenu": {
|
||||
"actions": ["create symbol"],
|
||||
"disable": ["copy", "remove"]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"zh_CN": "数字输入框"
|
||||
},
|
||||
"component": "TinyNumeric",
|
||||
"icon": "numeric",
|
||||
"description": "通过鼠标或键盘输入字符",
|
||||
"docUrl": "",
|
||||
"screenshot": "",
|
||||
"tags": "",
|
||||
"keywords": "",
|
||||
"devMode": "proCode",
|
||||
"npm": {
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "Numeric",
|
||||
"version": "",
|
||||
"destructuring": true
|
||||
},
|
||||
"group": "component",
|
||||
"priority": 1,
|
||||
"schema": {
|
||||
"properties": [
|
||||
{
|
||||
"label": {
|
||||
"zh_CN": "基础信息"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "基础信息"
|
||||
},
|
||||
"collapse": {
|
||||
"number": 6,
|
||||
"text": {
|
||||
"zh_CN": "显示更多"
|
||||
}
|
||||
},
|
||||
"content": [
|
||||
{
|
||||
"property": "modelValue",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "绑定值"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"widget": {
|
||||
"component": "MetaBindI18n",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "双向绑定值"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "placeholder",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "占位文本"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaBindI18n",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "输入框占位文本"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "allow-empty",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "内容可清空"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSwitch",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "是否内容可清空"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "disabled",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "禁用"
|
||||
}
|
||||
},
|
||||
"required": false,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSwitch",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "禁用"
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "size",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "尺寸"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSelect",
|
||||
"props": {
|
||||
"options": [
|
||||
{
|
||||
"label": "medium",
|
||||
"value": "medium"
|
||||
},
|
||||
{
|
||||
"label": "small",
|
||||
"value": "small"
|
||||
},
|
||||
{
|
||||
"label": "mini",
|
||||
"value": "mini"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "输入框尺寸。该属性的可选值为 medium / small / mini"
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "controls",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "是否使用加减按钮"
|
||||
}
|
||||
},
|
||||
"required": false,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSwitch",
|
||||
"props": {}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"property": "controls-position",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "加减按钮位置"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaSelect",
|
||||
"props": {
|
||||
"options": [
|
||||
{
|
||||
"label": "左右两侧",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"label": "只在右侧",
|
||||
"value": "right"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "加减按钮位置"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "precision",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "数值精度"
|
||||
}
|
||||
},
|
||||
"required": false,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaNumber",
|
||||
"props": {
|
||||
"allowEmpty": true
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "数值精度"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "step",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "步长"
|
||||
}
|
||||
},
|
||||
"required": false,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaNumber",
|
||||
"props": {
|
||||
"allowEmpty": true
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "步长"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "max",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "可输入的最大数值"
|
||||
}
|
||||
},
|
||||
"required": false,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaNumber",
|
||||
"props": {
|
||||
"allowEmpty": true
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "可输入的最大数值"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
},
|
||||
{
|
||||
"property": "min",
|
||||
"label": {
|
||||
"text": {
|
||||
"zh_CN": "可输入的最小数值"
|
||||
}
|
||||
},
|
||||
"required": false,
|
||||
"readOnly": false,
|
||||
"disabled": false,
|
||||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaNumber",
|
||||
"props": {
|
||||
"allowEmpty": true
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "可输入的最大数值"
|
||||
},
|
||||
"labelPosition": "left"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": {
|
||||
"onChange": {
|
||||
"label": {
|
||||
"zh_CN": "值改变时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 值改变时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "输入框改变后的值"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onInput": {
|
||||
"label": {
|
||||
"zh_CN": "输入值改变时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 输入值改变时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "输入框输入的值"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onUpdate:modelValue": {
|
||||
"label": {
|
||||
"zh_CN": "双向绑定的值改变时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 输入值改变时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": "string",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "双向绑定的值"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onBlur": {
|
||||
"label": {
|
||||
"zh_CN": "失去焦点时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 失去焦点时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "event",
|
||||
"type": "Object",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "原生 event"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onFocus": {
|
||||
"label": {
|
||||
"zh_CN": "获取焦点时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "在 Input 获取焦点时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [
|
||||
{
|
||||
"name": "event",
|
||||
"type": "Object",
|
||||
"defaultValue": "",
|
||||
"description": {
|
||||
"zh_CN": "原生 event"
|
||||
}
|
||||
}
|
||||
],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
},
|
||||
"onClear": {
|
||||
"label": {
|
||||
"zh_CN": "点击清空按钮时触发"
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": "点击清空按钮时触发"
|
||||
},
|
||||
"type": "event",
|
||||
"functionInfo": {
|
||||
"params": [],
|
||||
"returns": {}
|
||||
},
|
||||
"defaultValue": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"configure": {
|
||||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": true,
|
||||
"isModal": false,
|
||||
"nestingRule": {
|
||||
"childWhitelist": "",
|
||||
"parentWhitelist": "",
|
||||
"descendantBlacklist": "",
|
||||
"ancestorWhitelist": ""
|
||||
},
|
||||
"isNullNode": false,
|
||||
"isLayout": false,
|
||||
"rootSelector": "",
|
||||
"shortcuts": {
|
||||
"properties": ["value", "disabled"]
|
||||
},
|
||||
"contextMenu": {
|
||||
"actions": ["create symbol"],
|
||||
"disable": ["copy", "remove"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
||||
"@types/node": "^18.0.0",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.2",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"assert": "^2.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"chokidar": "^3.5.3",
|
||||
|
|
@ -65,5 +65,10 @@
|
|||
"engines": {
|
||||
"node": ">=14",
|
||||
"pnpm": ">=7"
|
||||
},
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"@vue/repl@2.9.0": "patches/@vue__repl@2.9.0.patch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-block-build",
|
||||
"version": "0.0.1-alpha.0",
|
||||
"version": "1.0.2",
|
||||
"description": "translate block to webcomponent template",
|
||||
"main": "./dist/web-components.es.js",
|
||||
"scripts": {
|
||||
|
|
@ -32,12 +32,12 @@
|
|||
"dependencies": {
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@opentiny/tiny-engine-webcomponent-core": "workspace:*",
|
||||
"@opentiny/vue": "~3.11.0",
|
||||
"@opentiny/vue-icon": "~3.11.0",
|
||||
"@opentiny/vue-theme": "~3.11.0",
|
||||
"@opentiny/vue": "~3.14.0",
|
||||
"@opentiny/vue-icon": "~3.14.0",
|
||||
"@opentiny/vue-theme": "~3.14.0",
|
||||
"@vue/shared": "^3.3.11",
|
||||
"vue": "^3.3.11",
|
||||
"vue-i18n": "^9.8.0"
|
||||
"vue": "^3.4.15",
|
||||
"vue-i18n": "^9.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.5.2",
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default defineConfig(({ command, mode }) => {
|
|||
}
|
||||
|
||||
const vuePluginConfig = {}
|
||||
const styleLinks = ['https://npm.onmicrosoft.cn/@opentiny/vue-theme@3.11/index.css']
|
||||
const styleLinks = ['https://npm.onmicrosoft.cn/@opentiny/vue-theme@3.14/index.css']
|
||||
|
||||
config.publicDir = false
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-builtin-component",
|
||||
"version": "0.1.0",
|
||||
"version": "1.0.1",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
|
|
@ -13,14 +16,18 @@
|
|||
"directory": "packages/builtinComponent"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentiny/vue": "~3.10.0"
|
||||
"vite-plugin-css-injected-by-js": "^3.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.2",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"vite": "^4.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.4.15"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@ import { defineConfig } from 'vite'
|
|||
import path from 'path'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import vitePluginCssInjectedByJs from 'vite-plugin-css-injected-by-js'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue(), vueJsx()],
|
||||
plugins: [vue(), vueJsx(), vitePluginCssInjectedByJs()],
|
||||
publicDir: false,
|
||||
build: {
|
||||
cssCodeSplit: false,
|
||||
|
|
@ -26,9 +27,6 @@ export default defineConfig({
|
|||
formats: ['es']
|
||||
},
|
||||
rollupOptions: {
|
||||
output: {
|
||||
banner: 'import "./style.css"'
|
||||
},
|
||||
external: ['vue']
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-canvas",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.3",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
|
@ -27,25 +27,26 @@
|
|||
"homepage": "https://opentiny.design/tiny-engine",
|
||||
"dependencies": {
|
||||
"@babel/core": "7.18.13",
|
||||
"@opentiny/tiny-engine-common": "workspace:*",
|
||||
"@opentiny/tiny-engine-builtin-component": "workspace:*",
|
||||
"@opentiny/tiny-engine-controller": "workspace:*",
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@opentiny/tiny-engine-utils": "workspace:*",
|
||||
"@opentiny/tiny-engine-webcomponent-core": "workspace:*",
|
||||
"@opentiny/tiny-engine-builtin-component": "workspace:*",
|
||||
"@opentiny/vue": "~3.10.0",
|
||||
"@opentiny/vue-icon": "~3.10.0",
|
||||
"@opentiny/vue-renderless": "~3.10.0",
|
||||
"@vue/babel-plugin-jsx": "1.1.1",
|
||||
"@vue/shared": "^3.3.4",
|
||||
"@vueuse/core": "^9.6.0",
|
||||
"vue": "3.2.45",
|
||||
"vue-i18n": "9.2.2"
|
||||
"@vueuse/core": "^9.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.10",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"vite": "^4.3.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentiny/vue": "^3.14.0",
|
||||
"@opentiny/vue-icon": "^3.14.0",
|
||||
"@opentiny/vue-renderless": "^3.14.0",
|
||||
"vue": "^3.4.15",
|
||||
"vue-i18n": "^9.9.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -514,8 +514,7 @@
|
|||
"schema": {
|
||||
"componentName": "Img",
|
||||
"props": {
|
||||
"src": "img/webNova.jpg",
|
||||
"style": "width: 200px; height: 200px"
|
||||
"src": "https://tinyengine-assets.obs.cn-north-4.myhuaweicloud.com/files/designer-default-icon.jpg"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
export const NODE_UID = 'data-uid'
|
||||
export const NODE_TAG = 'data-tag'
|
||||
|
|
@ -125,9 +125,10 @@ export const getClipboardSchema = (event) => translateStringToSchame(event.clipb
|
|||
*/
|
||||
export const dynamicImportComponents = async ({ package: pkg, script, components }) => {
|
||||
if (!script) return
|
||||
const scriptUrl = script.startsWith('.') ? new URL(script, location.href).href : script
|
||||
|
||||
if (!window.TinyComponentLibs[pkg]) {
|
||||
const modules = await import(/* @vite-ignore */ script)
|
||||
const modules = await import(/* @vite-ignore */ scriptUrl)
|
||||
|
||||
window.TinyComponentLibs[pkg] = modules
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,16 +27,48 @@
|
|||
</div>
|
||||
<!-- 绝对定位画布时调节元素大小 -->
|
||||
<template v-else>
|
||||
<div class="drag-resize resize-top" @mousedown.stop="onMousedown($event, 'center', 'start')"></div>
|
||||
<div class="drag-resize resize-bottom" @mousedown.stop="onMousedown($event, 'center', 'end')"></div>
|
||||
<div class="drag-resize resize-left" @mousedown.stop="onMousedown($event, 'start', 'center')"></div>
|
||||
<div class="drag-resize resize-right" @mousedown.stop="onMousedown($event, 'end', 'center')"></div>
|
||||
<div class="drag-resize resize-top-left" @mousedown.stop="onMousedown($event, 'start', 'start')"></div>
|
||||
<div class="drag-resize resize-top-right" @mousedown.stop="onMousedown($event, 'end', 'start')"></div>
|
||||
<div class="drag-resize resize-bottom-left" @mousedown.stop="onMousedown($event, 'start', 'end')"></div>
|
||||
<div class="drag-resize resize-bottom-right" @mousedown.stop="onMousedown($event, 'end', 'end')"></div>
|
||||
<div
|
||||
class="drag-resize resize-top"
|
||||
draggable="true"
|
||||
@mousedown.stop="onMousedown($event, 'center', 'start')"
|
||||
></div>
|
||||
<div
|
||||
class="drag-resize resize-bottom"
|
||||
draggable="true"
|
||||
@mousedown.stop="onMousedown($event, 'center', 'end')"
|
||||
></div>
|
||||
<div
|
||||
class="drag-resize resize-left"
|
||||
draggable="true"
|
||||
@mousedown.stop="onMousedown($event, 'start', 'center')"
|
||||
></div>
|
||||
<div
|
||||
class="drag-resize resize-right"
|
||||
draggable="true"
|
||||
@mousedown.stop="onMousedown($event, 'end', 'center')"
|
||||
></div>
|
||||
<div
|
||||
class="drag-resize resize-top-left"
|
||||
draggable="true"
|
||||
@mousedown.stop="onMousedown($event, 'start', 'start')"
|
||||
></div>
|
||||
<div
|
||||
class="drag-resize resize-top-right"
|
||||
draggable="true"
|
||||
@mousedown.stop="onMousedown($event, 'end', 'start')"
|
||||
></div>
|
||||
<div
|
||||
class="drag-resize resize-bottom-left"
|
||||
draggable="true"
|
||||
@mousedown.stop="onMousedown($event, 'start', 'end')"
|
||||
></div>
|
||||
<div
|
||||
class="drag-resize resize-bottom-right"
|
||||
draggable="true"
|
||||
@mousedown.stop="onMousedown($event, 'end', 'end')"
|
||||
></div>
|
||||
</template>
|
||||
<div v-if="showAction" class="corner-mark-right" :style="fixStyle">
|
||||
<div v-if="showAction" ref="optionRef" class="corner-mark-right" :style="fixStyle">
|
||||
<template v-if="!isModal">
|
||||
<div v-if="showToParent" title="选择父级">
|
||||
<icon-chevron-left @click.stop="selectParent"></icon-chevron-left>
|
||||
|
|
@ -68,13 +100,13 @@
|
|||
<div v-show="hoverState.configure?.isContainer" class="corner-mark-bottom-right">拖放元素到容器内</div>
|
||||
</div>
|
||||
<div v-show="lineState.height && lineState.width" class="canvas-rect line">
|
||||
<div :class="['hover-line', lineState.position]">
|
||||
<div :class="['hover-line', lineState.position, { forbidden: lineState.forbidden }]">
|
||||
<div v-if="lineState.position === 'in' && hoverState.configure" class="choose-slots"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { watchPostEffect, ref, watch, computed } from 'vue'
|
||||
import { watchPostEffect, ref, watch, computed, nextTick } from 'vue'
|
||||
import {
|
||||
IconDel,
|
||||
IconSetting,
|
||||
|
|
@ -85,6 +117,7 @@ import {
|
|||
IconEyeclose
|
||||
} from '@opentiny/vue-icon'
|
||||
import {
|
||||
canvasState,
|
||||
getCurrent,
|
||||
removeNodeById,
|
||||
selectNode,
|
||||
|
|
@ -95,7 +128,7 @@ import {
|
|||
dragStart,
|
||||
getCurrentElement
|
||||
} from './container'
|
||||
import { useResource } from '@opentiny/tiny-engine-controller'
|
||||
import { useLayout, useResource } from '@opentiny/tiny-engine-controller'
|
||||
import { Popover } from '@opentiny/vue'
|
||||
import shortCutPopover from './shortCutPopover.vue'
|
||||
|
||||
|
|
@ -103,8 +136,6 @@ import shortCutPopover from './shortCutPopover.vue'
|
|||
const OPTION_BAR_HEIGHT = 24
|
||||
// 标签高度
|
||||
const LABEL_HEIGHT = 24
|
||||
// 操作条最大宽度
|
||||
const MAX_OPTION_WIDTH = 110
|
||||
|
||||
// 画布右边滚动条宽度
|
||||
const SCROLL_BAR_WIDTH = 8
|
||||
|
|
@ -112,6 +143,11 @@ const SCROLL_BAR_WIDTH = 8
|
|||
// 当工具操作条和标签高度并排显示时,需要的间距 6px
|
||||
const OPTION_SPACE = 6
|
||||
|
||||
// 选中框的边框宽度
|
||||
const SELECTION_BORDER_WIDTH = 2
|
||||
|
||||
const STYLE_UNSET = 'unset'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
IconDel: IconDel(),
|
||||
|
|
@ -204,6 +240,7 @@ export default {
|
|||
return config?.configure?.isModal
|
||||
})
|
||||
|
||||
const optionRef = ref(null)
|
||||
const fixStyle = ref('')
|
||||
|
||||
let showPopover = ref(false)
|
||||
|
|
@ -265,45 +302,188 @@ export default {
|
|||
const labelRef = ref(null)
|
||||
const labelStyle = ref('')
|
||||
|
||||
const bottomPanelHeight = ref(0)
|
||||
const topToolbarHeight = ref(0)
|
||||
|
||||
watchPostEffect(() => {
|
||||
if (!bottomPanelHeight.value) {
|
||||
bottomPanelHeight.value = document.querySelector('#tiny-bottom-panel')?.offsetHeight
|
||||
const positions = {
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right',
|
||||
TOP: 'top',
|
||||
BOTTOM: 'bottom',
|
||||
isHorizontal(position) {
|
||||
return [this.LEFT, this.RIGHT].includes(position)
|
||||
},
|
||||
isVertical(position) {
|
||||
return [this.TOP, this.BOTTOM].includes(position)
|
||||
}
|
||||
if (!topToolbarHeight.value) {
|
||||
topToolbarHeight.value = document.querySelector('.tiny-engine-toolbar')?.offsetHeight
|
||||
}
|
||||
|
||||
class Align {
|
||||
alignLeft = false
|
||||
horizontalValue = 0
|
||||
alignTop = false
|
||||
verticalValue = 0
|
||||
|
||||
constructor({ alignLeft, horizontalValue, alignTop, verticalValue }) {
|
||||
this.alignLeft = alignLeft
|
||||
this.horizontalValue = horizontalValue
|
||||
this.alignTop = alignTop
|
||||
this.verticalValue = verticalValue
|
||||
}
|
||||
|
||||
const { left, top, width, height } = props.selectState
|
||||
align(position, value = 0) {
|
||||
if (positions.isHorizontal(position)) {
|
||||
this.alignLeft = position === positions.LEFT
|
||||
this.horizontalValue = value
|
||||
return this
|
||||
}
|
||||
if (positions.isVertical(position)) {
|
||||
this.alignTop = position === positions.TOP
|
||||
this.horizontalValue = value
|
||||
return this
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
toStyleValue() {
|
||||
const styleObj = {}
|
||||
|
||||
if (this.alignLeft) {
|
||||
styleObj.left = this.horizontalValue
|
||||
styleObj.right = STYLE_UNSET
|
||||
} else {
|
||||
styleObj.right = this.horizontalValue
|
||||
styleObj.left = STYLE_UNSET
|
||||
}
|
||||
|
||||
if (this.alignTop) {
|
||||
styleObj.top = this.verticalValue
|
||||
styleObj.bottom = STYLE_UNSET
|
||||
} else {
|
||||
styleObj.bottom = this.verticalValue
|
||||
styleObj.top = STYLE_UNSET
|
||||
}
|
||||
|
||||
return this.styleObj2Str(styleObj)
|
||||
}
|
||||
|
||||
styleObj2Str = (styleObj) => {
|
||||
return Object.entries(styleObj)
|
||||
.map(([key, value]) => {
|
||||
const num = Number(value)
|
||||
|
||||
if (Number.isNaN(num)) {
|
||||
return `${key}:${value}`
|
||||
}
|
||||
|
||||
const val = positions.isHorizontal(key) ? num - SELECTION_BORDER_WIDTH : num
|
||||
return `${key}:${val}px`
|
||||
})
|
||||
.join(';')
|
||||
}
|
||||
}
|
||||
|
||||
const getStyleValues = (selectState, canvasSize, labelWidth, optionWidth) => {
|
||||
const { left, top, width, height, doc } = selectState
|
||||
const { width: canvasWidth, height: canvasHeight } = canvasSize
|
||||
// 标签宽度和工具操作条宽度之和加上间距
|
||||
const fullRectWidth = labelWidth + optionWidth + OPTION_SPACE
|
||||
|
||||
// 是否 将label 标签放置到底部,判断 top 距离
|
||||
const isLabelAtBottom = top <= topToolbarHeight.value + LABEL_HEIGHT
|
||||
const isLabelAtBottom = top < LABEL_HEIGHT
|
||||
const labelAlign = new Align({
|
||||
alignLeft: true,
|
||||
horizontalValue: 0,
|
||||
alignTop: !isLabelAtBottom,
|
||||
verticalValue: -LABEL_HEIGHT
|
||||
})
|
||||
|
||||
// 是否将操作栏放置到底部,判断当前选中组件底部与页面底部的距离。
|
||||
const isOptionAtBottom = window.innerHeight - top - height - bottomPanelHeight.value > OPTION_BAR_HEIGHT
|
||||
const isOptionAtBottom = canvasHeight - top - height >= OPTION_BAR_HEIGHT
|
||||
const optionAlign = new Align({
|
||||
alignLeft: false,
|
||||
horizontalValue: 0,
|
||||
alignTop: !isOptionAtBottom,
|
||||
verticalValue: -OPTION_BAR_HEIGHT
|
||||
})
|
||||
|
||||
// 选中组件需要最小的宽度,如果小于这个最小宽度,label 和 option 组件可能会重叠遮挡,labelRef.value.clientWidth:label 的宽度
|
||||
const minWidth = MAX_OPTION_WIDTH + labelRef.value?.clientWidth || 0
|
||||
let translateXDis = 0
|
||||
const scrollBarWidth = doc.documentElement.scrollHeight > doc.documentElement.clientHeight ? SCROLL_BAR_WIDTH : 0
|
||||
|
||||
const siteCanvas = document.querySelector('.site-canvas')
|
||||
const right = siteCanvas.getBoundingClientRect().right
|
||||
// 判断是否偏右,偏右且重叠的话,需要移动 label 的位移,不能移动 option 的位移,否则有可能被遮挡
|
||||
const isOverRight = right <= left + width + SCROLL_BAR_WIDTH
|
||||
if (width < fullRectWidth) {
|
||||
// 选中框宽度小于标签宽度和工具操作条宽度之和加上间距
|
||||
|
||||
// 如果选中组件宽度小于最小宽度要求,则需要位移
|
||||
if (width < minWidth) {
|
||||
translateXDis = MAX_OPTION_WIDTH - width + (labelRef.value?.clientWidth || 0) + OPTION_SPACE
|
||||
// 如果labe宽度大于选中框宽度,并且label右侧已经超出画布,则label对齐右侧
|
||||
const isLabelAlignRight = labelWidth > width && left + labelWidth + scrollBarWidth > canvasWidth
|
||||
if (isLabelAlignRight) {
|
||||
labelAlign.align(positions.RIGHT)
|
||||
}
|
||||
|
||||
// 如果option宽度大于选中框宽度,并且option左侧已经超出画布,则option对齐左侧
|
||||
const isOptionAlignLeft = optionWidth > width && left + width - optionWidth < 0
|
||||
if (isOptionAlignLeft) {
|
||||
optionAlign.align(positions.LEFT)
|
||||
}
|
||||
|
||||
if (isLabelAtBottom === isOptionAtBottom) {
|
||||
// 标签框和工具操作框都在顶部或者都在底部
|
||||
|
||||
if (left + fullRectWidth < canvasWidth) {
|
||||
// 都放在左侧
|
||||
labelAlign.align(positions.LEFT)
|
||||
optionAlign.align(positions.LEFT, labelWidth + OPTION_SPACE)
|
||||
} else {
|
||||
// 都放在右侧
|
||||
optionAlign.align(positions.RIGHT)
|
||||
labelAlign.align(positions.RIGHT, optionWidth + OPTION_SPACE)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (left < 0) {
|
||||
labelAlign.align(positions.LEFT, Math.min(-left, width - fullRectWidth))
|
||||
}
|
||||
|
||||
if (left + width + scrollBarWidth > canvasWidth) {
|
||||
optionAlign.align(
|
||||
positions.RIGHT,
|
||||
Math.min(left + width + scrollBarWidth - canvasWidth, width - fullRectWidth)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
labelStyle.value = `top: unset; ${isLabelAtBottom ? 'bottom' : 'top'}: -${LABEL_HEIGHT}px; ${
|
||||
isOverRight && isLabelAtBottom === isOptionAtBottom && `left: -${translateXDis}px;`
|
||||
}`
|
||||
return {
|
||||
labelStyleValue: labelAlign.toStyleValue(),
|
||||
optionStyleValue: optionAlign.toStyleValue()
|
||||
}
|
||||
}
|
||||
|
||||
fixStyle.value = `
|
||||
${translateXDis && !isOverRight ? `transform: translateX(${translateXDis}px);` : ''}
|
||||
${isOptionAtBottom ? 'bottom' : 'top'}: -${OPTION_BAR_HEIGHT}px;`
|
||||
watchPostEffect(async () => {
|
||||
const { left, top, width, height, doc } = props.selectState
|
||||
|
||||
// nextTick后ref才能获取到元素。需要把监听的依赖放在await之前,否则无法监听变化
|
||||
await nextTick()
|
||||
|
||||
if (labelRef.value && !optionRef.value) {
|
||||
// 选中body的情况
|
||||
labelStyle.value = `left: 0; right: unset; top: unset; bottom: 0`
|
||||
return
|
||||
}
|
||||
|
||||
if (!labelRef.value || !optionRef.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const scale = useLayout().getScale()
|
||||
const canvasRect = canvasState.iframe.getBoundingClientRect()
|
||||
const { width: labelWidth } = labelRef.value.getBoundingClientRect()
|
||||
const { width: optionWidth } = optionRef.value.getBoundingClientRect()
|
||||
|
||||
// canvas容器中,iframe以及iframe之外的元素clientRect的尺寸都是缩放过的,除以scale得到原始大小
|
||||
const { labelStyleValue, optionStyleValue } = getStyleValues(
|
||||
{ left, top, width, height, doc },
|
||||
{ width: canvasRect.width / scale, height: canvasRect.height / scale },
|
||||
labelWidth / scale,
|
||||
optionWidth / scale
|
||||
)
|
||||
|
||||
labelStyle.value = labelStyleValue
|
||||
fixStyle.value = optionStyleValue
|
||||
})
|
||||
|
||||
return {
|
||||
|
|
@ -313,6 +493,7 @@ export default {
|
|||
copy,
|
||||
hide,
|
||||
selectParent,
|
||||
optionRef,
|
||||
fixStyle,
|
||||
showAction,
|
||||
showPopover,
|
||||
|
|
@ -329,7 +510,7 @@ export default {
|
|||
|
||||
<style lang="less">
|
||||
.canvas-rect {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
pointer-events: none;
|
||||
border: 1px solid var(--ti-lowcode-canvas-rect-border-color);
|
||||
|
|
@ -392,11 +573,12 @@ export default {
|
|||
height: 100%;
|
||||
background: var(--ti-lowcode-canvas-hover-line-in-bg-color);
|
||||
}
|
||||
&.forbid {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
&.forbidden:not(.in) {
|
||||
background: var(--ti-lowcode-canvas-hover-line-forbid-bg-color);
|
||||
}
|
||||
&.forbidden.in {
|
||||
background: var(--ti-lowcode-canvas-hover-line-in-forbid-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
.choose-slots {
|
||||
|
|
@ -454,7 +636,6 @@ export default {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
right: -1px;
|
||||
height: 24px;
|
||||
padding: 0 4px;
|
||||
color: var(--ti-lowcode-canvas-corner-mark-right-color);
|
||||
|
|
@ -479,7 +660,6 @@ export default {
|
|||
.corner-mark-left {
|
||||
white-space: nowrap;
|
||||
pointer-events: all;
|
||||
left: -2px;
|
||||
color: var(--ti-lowcode-canvas-select-corner-mark-left-color);
|
||||
background: var(--ti-lowcode-canvas-select-corner-mark-left-bg-color);
|
||||
svg {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
:windowGetClickEventTarget="target"
|
||||
:resize="canvasState.type === 'absolute'"
|
||||
@select-slot="selectSlot"
|
||||
@setting="settingModle"
|
||||
@setting="settingModel"
|
||||
></canvas-action>
|
||||
<canvas-divider :selectState="selectState"></canvas-divider>
|
||||
<canvas-resize-border :iframe="iframe"></canvas-resize-border>
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
<script>
|
||||
import { onMounted, ref, computed, onUnmounted } from 'vue'
|
||||
import { iframeMonitoring } from '@opentiny/tiny-engine-common/js/monitor'
|
||||
import { iframeMonitoring } from '@opentiny/tiny-engine-controller/js/monitor'
|
||||
import { useTranslate, useCanvas, useResource } from '@opentiny/tiny-engine-controller'
|
||||
import CanvasAction from './CanvasAction.vue'
|
||||
import CanvasResize from './CanvasResize.vue'
|
||||
|
|
@ -50,12 +50,12 @@ import {
|
|||
updateRect,
|
||||
getElement,
|
||||
dragStart,
|
||||
getOffset,
|
||||
selectNode,
|
||||
initCanvas,
|
||||
clearLineState,
|
||||
querySelectById,
|
||||
getCurrent
|
||||
getCurrent,
|
||||
canvasApi
|
||||
} from './container'
|
||||
|
||||
export default {
|
||||
|
|
@ -71,7 +71,7 @@ export default {
|
|||
const insertPanel = ref(null)
|
||||
const insertPosition = ref(false)
|
||||
const loading = computed(() => useCanvas().isLoading())
|
||||
let showSettingModle = ref(false)
|
||||
let showSettingModel = ref(false)
|
||||
let target = ref(null)
|
||||
|
||||
const setCurrentNode = async (event) => {
|
||||
|
|
@ -100,11 +100,13 @@ export default {
|
|||
|
||||
// 如果是点击右键则打开右键菜单
|
||||
if (event.button === 2) {
|
||||
openMenu(getOffset(event.target), event)
|
||||
openMenu(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useCanvas().initCanvasApi(canvasApi)
|
||||
|
||||
const beforeCanvasReady = () => {
|
||||
if (iframe.value) {
|
||||
const win = iframe.value.contentWindow
|
||||
|
|
@ -123,8 +125,30 @@ export default {
|
|||
const doc = iframe.value.contentDocument
|
||||
const win = iframe.value.contentWindow
|
||||
|
||||
let isScrolling = false
|
||||
|
||||
// 以下是内部iframe监听的事件
|
||||
win.addEventListener('mousedown', (event) => {
|
||||
// html元素使用scroll和mouseup事件处理
|
||||
if (event.target === doc.documentElement) {
|
||||
isScrolling = false
|
||||
return
|
||||
}
|
||||
|
||||
insertPosition.value = false
|
||||
setCurrentNode(event)
|
||||
target.value = event.target
|
||||
})
|
||||
|
||||
win.addEventListener('scroll', () => {
|
||||
isScrolling = true
|
||||
})
|
||||
|
||||
win.addEventListener('mouseup', (event) => {
|
||||
if (event.target !== doc.documentElement || isScrolling) {
|
||||
return
|
||||
}
|
||||
|
||||
insertPosition.value = false
|
||||
setCurrentNode(event)
|
||||
target.value = event.target
|
||||
|
|
@ -156,8 +180,8 @@ export default {
|
|||
}
|
||||
}
|
||||
// 设置弹窗
|
||||
const settingModle = () => {
|
||||
showSettingModle.value = true
|
||||
const settingModel = () => {
|
||||
showSettingModel.value = true
|
||||
}
|
||||
|
||||
const updateI18n = (message) => {
|
||||
|
|
@ -194,7 +218,9 @@ export default {
|
|||
|
||||
onMounted(() => run(iframe))
|
||||
onUnmounted(() => {
|
||||
removeHostkeyEvent(iframe.value.contentDocument)
|
||||
if (iframe.value?.contentDocument) {
|
||||
removeHostkeyEvent(iframe.value.contentDocument)
|
||||
}
|
||||
window.removeEventListener('message', updateI18n, false)
|
||||
})
|
||||
|
||||
|
|
@ -212,9 +238,9 @@ export default {
|
|||
canvasState,
|
||||
insertComponent,
|
||||
insertPanel,
|
||||
settingModle,
|
||||
settingModel,
|
||||
target,
|
||||
showSettingModle,
|
||||
showSettingModel,
|
||||
insertPosition,
|
||||
loading
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ const ROW_SNIPPET = {
|
|||
grow: true,
|
||||
shrink: true,
|
||||
widthType: 'auto'
|
||||
}
|
||||
},
|
||||
children: []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -103,16 +104,7 @@ export default {
|
|||
if (schema.componentName === 'CanvasCol') {
|
||||
// 当前组件为空组件,直接切成两行
|
||||
if (!schema.children?.length) {
|
||||
schema.children = [
|
||||
{
|
||||
...extend(true, {}, ROW_SNIPPET),
|
||||
children: [{ ...extend(true, {}, COL_SNIPPET) }]
|
||||
},
|
||||
{
|
||||
...extend(true, {}, ROW_SNIPPET),
|
||||
children: [{ ...extend(true, {}, COL_SNIPPET) }]
|
||||
}
|
||||
]
|
||||
schema.children = [extend(true, {}, ROW_SNIPPET), extend(true, {}, ROW_SNIPPET)]
|
||||
} else if (schema.children[0].componentName !== 'CanvasRow') {
|
||||
// 当前组件不为空组件且第一个孩子不为 row,则是第一次切割,切割成两行,需要将原来有的 children 放置到第一个 row 的 col
|
||||
schema.children = [
|
||||
|
|
@ -129,7 +121,7 @@ export default {
|
|||
]
|
||||
} else {
|
||||
// 已经切割过了,直接加一行
|
||||
schema.children.push(...extend(true, {}, ROW_SNIPPET))
|
||||
schema.children.push(extend(true, {}, ROW_SNIPPET))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +194,7 @@ export default {
|
|||
|
||||
<style lang="less" scoped>
|
||||
.divider-wrapper {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -239,7 +231,7 @@ export default {
|
|||
}
|
||||
|
||||
.divider-line {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
border: 1px dashed var(--ti-lowcode-common-primary-color);
|
||||
z-index: 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export default {
|
|||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
emits: ['click']
|
||||
|
|
@ -44,37 +44,23 @@ export default {
|
|||
li {
|
||||
width: unset !important;
|
||||
background: var(--ti-lowcode-breadcrumb-bg);
|
||||
a {
|
||||
.label {
|
||||
padding: 0 3px 0 16px;
|
||||
border-top: 0;
|
||||
color: var(--ti-lowcode-breadcrumb-color);
|
||||
transition: 0.3s;
|
||||
&::after {
|
||||
display: inline-block;
|
||||
right: -6px;
|
||||
border-left: 6px solid var(--ti-lowcode-breadcrumb-bg);
|
||||
transition: 0.3s;
|
||||
}
|
||||
&::before {
|
||||
display: inline-block;
|
||||
right: -7px;
|
||||
left: unset;
|
||||
border-left: 6px solid var(--ti-lowcode-breadcrumb-icon-color);
|
||||
transition: 0.3s;
|
||||
z-index: 1;
|
||||
}
|
||||
&:hover {
|
||||
background: var(--ti-lowcode-breadcrumb-hover-bg);
|
||||
cursor: pointer;
|
||||
&::after {
|
||||
border-left-color: var(--ti-lowcode-breadcrumb-hover-bg);
|
||||
border-left-color: var(--ti-steps-advanced-li-hover-bg-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
&:last-child a {
|
||||
&:last-child .label {
|
||||
border-right: 0px solid var(--ti-lowcode-breadcrumb-color);
|
||||
border-radius: 0;
|
||||
}
|
||||
&:first-child a {
|
||||
&:first-child .label {
|
||||
border-right: 0px solid var(--ti-lowcode-breadcrumb-color);
|
||||
border-radius: 0;
|
||||
border-left: unset;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
<span>{{ item.name }}</span>
|
||||
<span v-if="item.items"><icon-right></icon-right></span>
|
||||
</div>
|
||||
<ul v-if="item.items && current === item" class="sub-menu menu-item">
|
||||
<ul v-if="item.items && current === item" class="sub-menu menu-item" :style="subMenuStyles">
|
||||
<template v-for="(subItem, subIndex) in item.items" :key="subIndex">
|
||||
<li
|
||||
:class="[{ 'menu-item-disabled': subItem.check && !subItem.check?.() }]"
|
||||
|
|
@ -27,15 +27,14 @@
|
|||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<save-new-block :boxVisibility="boxVisibility" fromCanvas @close="close"></save-new-block>
|
||||
<SaveNewBlock :boxVisibility="boxVisibility" fromCanvas @close="close"></SaveNewBlock>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="jsx">
|
||||
import { ref, reactive, nextTick } from 'vue'
|
||||
import { getConfigure, getController, getCurrent, copyNode, removeNodeById } from './container'
|
||||
import { canvasState, getConfigure, getController, getCurrent, copyNode, removeNodeById } from './container'
|
||||
import { useLayout, useModal, useCanvas } from '@opentiny/tiny-engine-controller'
|
||||
import { SaveNewBlock } from '@opentiny/tiny-engine-common'
|
||||
import { iconRight } from '@opentiny/vue-icon'
|
||||
|
||||
const menuState = reactive({
|
||||
|
|
@ -46,27 +45,35 @@ const menuState = reactive({
|
|||
|
||||
const current = ref(null)
|
||||
const menuDom = ref(null)
|
||||
const subMenuStyles = ref(null)
|
||||
|
||||
export const closeMenu = () => {
|
||||
menuState.show = false
|
||||
current.value = null
|
||||
}
|
||||
|
||||
export const openMenu = (offset, event) => {
|
||||
const { x, y } = offset
|
||||
const { getScale } = useLayout()
|
||||
export const openMenu = (event) => {
|
||||
menuState.position = {
|
||||
// 位置处于画布右侧边缘时需要调整显示方向 TODO
|
||||
left: event.clientX * getScale() + x + 2 + 'px',
|
||||
top: event.clientY * getScale() + y + 'px'
|
||||
left: event.clientX + 2 + 'px',
|
||||
top: event.clientY + 'px'
|
||||
}
|
||||
menuState.show = sessionStorage.getItem('pageInfo') ? true : false
|
||||
|
||||
nextTick(() => {
|
||||
if (menuDom.value) {
|
||||
const { bottom, height, top } = menuDom.value.getBoundingClientRect()
|
||||
if (bottom > document.body?.clientHeight) {
|
||||
menuState.position.top = top - height + 'px'
|
||||
const { right, bottom, width, height } = menuDom.value.getBoundingClientRect()
|
||||
const canvasRect = canvasState.iframe.getBoundingClientRect()
|
||||
if (bottom > canvasRect.bottom) {
|
||||
menuState.position.top = `${parseInt(menuState.position.top) - height}px`
|
||||
}
|
||||
if (right > canvasRect.right) {
|
||||
menuState.position.left = `${parseInt(menuState.position.left) - width - 2}px`
|
||||
}
|
||||
// sub-menu样式width为100px,少于100宽度的空白区域则放置到左侧
|
||||
if (right + 100 < canvasRect.right) {
|
||||
subMenuStyles.value = { right: '-100px' }
|
||||
} else {
|
||||
subMenuStyles.value = { left: '-100px' }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -74,7 +81,6 @@ export const openMenu = (offset, event) => {
|
|||
|
||||
export default {
|
||||
components: {
|
||||
SaveNewBlock,
|
||||
IconRight: iconRight()
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
|
|
@ -228,6 +234,7 @@ export default {
|
|||
close,
|
||||
current,
|
||||
menuDom,
|
||||
subMenuStyles,
|
||||
actionDisabled,
|
||||
onShowChildrenMenu
|
||||
}
|
||||
|
|
@ -237,7 +244,7 @@ export default {
|
|||
|
||||
<style lang="less" scoped>
|
||||
.context-menu {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
}
|
||||
.menu-item {
|
||||
|
|
@ -278,7 +285,6 @@ export default {
|
|||
&.sub-menu {
|
||||
width: 100px;
|
||||
position: absolute;
|
||||
right: -100px;
|
||||
top: -2px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,26 +17,18 @@ import { canvasState } from './container'
|
|||
export default {
|
||||
setup() {
|
||||
const sizeStyle = computed(() => {
|
||||
const { width, maxWidth, minWidth, scale } = useLayout().getDimension()
|
||||
const { width, height, maxWidth, minWidth } = useLayout().getDimension()
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
maxWidth,
|
||||
minWidth,
|
||||
height: `${100 / scale}%`,
|
||||
transform: `scale(${scale}) translateY(-${(100 / scale - 100) / 2}%)`
|
||||
minWidth
|
||||
}
|
||||
})
|
||||
|
||||
const mouseDown = ref(false)
|
||||
const resizeDom = ref(null)
|
||||
|
||||
const onMouseMove = (event) => {
|
||||
if (mouseDown.value) {
|
||||
event.preventDefault()
|
||||
calculateSize(event)
|
||||
}
|
||||
}
|
||||
|
||||
const calculateSize = ({ movementX }) => {
|
||||
const dimension = useLayout().getDimension()
|
||||
const { maxWidth, minWidth, width } = dimension
|
||||
|
|
@ -48,6 +40,30 @@ export default {
|
|||
})
|
||||
}
|
||||
|
||||
const onMouseMove = (event) => {
|
||||
if (mouseDown.value) {
|
||||
event.preventDefault()
|
||||
calculateSize(event)
|
||||
}
|
||||
}
|
||||
|
||||
const onMouseUp = () => {
|
||||
const iframe = canvasState.iframe
|
||||
|
||||
if (iframe) {
|
||||
iframe.style['pointer-events'] = 'auto'
|
||||
mouseDown.value = false
|
||||
|
||||
document.removeEventListener('mousemove', onMouseMove, { passive: false })
|
||||
document.removeEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
}
|
||||
|
||||
const bindEvents = () => {
|
||||
document.addEventListener('mousemove', onMouseMove, { passive: false })
|
||||
document.addEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
|
||||
const onMouseDown = () => {
|
||||
const iframe = canvasState.iframe
|
||||
|
||||
|
|
@ -58,44 +74,35 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
const onMouseUp = () => {
|
||||
const iframe = canvasState.iframe
|
||||
|
||||
if (iframe) {
|
||||
iframe.style['pointer-events'] = 'auto'
|
||||
mouseDown.value = false
|
||||
unbindEvents()
|
||||
}
|
||||
}
|
||||
|
||||
const bindEvents = () => {
|
||||
document.addEventListener('mousemove', onMouseMove, { passive: false })
|
||||
document.addEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
|
||||
const unbindEvents = () => {
|
||||
document.removeEventListener('mousemove', onMouseMove, { passive: false })
|
||||
document.removeEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
|
||||
const setScale = () => {
|
||||
useLayout().setDimension({ scale: 1 })
|
||||
nextTick(() => {
|
||||
const canvasWrap = document.querySelector('#canvas-wrap')
|
||||
|
||||
if (!canvasWrap) {
|
||||
return
|
||||
}
|
||||
|
||||
const rate = canvasWrap.offsetWidth / resizeDom.value.offsetWidth
|
||||
useLayout().setDimension({
|
||||
scale: rate > 1 ? 1 : rate
|
||||
scale: Math.min(rate, 1)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
watch(() => useLayout().getDimension().width, setScale, { flush: 'post' })
|
||||
watch(() => useLayout().getDimension().width, setScale, { flush: 'post', immediate: true })
|
||||
|
||||
watch(() => useLayout().getPluginState().fixedPanels, setScale, { flush: 'post' })
|
||||
|
||||
watch(
|
||||
() => useLayout().getPluginState().render,
|
||||
(value) => !value && setScale(),
|
||||
(value) => {
|
||||
const currentFixed = useLayout().getPluginState().fixedPanels.includes(value)
|
||||
|
||||
if (!value || currentFixed) {
|
||||
setScale()
|
||||
}
|
||||
},
|
||||
{ flush: 'post' }
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
<script>
|
||||
import { reactive, watch } from 'vue'
|
||||
import { useLayout } from '@opentiny/tiny-engine-controller'
|
||||
import { getCurrent, updateRect, selectState, querySelectById } from './container'
|
||||
|
||||
export default {
|
||||
|
|
@ -38,12 +39,17 @@ export default {
|
|||
}
|
||||
|
||||
const handleResize = (event, type) => {
|
||||
let { clientX, clientY } = event
|
||||
if (!props.iframe) {
|
||||
return
|
||||
}
|
||||
|
||||
if (type === 'iframe' && props.iframe) {
|
||||
const iframeRect = props.iframe.getBoundingClientRect()
|
||||
clientX += iframeRect.left
|
||||
clientY += iframeRect.top
|
||||
let { clientX, clientY } = event
|
||||
const iframeRect = props.iframe.getBoundingClientRect()
|
||||
const scale = useLayout().getScale()
|
||||
|
||||
if (type !== 'iframe') {
|
||||
clientX = (clientX - iframeRect.left) / scale
|
||||
clientY = (clientY - iframeRect.top) / scale
|
||||
}
|
||||
|
||||
const { parent, schema } = getCurrent()
|
||||
|
|
@ -65,14 +71,9 @@ export default {
|
|||
const parentWidth = parseInt(window.getComputedStyle(parentDomNode).width, 10)
|
||||
|
||||
// 最大宽度不能大于父组件宽度
|
||||
if (newWidth >= parentWidth) {
|
||||
newWidth = parentWidth
|
||||
}
|
||||
|
||||
newWidth = Math.min(newWidth, parentWidth)
|
||||
// 最小宽度32
|
||||
if (newWidth <= 32) {
|
||||
newWidth = 32
|
||||
}
|
||||
newWidth = Math.max(newWidth, 32)
|
||||
|
||||
schema.props.flexBasis = `${newWidth}px`
|
||||
schema.props.widthType = 'fixed'
|
||||
|
|
@ -186,7 +187,7 @@ export default {
|
|||
|
||||
<style lang="less" scoped>
|
||||
.resize-border {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -20,15 +20,16 @@ import {
|
|||
NODE_LOOP
|
||||
} from '../common'
|
||||
import { useCanvas, useLayout, useResource, useTranslate } from '@opentiny/tiny-engine-controller'
|
||||
import { isVsCodeEnv } from '@opentiny/tiny-engine-controller/js/environments'
|
||||
import Builtin from '../builtin/builtin.json'
|
||||
|
||||
export const POSITION = Object.freeze({
|
||||
TOP: 'top',
|
||||
BOTTOM: 'bottom',
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right',
|
||||
IN: 'in',
|
||||
FORBID: 'forbid'
|
||||
IN: 'in'
|
||||
})
|
||||
import { isVsCodeEnv } from '@opentiny/tiny-engine-common/js/environments'
|
||||
|
||||
const initialDragState = {
|
||||
keydown: false,
|
||||
|
|
@ -51,6 +52,28 @@ export const canvasState = shallowReactive({
|
|||
loopId: null
|
||||
})
|
||||
|
||||
export const getRenderer = () => canvasState.renderer
|
||||
|
||||
export const getController = () => canvasState.controller
|
||||
|
||||
export const getDocument = () => canvasState.iframe.contentDocument
|
||||
|
||||
export const getWindow = () => canvasState.iframe.contentWindow
|
||||
|
||||
export const getCurrent = () => {
|
||||
return {
|
||||
schema: canvasState.current,
|
||||
parent: canvasState.parent,
|
||||
loopId: canvasState.loopId
|
||||
}
|
||||
}
|
||||
|
||||
export const getGlobalState = () => getRenderer().getGlobalState()
|
||||
|
||||
export const getNode = (id, parent) => getRenderer()?.getNode(id, parent)
|
||||
|
||||
export const getSchema = () => getRenderer()?.getSchema()
|
||||
|
||||
export const getContext = () => {
|
||||
return getRenderer().getContext()
|
||||
}
|
||||
|
|
@ -76,8 +99,10 @@ const initialLineState = {
|
|||
width: 0,
|
||||
left: 0,
|
||||
position: '',
|
||||
forbidden: false,
|
||||
id: '',
|
||||
config: null
|
||||
config: null,
|
||||
doc: null
|
||||
}
|
||||
|
||||
// 选中画布中元素时的状态
|
||||
|
|
@ -95,6 +120,43 @@ export const lineState = reactive({
|
|||
...initialLineState
|
||||
})
|
||||
|
||||
export const clearHover = () => {
|
||||
Object.assign(hoverState, initialRectState, { slot: null })
|
||||
}
|
||||
|
||||
export const clearSelect = () => {
|
||||
canvasState.current = null
|
||||
canvasState.parent = null
|
||||
Object.assign(selectState, initialRectState)
|
||||
// 临时借用 remote 事件出发 currentSchema 更新
|
||||
canvasState?.emit?.('remove')
|
||||
}
|
||||
|
||||
const smoothScroll = {
|
||||
timmer: null,
|
||||
/**
|
||||
*
|
||||
* @param {*} up 方向
|
||||
* @param {*} step 每次滚动距离
|
||||
* @param {*} time 滚动延时(不得大于系统滚动时长,否则可能出现卡顿效果)
|
||||
*/
|
||||
start(up, step = 40, time = 100) {
|
||||
const dom = getDocument().documentElement
|
||||
const fn = () => {
|
||||
const top = up ? dom.scrollTop + step : dom.scrollTop - step
|
||||
|
||||
dom.scrollTo({ top, behavior: 'smooth' })
|
||||
this.timmer = setTimeout(fn, time)
|
||||
}
|
||||
|
||||
this.timmer || fn()
|
||||
},
|
||||
stop() {
|
||||
clearTimeout(this.timmer)
|
||||
this.timmer = null
|
||||
}
|
||||
}
|
||||
|
||||
export const dragStart = (
|
||||
data,
|
||||
element,
|
||||
|
|
@ -146,6 +208,12 @@ export const getElement = (element) => {
|
|||
if (element === element.ownerDocument.body) {
|
||||
return element
|
||||
}
|
||||
|
||||
// 如果当前元素是画布的html,返回画布的body
|
||||
if (element === element.ownerDocument.documentElement) {
|
||||
return element.ownerDocument.body
|
||||
}
|
||||
|
||||
if (!element || element.nodeType !== 1) {
|
||||
return undefined
|
||||
}
|
||||
|
|
@ -159,6 +227,23 @@ export const getElement = (element) => {
|
|||
return undefined
|
||||
}
|
||||
|
||||
const getRect = (element) => {
|
||||
if (element === getDocument().body) {
|
||||
const { innerWidth: width, innerHeight: height } = getWindow()
|
||||
return {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: width,
|
||||
bottom: height,
|
||||
width,
|
||||
height,
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
return element.getBoundingClientRect()
|
||||
}
|
||||
|
||||
const inserAfter = ({ parent, node, data }) => {
|
||||
const parentChildren = parent.children
|
||||
const index = parentChildren.indexOf(node)
|
||||
|
|
@ -215,110 +300,245 @@ export const removeNodeById = (id) => {
|
|||
canvasState.emit('remove')
|
||||
}
|
||||
|
||||
export const insertNode = (node, position = POSITION.IN, select = true) => {
|
||||
if (!node.parent) {
|
||||
insertInner({ node: canvasState.schema, data: node.data }, position)
|
||||
export const querySelectById = (id) => {
|
||||
let selector = `[${NODE_UID}="${id}"]`
|
||||
const doc = canvasState.iframe.contentDocument
|
||||
let element = doc.querySelector(selector)
|
||||
const loopId = element?.getAttribute('loop-id')
|
||||
if (element && loopId) {
|
||||
const currentLoopId = getCurrent().loopId
|
||||
selector = `[${NODE_UID}="${id}"][${NODE_LOOP}="${currentLoopId}"]`
|
||||
element = doc.querySelector(selector)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
||||
export const getCurrentElement = () => querySelectById(getCurrent().schema?.id)
|
||||
|
||||
// 滚动页面后,目标元素与页面边界至少保留的边距
|
||||
const SCROLL_MARGIN = 15
|
||||
|
||||
export const scrollToNode = (element) => {
|
||||
if (element) {
|
||||
const container = getDocument().documentElement
|
||||
const { clientWidth, clientHeight } = container
|
||||
const { left, right, top, bottom, width, height } = element.getBoundingClientRect()
|
||||
const option = {}
|
||||
|
||||
if (right < 0) {
|
||||
option.left = container.scrollLeft + left - SCROLL_MARGIN
|
||||
} else if (left > clientWidth) {
|
||||
option.left = container.scrollLeft + left - clientWidth + width + SCROLL_MARGIN
|
||||
}
|
||||
|
||||
if (bottom < 0) {
|
||||
option.top = container.scrollTop + top - SCROLL_MARGIN
|
||||
} else if (top > clientHeight) {
|
||||
option.top = container.scrollTop + top - clientHeight + height + SCROLL_MARGIN
|
||||
}
|
||||
|
||||
if (typeof option.left === 'number' || typeof option.top === 'number') {
|
||||
container.scrollTo(option)
|
||||
}
|
||||
}
|
||||
|
||||
return nextTick()
|
||||
}
|
||||
const setSelectRect = (element) => {
|
||||
element = element || getDocument().body
|
||||
|
||||
const { left, height, top, width } = getRect(element)
|
||||
const componentName = getCurrent().schema?.componentName || ''
|
||||
clearHover()
|
||||
Object.assign(selectState, {
|
||||
width,
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
componentName,
|
||||
doc: getDocument()
|
||||
})
|
||||
}
|
||||
|
||||
export const updateRect = (id) => {
|
||||
id = (typeof id === 'string' && id) || getCurrent().schema?.id
|
||||
clearHover()
|
||||
|
||||
if (id) {
|
||||
setTimeout(() => setSelectRect(querySelectById(id)))
|
||||
} else {
|
||||
switch (position) {
|
||||
case POSITION.TOP:
|
||||
case POSITION.LEFT:
|
||||
insertBefore(node)
|
||||
break
|
||||
case POSITION.BOTTOM:
|
||||
case POSITION.RIGHT:
|
||||
inserAfter(node)
|
||||
break
|
||||
case POSITION.IN:
|
||||
insertInner(node)
|
||||
break
|
||||
default:
|
||||
insertInner(node)
|
||||
break
|
||||
// 如果选中的是body,不清除选中框
|
||||
if (!selectState.componentName && selectState.width > 0) {
|
||||
return
|
||||
}
|
||||
clearSelect()
|
||||
}
|
||||
}
|
||||
|
||||
export const getConfigure = (targetName) => {
|
||||
const material = getController().getMaterial(targetName)
|
||||
|
||||
// 这里如果是区块插槽,则返回标识为容器的对象
|
||||
if (targetName === 'Template') {
|
||||
return {
|
||||
isContainer: true
|
||||
}
|
||||
}
|
||||
|
||||
select && setTimeout(() => selectNode(node.data.id))
|
||||
|
||||
getController().addHistory()
|
||||
return material?.content?.configure || material.configure || {}
|
||||
}
|
||||
|
||||
export const addComponent = (data, position) => {
|
||||
const { schema, parent } = getCurrent()
|
||||
/**
|
||||
* 是否允许插入
|
||||
* @param {*} configure 当前放置目标的 configure,比如getConfigure(componentName)
|
||||
* @param {*} data 当前插入目标的schame数据
|
||||
* @returns
|
||||
*/
|
||||
export const allowInsert = (configure = hoverState.configure || {}, data = dragState.data || {}) => {
|
||||
const { nestingRule = {} } = configure
|
||||
const { childWhitelist = [], descendantBlacklist = [] } = nestingRule
|
||||
|
||||
insertNode({ node: schema, parent, data }, position)
|
||||
}
|
||||
|
||||
export const copyNode = (id) => {
|
||||
if (!id) {
|
||||
return
|
||||
// 要插入的父节点必须是容器
|
||||
if (!configure.isContainer) {
|
||||
return false
|
||||
}
|
||||
const { node, parent } = getNode(id, true)
|
||||
|
||||
inserAfter({ parent, node, data: copyObject(node) })
|
||||
getController().addHistory()
|
||||
let flag = true
|
||||
// 白名单
|
||||
flag = childWhitelist.length ? childWhitelist.includes(data?.componentName) : true
|
||||
|
||||
// 黑名单
|
||||
if (descendantBlacklist.length) {
|
||||
flag = !descendantBlacklist.includes(data?.componentName)
|
||||
}
|
||||
|
||||
return flag
|
||||
}
|
||||
|
||||
export const onMouseUp = ({ target }) => {
|
||||
const { draging, data } = dragState
|
||||
const { position } = lineState
|
||||
const absolute = canvasState.type === 'absolute'
|
||||
const sourceId = data?.id
|
||||
const lineId = lineState.id
|
||||
const allowInsert = position !== POSITION.FORBID
|
||||
const isAncestor = (ancestor, descendant) => {
|
||||
const ancestorId = typeof ancestor === 'string' ? ancestor : ancestor.id
|
||||
let descendantId = typeof descendant === 'string' ? descendant : descendant.id
|
||||
|
||||
if (draging && allowInsert) {
|
||||
const { parent, node } = getNode(lineId, true) || {} // target
|
||||
const targetNode = { parent, node, data: toRaw(data) }
|
||||
while (descendantId) {
|
||||
const { parent } = getNode(descendantId, true) || {}
|
||||
|
||||
if (sourceId) {
|
||||
// 内部拖拽
|
||||
if (sourceId !== lineId && !absolute) {
|
||||
removeNode(getNode(sourceId, true))
|
||||
insertNode(targetNode, position)
|
||||
if (parent.id === ancestorId) {
|
||||
return true
|
||||
}
|
||||
|
||||
descendantId = parent.id
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 获取位置信息,返回状态
|
||||
const lineAbs = 20
|
||||
const getPosLine = (rect, configure) => {
|
||||
const mousePos = dragState.mouse
|
||||
const yAbs = Math.min(lineAbs, rect.height / 3)
|
||||
const xAbs = Math.min(lineAbs, rect.width / 3)
|
||||
let type
|
||||
let forbidden = false
|
||||
|
||||
if (mousePos.y < rect.top + yAbs) {
|
||||
type = POSITION.TOP
|
||||
} else if (mousePos.y > rect.bottom - yAbs) {
|
||||
type = POSITION.BOTTOM
|
||||
} else if (mousePos.x < rect.left + xAbs) {
|
||||
type = POSITION.LEFT
|
||||
} else if (mousePos.x > rect.right - xAbs) {
|
||||
type = POSITION.RIGHT
|
||||
} else if (configure.isContainer) {
|
||||
type = POSITION.IN
|
||||
if (!allowInsert()) {
|
||||
forbidden = true
|
||||
}
|
||||
} else {
|
||||
type = POSITION.BOTTOM
|
||||
}
|
||||
|
||||
// 如果被拖拽的节点不是新增的,并且是放置的节点的祖先节点,则禁止插入
|
||||
const draggedId = dragState.data?.id
|
||||
if (draggedId && isAncestor(draggedId, lineState.id)) {
|
||||
forbidden = true
|
||||
}
|
||||
|
||||
return { type, forbidden }
|
||||
}
|
||||
|
||||
const isBodyEl = (element) => element.nodeName === 'BODY'
|
||||
|
||||
const setHoverRect = (element, data) => {
|
||||
if (!element) {
|
||||
return clearHover()
|
||||
}
|
||||
const componentName = element.getAttribute(NODE_TAG)
|
||||
const id = element.getAttribute(NODE_UID)
|
||||
const configure = getConfigure(componentName)
|
||||
const rect = getRect(element)
|
||||
const { left, height, top, width } = rect
|
||||
|
||||
hoverState.configure = configure
|
||||
|
||||
if (data) {
|
||||
let childEle = null
|
||||
lineState.id = id
|
||||
lineState.configure = configure
|
||||
const rectType = isBodyEl(element) ? POSITION.IN : getPosLine(rect, configure).type
|
||||
|
||||
// 如果拖拽经过的元素是body或者是带有容器属性的盒子,并且在元素内部插入,则需要特殊处理
|
||||
if ((isBodyEl(element) || configure?.isContainer) && rectType === POSITION.IN) {
|
||||
const { node } = isBodyEl(element) ? { node: getSchema() } : getNode(id, true) || {}
|
||||
const children = node?.children || []
|
||||
if (children.length > 0) {
|
||||
// 如果容器盒子有子节点,则以最后一个子节点为拖拽参照物
|
||||
const lastNode = children[children.length - 1]
|
||||
childEle = querySelectById(lastNode.id)
|
||||
const childComponentName = element.getAttribute(childEle)
|
||||
const Childconfigure = getConfigure(childComponentName)
|
||||
lineState.id = lastNode.id
|
||||
lineState.configure = Childconfigure
|
||||
}
|
||||
}
|
||||
|
||||
// 如果容器盒子有子元素
|
||||
if (childEle) {
|
||||
const childRect = getRect(childEle)
|
||||
const { left, height, top, width } = childRect
|
||||
const posLine = getPosLine(childRect, lineState.configure)
|
||||
Object.assign(lineState, {
|
||||
width,
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
position: canvasState.type === 'absolute' || posLine.type,
|
||||
forbidden: posLine.forbidden
|
||||
})
|
||||
} else {
|
||||
// 从外部拖拽进来的无ID,insert
|
||||
if (absolute) {
|
||||
targetNode.node = getSchema()
|
||||
data.props = data.props || {}
|
||||
data.props.style = {
|
||||
position: 'absolute',
|
||||
top: dragState.mouse.y + 'px',
|
||||
left: dragState.mouse.x + 'px'
|
||||
}
|
||||
}
|
||||
|
||||
insertNode(targetNode, position)
|
||||
}
|
||||
}
|
||||
|
||||
// 重置拖拽状态
|
||||
dragEnd()
|
||||
}
|
||||
|
||||
const smoothScroll = {
|
||||
timmer: null,
|
||||
/**
|
||||
*
|
||||
* @param {*} up 方向
|
||||
* @param {*} step 每次滚动距离
|
||||
* @param {*} time 滚动延时(不得大于系统滚动时长,否则可能出现卡顿效果)
|
||||
*/
|
||||
start(up, step = 40, time = 100) {
|
||||
const dom = getDocument().documentElement
|
||||
const fn = () => {
|
||||
const top = up ? dom.scrollTop + step : dom.scrollTop - step
|
||||
|
||||
dom.scrollTo({ top, behavior: 'smooth' })
|
||||
this.timmer = setTimeout(fn, time)
|
||||
const posLine = getPosLine(rect, configure)
|
||||
Object.assign(lineState, {
|
||||
width,
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
position: canvasState.type === 'absolute' || posLine.type,
|
||||
forbidden: posLine.forbidden
|
||||
})
|
||||
}
|
||||
|
||||
this.timmer || fn()
|
||||
},
|
||||
stop() {
|
||||
clearTimeout(this.timmer)
|
||||
this.timmer = null
|
||||
useLayout().closePlugin()
|
||||
}
|
||||
|
||||
// 设置元素hover状态
|
||||
Object.assign(hoverState, {
|
||||
width,
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
componentName
|
||||
})
|
||||
return undefined
|
||||
}
|
||||
|
||||
// 绝对布局
|
||||
|
|
@ -402,43 +622,6 @@ export const dragMove = (event, isHover) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const clearHover = () => {
|
||||
Object.assign(hoverState, initialRectState, { slot: null })
|
||||
}
|
||||
|
||||
export const clearSelect = () => {
|
||||
canvasState.current = null
|
||||
canvasState.parent = null
|
||||
Object.assign(selectState, initialRectState)
|
||||
// 临时借用 remote 事件出发 currentSchema 更新
|
||||
canvasState?.emit?.('remove')
|
||||
}
|
||||
|
||||
export const querySelectById = (id, type = '') => {
|
||||
let selector = `[${NODE_UID}="${id}"]`
|
||||
const doc = canvasState.iframe.contentDocument
|
||||
let element = doc.querySelector(selector)
|
||||
const loopId = element?.getAttribute('loop-id')
|
||||
if (element && loopId) {
|
||||
const currentLoopId = getCurrent().loopId
|
||||
selector = `[${NODE_UID}="${id}"][${NODE_LOOP}="${currentLoopId}"]`
|
||||
element = doc.querySelector(selector)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
||||
export const getCurrentElement = () => querySelectById(getCurrent().schema?.id)
|
||||
|
||||
export const updateRect = (id) => {
|
||||
id = (typeof id === 'string' && id) || getCurrent().schema?.id
|
||||
clearHover()
|
||||
|
||||
if (id) {
|
||||
setTimeout(() => setSelectRect(querySelectById(id)))
|
||||
} else {
|
||||
clearSelect()
|
||||
}
|
||||
}
|
||||
// type == clickTree, 为点击大纲; type == loop-id=xxx ,为点击循环数据
|
||||
export const selectNode = async (id, type) => {
|
||||
if (type && type.indexOf('loop-id') > -1) {
|
||||
|
|
@ -468,174 +651,84 @@ export const hoverNode = (id, data) => {
|
|||
element && setHoverRect(element, data)
|
||||
}
|
||||
|
||||
export const scrollToNode = (element) => {
|
||||
if (element) {
|
||||
const container = getDocument().documentElement
|
||||
const h = container?.clientHeight
|
||||
const { y, height } = element.getBoundingClientRect()
|
||||
|
||||
if (y < 0) {
|
||||
container.scrollTo({ top: container.scrollTop + y - 15 })
|
||||
} else if (y > h) {
|
||||
container.scrollTo({ top: y + height - h + 15 })
|
||||
}
|
||||
}
|
||||
|
||||
return nextTick()
|
||||
}
|
||||
const setSelectRect = (element) => {
|
||||
element = element || getDocument().body
|
||||
|
||||
const { left, height, top, width } = element.getBoundingClientRect()
|
||||
const { x, y } = getOffset(element)
|
||||
const componentName = getCurrent().schema?.componentName || ''
|
||||
const scale = useLayout().getScale()
|
||||
clearHover()
|
||||
Object.assign(selectState, {
|
||||
width: width * scale,
|
||||
height: height * scale,
|
||||
top: top * scale + y,
|
||||
left: left * scale + x,
|
||||
componentName
|
||||
})
|
||||
}
|
||||
|
||||
const isBodyEl = (element) => element.nodeName === 'BODY'
|
||||
|
||||
const setHoverRect = (element, data) => {
|
||||
if (!element) {
|
||||
return clearHover()
|
||||
}
|
||||
const componentName = element.getAttribute(NODE_TAG)
|
||||
const id = element.getAttribute(NODE_UID)
|
||||
const configure = getConfigure(componentName)
|
||||
const rect = element.getBoundingClientRect()
|
||||
const { left, height, top, width } = rect
|
||||
const { x, y } = getOffset(element)
|
||||
const scale = useLayout().getScale()
|
||||
|
||||
hoverState.configure = configure
|
||||
|
||||
if (data) {
|
||||
let childEle = null
|
||||
lineState.id = id
|
||||
lineState.configure = configure
|
||||
const rectType = isBodyEl(element) ? POSITION.IN : getPosLine(rect, configure).type
|
||||
|
||||
// 如果拖拽经过的元素是body或者是带有容器属性的盒子,并且在元素内部插入,则需要特殊处理
|
||||
if ((isBodyEl(element) || configure?.isContainer) && rectType === POSITION.IN) {
|
||||
const { node } = isBodyEl(element) ? { node: getSchema() } : getNode(id, true) || {}
|
||||
const children = node?.children || []
|
||||
if (children.length > 0) {
|
||||
// 如果容器盒子有子节点,则以最后一个子节点为拖拽参照物
|
||||
const lastNode = children[children.length - 1]
|
||||
childEle = querySelectById(lastNode.id)
|
||||
const childComponentName = element.getAttribute(childEle)
|
||||
const Childconfigure = getConfigure(childComponentName)
|
||||
lineState.id = lastNode.id
|
||||
lineState.configure = Childconfigure
|
||||
}
|
||||
}
|
||||
|
||||
// 如果容器盒子有子元素
|
||||
if (childEle) {
|
||||
const childRect = childEle.getBoundingClientRect()
|
||||
const { left, height, top, width } = childRect
|
||||
const { x, y } = getOffset(childEle)
|
||||
Object.assign(lineState, {
|
||||
width: width * scale,
|
||||
height: height * scale,
|
||||
top: top * scale + y,
|
||||
left: left * scale + x,
|
||||
position: canvasState.type === 'absolute' || getPosLine(childRect, lineState.configure).type
|
||||
})
|
||||
} else {
|
||||
Object.assign(lineState, {
|
||||
width: width * scale,
|
||||
height: height * scale,
|
||||
top: top * scale + y,
|
||||
left: left * scale + x,
|
||||
position: canvasState.type === 'absolute' || getPosLine(rect, configure).type
|
||||
})
|
||||
}
|
||||
|
||||
useLayout().closePlugin()
|
||||
}
|
||||
|
||||
// 设置元素hover状态
|
||||
Object.assign(hoverState, {
|
||||
width: width * scale,
|
||||
height: height * scale,
|
||||
top: top * scale + y,
|
||||
left: left * scale + x,
|
||||
componentName
|
||||
})
|
||||
return undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否允许插入
|
||||
* @param {*} configure 当前放置目标的 configure,比如getConfigure(componentName)
|
||||
* @param {*} data 当前插入目标的schame数据
|
||||
* @returns
|
||||
*/
|
||||
export const allowInsert = (configure = hoverState.configure || {}, data = dragState.data || {}) => {
|
||||
const { nestingRule = {} } = configure
|
||||
const { childWhitelist = [], descendantBlacklist = [] } = nestingRule
|
||||
|
||||
// 要插入的父节点必须是容器
|
||||
if (!configure.isContainer) {
|
||||
return false
|
||||
}
|
||||
|
||||
let flag = true
|
||||
// 白名单
|
||||
flag = childWhitelist.length ? childWhitelist.includes(data?.componentName) : true
|
||||
|
||||
// 黑名单
|
||||
if (descendantBlacklist.length) {
|
||||
flag = !descendantBlacklist.includes(data?.componentName)
|
||||
}
|
||||
|
||||
return flag
|
||||
}
|
||||
|
||||
export const getConfigure = (targetName) => {
|
||||
const material = getController().getMaterial(targetName)
|
||||
|
||||
// 这里如果是区块插槽,则返回标识为容器的对象
|
||||
if (targetName === 'Template') {
|
||||
return {
|
||||
isContainer: true
|
||||
}
|
||||
}
|
||||
|
||||
return material?.content?.configure || material.configure || {}
|
||||
}
|
||||
|
||||
// 获取位置信息,返回状态
|
||||
const lineAbs = 20
|
||||
const getPosLine = (rect, configure) => {
|
||||
const mousePos = dragState.mouse
|
||||
const yAbs = Math.min(lineAbs, rect.height / 3)
|
||||
const xAbs = Math.min(lineAbs, rect.width / 3)
|
||||
let type
|
||||
|
||||
if (mousePos.y < rect.top + yAbs) {
|
||||
type = POSITION.TOP
|
||||
} else if (mousePos.y > rect.bottom - yAbs) {
|
||||
type = POSITION.BOTTOM
|
||||
} else if (mousePos.x < rect.left + xAbs) {
|
||||
type = POSITION.LEFT
|
||||
} else if (mousePos.x > rect.right - xAbs) {
|
||||
type = POSITION.RIGHT
|
||||
} else if (configure.isContainer) {
|
||||
type = allowInsert() ? POSITION.IN : POSITION.FORBID
|
||||
export const insertNode = (node, position = POSITION.IN, select = true) => {
|
||||
if (!node.parent) {
|
||||
insertInner({ node: canvasState.schema, data: node.data }, position)
|
||||
} else {
|
||||
type = POSITION.BOTTOM
|
||||
switch (position) {
|
||||
case POSITION.TOP:
|
||||
case POSITION.LEFT:
|
||||
insertBefore(node)
|
||||
break
|
||||
case POSITION.BOTTOM:
|
||||
case POSITION.RIGHT:
|
||||
inserAfter(node)
|
||||
break
|
||||
case POSITION.IN:
|
||||
insertInner(node)
|
||||
break
|
||||
default:
|
||||
insertInner(node)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return { type }
|
||||
select && setTimeout(() => selectNode(node.data.id))
|
||||
|
||||
getController().addHistory()
|
||||
}
|
||||
|
||||
export const addComponent = (data, position) => {
|
||||
const { schema, parent } = getCurrent()
|
||||
|
||||
insertNode({ node: schema, parent, data }, position)
|
||||
}
|
||||
|
||||
export const copyNode = (id) => {
|
||||
if (!id) {
|
||||
return
|
||||
}
|
||||
const { node, parent } = getNode(id, true)
|
||||
|
||||
inserAfter({ parent, node, data: copyObject(node) })
|
||||
getController().addHistory()
|
||||
}
|
||||
|
||||
export const onMouseUp = () => {
|
||||
const { draging, data } = dragState
|
||||
const { position, forbidden } = lineState
|
||||
const absolute = canvasState.type === 'absolute'
|
||||
const sourceId = data?.id
|
||||
const lineId = lineState.id
|
||||
|
||||
if (draging && !forbidden) {
|
||||
const { parent, node } = getNode(lineId, true) || {} // target
|
||||
const targetNode = { parent, node, data: toRaw(data) }
|
||||
|
||||
if (sourceId) {
|
||||
// 内部拖拽
|
||||
if (sourceId !== lineId && !absolute) {
|
||||
removeNode(getNode(sourceId, true))
|
||||
insertNode(targetNode, position)
|
||||
}
|
||||
} else {
|
||||
// 从外部拖拽进来的无ID,insert
|
||||
if (absolute) {
|
||||
targetNode.node = getSchema()
|
||||
data.props = data.props || {}
|
||||
data.props.style = {
|
||||
position: 'absolute',
|
||||
top: dragState.mouse.y + 'px',
|
||||
left: dragState.mouse.x + 'px'
|
||||
}
|
||||
}
|
||||
|
||||
insertNode(targetNode, position)
|
||||
}
|
||||
}
|
||||
|
||||
// 重置拖拽状态
|
||||
dragEnd()
|
||||
}
|
||||
|
||||
export const setPageCss = (css = '') => {
|
||||
|
|
@ -701,26 +794,6 @@ export const setGlobalState = (state) => {
|
|||
getRenderer().setGlobalState(state)
|
||||
}
|
||||
|
||||
export const getGlobalState = () => getRenderer().getGlobalState()
|
||||
|
||||
export const getRenderer = () => canvasState.renderer
|
||||
|
||||
export const getController = () => canvasState.controller
|
||||
|
||||
export const getNode = (id, parent) => getRenderer()?.getNode(id, parent)
|
||||
|
||||
export const getDocument = () => canvasState.iframe.contentDocument
|
||||
|
||||
export const getWindow = () => canvasState.iframe.contentWindow
|
||||
|
||||
export const getCurrent = () => {
|
||||
return {
|
||||
schema: canvasState.current,
|
||||
parent: canvasState.parent,
|
||||
loopId: canvasState.loopId
|
||||
}
|
||||
}
|
||||
|
||||
export const getNodePath = (id, nodes = []) => {
|
||||
const { parent, node } = getNode(id, true) || {}
|
||||
|
||||
|
|
@ -743,8 +816,6 @@ export const setSchema = async (schema) => {
|
|||
return canvasState.schema
|
||||
}
|
||||
|
||||
export const getSchema = () => getRenderer()?.getSchema()
|
||||
|
||||
export const setConfigure = (configure) => {
|
||||
getRenderer().setConfigure(configure)
|
||||
}
|
||||
|
|
@ -777,6 +848,49 @@ export const canvasDispatch = (name, data, doc = getDocument()) => {
|
|||
doc.dispatchEvent(new CustomEvent(name, data))
|
||||
}
|
||||
|
||||
export const canvasApi = {
|
||||
dragStart,
|
||||
updateRect,
|
||||
getContext,
|
||||
getNodePath,
|
||||
dragMove,
|
||||
setLocales,
|
||||
setState,
|
||||
deleteState,
|
||||
getRenderer,
|
||||
clearSelect,
|
||||
selectNode,
|
||||
hoverNode,
|
||||
insertNode,
|
||||
removeNode,
|
||||
addComponent,
|
||||
setPageCss,
|
||||
addScript,
|
||||
addStyle,
|
||||
getNode,
|
||||
getCurrent,
|
||||
setSchema,
|
||||
setUtils,
|
||||
updateUtils,
|
||||
deleteUtils,
|
||||
getSchema,
|
||||
setI18n,
|
||||
getCanvasType,
|
||||
setCanvasType,
|
||||
setProps,
|
||||
setGlobalState,
|
||||
getGlobalState,
|
||||
getDocument,
|
||||
canvasDispatch,
|
||||
Builtin,
|
||||
setDataSourceMap: (...args) => {
|
||||
return canvasState.renderer.setDataSourceMap(...args)
|
||||
},
|
||||
getDataSourceMap: (...args) => {
|
||||
return canvasState.renderer.getDataSourceMap(...args)
|
||||
}
|
||||
}
|
||||
|
||||
export const initCanvas = ({ renderer, iframe, emit, controller }) => {
|
||||
const currentSchema = getSchema()
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
<icon-close class="icon-close" @click="closePanel"></icon-close>
|
||||
</span>
|
||||
</div>
|
||||
<config-group :group="propertiesList" :index="0">
|
||||
<ConfigGroup :group="propertiesList" :index="0">
|
||||
<template #item="{ data, propIndex }">
|
||||
<config-item
|
||||
<ConfigItem
|
||||
:key="propIndex"
|
||||
:property="data"
|
||||
:data-prop-index="propIndex"
|
||||
|
|
@ -22,22 +22,19 @@
|
|||
<template v-if="!data.noBinding" #suffix>
|
||||
<slot name="suffix" :data="data"></slot>
|
||||
</template>
|
||||
</config-item>
|
||||
</ConfigItem>
|
||||
</template>
|
||||
</config-group>
|
||||
</ConfigGroup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, ref } from 'vue'
|
||||
import { useResource, useProperties, useCanvas, useProperty } from '@opentiny/tiny-engine-controller'
|
||||
import { ConfigGroup, ConfigItem } from '@opentiny/tiny-engine-common'
|
||||
import { iconSetting, iconClose } from '@opentiny/vue-icon'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ConfigGroup,
|
||||
ConfigItem,
|
||||
IconSetting: iconSetting(),
|
||||
IconClose: iconClose()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -376,6 +376,13 @@ export default {
|
|||
)
|
||||
},
|
||||
render() {
|
||||
// 渲染画布增加根节点,与出码和预览保持一致
|
||||
const rootChildrenSchema = {
|
||||
componentName: 'div',
|
||||
props: schema.props,
|
||||
children: schema.children
|
||||
}
|
||||
|
||||
return h(
|
||||
'tiny-i18n-host',
|
||||
{
|
||||
|
|
@ -384,9 +391,7 @@ export default {
|
|||
ref: 'page',
|
||||
className: 'design-page'
|
||||
},
|
||||
schema.children?.length
|
||||
? schema.children.map((child) => h(renderer, { schema: child, parent: schema }))
|
||||
: [h(CanvasEmpty)]
|
||||
schema.children?.length ? h(renderer, { schema: rootChildrenSchema, parent: schema }) : [h(CanvasEmpty)]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -419,5 +424,3 @@ export const api = {
|
|||
setDataSourceMap,
|
||||
setGlobalState
|
||||
}
|
||||
|
||||
window.api = api
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ const { BROADCAST_CHANNEL } = constants
|
|||
const { hyphenateRE } = utils
|
||||
const customElements = {}
|
||||
|
||||
const transformJSX = (code) =>
|
||||
transformSync(code, {
|
||||
const transformJSX = (code) => {
|
||||
const res = transformSync(code, {
|
||||
plugins: [
|
||||
[
|
||||
babelPluginJSX,
|
||||
|
|
@ -46,6 +46,13 @@ const transformJSX = (code) =>
|
|||
]
|
||||
]
|
||||
})
|
||||
return (res.code || '')
|
||||
.replace(/import \{.+\} from "vue";/, '')
|
||||
.replace(/h\(_?resolveComponent\((.*?)\)/g, `h(this.getComponent($1)`)
|
||||
.replace(/_?resolveComponent/g, 'h')
|
||||
.replace(/_?createTextVNode\((.*?)\)/g, '$1')
|
||||
.trim()
|
||||
}
|
||||
|
||||
export const blockSlotDataMap = reactive({})
|
||||
|
||||
|
|
@ -138,7 +145,7 @@ export const newFn = (...argv) => {
|
|||
return new Fn(...argv)
|
||||
}
|
||||
|
||||
const parseExpression = (data, scope, ctx) => {
|
||||
const parseExpression = (data, scope, ctx, isJsx = false) => {
|
||||
try {
|
||||
if (data.value.indexOf('this.i18n') > -1) {
|
||||
ctx.i18n = i18nHost.global.t
|
||||
|
|
@ -146,12 +153,17 @@ const parseExpression = (data, scope, ctx) => {
|
|||
ctx.t = i18nHost.global.t
|
||||
}
|
||||
|
||||
return newFn('$scope', `with($scope || {}) { return ${data.value} }`).call(ctx, {
|
||||
const expression = isJsx ? transformJSX(data.value) : data.value
|
||||
return newFn('$scope', `with($scope || {}) { return ${expression} }`).call(ctx, {
|
||||
...ctx,
|
||||
...scope,
|
||||
slotScope: scope
|
||||
})
|
||||
} catch (err) {
|
||||
// 解析抛出异常,则再尝试解析 JSX 语法。如果解析 JSX 语法仍然出现错误,isJsx 变量会确保不会再次递归执行解析
|
||||
if (!isJsx) {
|
||||
return parseExpression(data, scope, ctx, true)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
|
@ -347,10 +359,6 @@ export const getComponent = (name) => {
|
|||
const parseJSXFunction = (data, ctx) => {
|
||||
try {
|
||||
const newValue = transformJSX(data.value)
|
||||
.code.replace(/import \{.+\} from "vue";/, '')
|
||||
.replace(/h\(_?resolveComponent\((.*?)\)/g, `h(this.getComponent($1)`)
|
||||
.replace(/_?resolveComponent/g, 'h')
|
||||
.replace(/_?createTextVNode\((.*?)\)/g, '$1')
|
||||
const fnInfo = parseFunctionString(newValue)
|
||||
if (!fnInfo) throw Error('函数解析失败,请检查格式。示例:function fnName() { }')
|
||||
|
||||
|
|
@ -590,6 +598,20 @@ const getLoopScope = ({ scope, index, item, loopArgs }) => {
|
|||
}
|
||||
}
|
||||
|
||||
const injectPlaceHolder = (componentName, children) => {
|
||||
const isEmptyArr = Array.isArray(children) && !children.length
|
||||
|
||||
if (configure[componentName]?.isContainer && (!children || isEmptyArr)) {
|
||||
return [
|
||||
{
|
||||
componentName: 'CanvasPlaceholder'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return children
|
||||
}
|
||||
|
||||
const renderGroup = (children, scope, parent) => {
|
||||
return children.map?.((schema) => {
|
||||
const { componentName, children, loop, loopArgs, condition, id } = schema
|
||||
|
|
@ -609,10 +631,14 @@ const renderGroup = (children, scope, parent) => {
|
|||
return null
|
||||
}
|
||||
|
||||
const renderChildren = injectPlaceHolder(componentName, children)
|
||||
|
||||
return h(
|
||||
getComponent(componentName),
|
||||
getBindProps(schema, mergeScope),
|
||||
Array.isArray(children) ? renderSlot(children, mergeScope, schema) : parseData(children, mergeScope)
|
||||
Array.isArray(renderChildren)
|
||||
? renderSlot(renderChildren, mergeScope, schema)
|
||||
: parseData(renderChildren, mergeScope)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -620,20 +646,11 @@ const renderGroup = (children, scope, parent) => {
|
|||
})
|
||||
}
|
||||
|
||||
const ContainerComponent = ['CanvasCol', 'CanvasRow', 'CanvasRowColContainer']
|
||||
|
||||
const getChildren = (schema, mergeScope) => {
|
||||
const { componentName, children } = schema
|
||||
let renderChildren = children
|
||||
|
||||
if (ContainerComponent.includes(componentName) && !renderChildren?.length) {
|
||||
renderChildren = [
|
||||
{
|
||||
componentName: 'CanvasPlaceholder'
|
||||
}
|
||||
]
|
||||
}
|
||||
const renderChildren = injectPlaceHolder(componentName, children)
|
||||
|
||||
const component = getComponent(componentName)
|
||||
const isNative = typeof component === 'string'
|
||||
const isCustomElm = customElements[componentName]
|
||||
const isGroup = checkGroup(componentName)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
import * as Vue from 'vue'
|
||||
import * as VueI18n from 'vue-i18n'
|
||||
import { addScript, addStyle, dynamicImportComponents, updateDependencies } from '../common'
|
||||
import TinyI18nHost, { I18nInjectionKey } from '@opentiny/tiny-engine-common/js/i18n'
|
||||
import TinyI18nHost, { I18nInjectionKey } from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
import * as TinyWebcomponentCore from '@opentiny/tiny-engine-webcomponent-core'
|
||||
import TinyVue from '@opentiny/vue'
|
||||
import * as TinyVueIcon from '@opentiny/vue-icon'
|
||||
|
|
@ -26,73 +26,77 @@ const dispatch = (name, data) => {
|
|||
window.parent.document.dispatchEvent(new CustomEvent(name, data))
|
||||
}
|
||||
|
||||
dispatch('beforeCanvasReady')
|
||||
const initRenderContext = () => {
|
||||
dispatch('beforeCanvasReady')
|
||||
|
||||
TinyI18nHost.lowcode = lowcode
|
||||
TinyI18nHost.lowcode = lowcode
|
||||
|
||||
// 目前先兼容老区块发布的代码,后期区块发布整改后再删除
|
||||
window.React = {}
|
||||
window.React.createElement = Vue.h
|
||||
// 目前先兼容老区块发布的代码,后期区块发布整改后再删除
|
||||
window.React = {}
|
||||
window.React.createElement = Vue.h
|
||||
|
||||
// 不能采用new Proxy代理Vue的方案,在编译后的vue会报错警告,采用一下方案扩展用于注入一些区块加载逻辑
|
||||
window.Vue = {
|
||||
...Vue,
|
||||
resolveComponent(...args) {
|
||||
// 此处先执行vue内部的解析组件的方法,如果可以拿到组件对象则直接返回,反之则去注册区块
|
||||
const component = Vue.resolveComponent(args[0])
|
||||
if (component && typeof component === 'string') {
|
||||
return getComponent(capitalize(camelize(args[0])))
|
||||
} else {
|
||||
return component
|
||||
}
|
||||
},
|
||||
// renderSlot方法第三个参数是作用域插槽传递的数据,格式{ data: vue.unref(state).componentData }
|
||||
renderSlot(...args) {
|
||||
// 获取当前vue的实例
|
||||
const instance = Vue.getCurrentInstance()
|
||||
|
||||
// 获取当前区块名称
|
||||
const blockName = instance.attrs.dataTag
|
||||
|
||||
const [, slotName, slotData] = args
|
||||
|
||||
// 如果是作用域插槽,则获取作用域插槽传递过来的参数
|
||||
if (slotData) {
|
||||
if (blockSlotDataMap[blockName]) {
|
||||
blockSlotDataMap[blockName][slotName] = slotData
|
||||
// 不能采用new Proxy代理Vue的方案,在编译后的vue会报错警告,采用一下方案扩展用于注入一些区块加载逻辑
|
||||
window.Vue = {
|
||||
...Vue,
|
||||
resolveComponent(...args) {
|
||||
// 此处先执行vue内部的解析组件的方法,如果可以拿到组件对象则直接返回,反之则去注册区块
|
||||
const component = Vue.resolveComponent(args[0])
|
||||
if (component && typeof component === 'string') {
|
||||
return getComponent(capitalize(camelize(args[0])))
|
||||
} else {
|
||||
blockSlotDataMap[blockName] = { [slotName]: slotData }
|
||||
return component
|
||||
}
|
||||
}
|
||||
},
|
||||
// renderSlot方法第三个参数是作用域插槽传递的数据,格式{ data: vue.unref(state).componentData }
|
||||
renderSlot(...args) {
|
||||
// 获取当前vue的实例
|
||||
const instance = Vue.getCurrentInstance()
|
||||
|
||||
/**
|
||||
* vue源码中的renderSlot会忽略default插槽的名称,所以这里必须手动添加args第三个参数的name值
|
||||
* vue源码如右所示:if (name !== 'default') props.name = name; return createVNode('slot', props, fallback && fallback());
|
||||
**/
|
||||
if (slotName === 'default') {
|
||||
args[2] = args[2] || {}
|
||||
args[2].name = slotName
|
||||
}
|
||||
// 获取当前区块名称
|
||||
const blockName = instance.attrs.dataTag
|
||||
|
||||
return Vue.renderSlot(...args)
|
||||
const [, slotName, slotData] = args
|
||||
|
||||
// 如果是作用域插槽,则获取作用域插槽传递过来的参数
|
||||
if (slotData) {
|
||||
if (blockSlotDataMap[blockName]) {
|
||||
blockSlotDataMap[blockName][slotName] = slotData
|
||||
} else {
|
||||
blockSlotDataMap[blockName] = { [slotName]: slotData }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* vue源码中的renderSlot会忽略default插槽的名称,所以这里必须手动添加args第三个参数的name值
|
||||
* vue源码如右所示:if (name !== 'default') props.name = name; return createVNode('slot', props, fallback && fallback());
|
||||
**/
|
||||
if (slotName === 'default') {
|
||||
args[2] = args[2] || {}
|
||||
args[2].name = slotName
|
||||
}
|
||||
|
||||
return Vue.renderSlot(...args)
|
||||
}
|
||||
}
|
||||
|
||||
window.VueI18n = VueI18n
|
||||
window.TinyVue = TinyVue
|
||||
window.TinyVueIcon = TinyVueIcon
|
||||
window.TinyWebcomponentCore = TinyWebcomponentCore
|
||||
window.TinyI18nHost = TinyI18nHost
|
||||
window.TinyLowcodeComponent = {}
|
||||
window.TinyComponentLibs = {}
|
||||
|
||||
Object.entries(TinyVue).forEach(([_key, component]) => {
|
||||
const { name } = component
|
||||
if (name) {
|
||||
window.TinyLowcodeComponent[name] = component
|
||||
}
|
||||
})
|
||||
|
||||
document.addEventListener('updateDependencies', updateDependencies)
|
||||
}
|
||||
|
||||
window.VueI18n = VueI18n
|
||||
window.TinyVue = TinyVue
|
||||
window.TinyVueIcon = TinyVueIcon
|
||||
window.TinyWebcomponentCore = TinyWebcomponentCore
|
||||
window.TinyI18nHost = TinyI18nHost
|
||||
window.TinyLowcodeComponent = {}
|
||||
window.TinyComponentLibs = {}
|
||||
|
||||
Object.entries(TinyVue).forEach(([_key, component]) => {
|
||||
const { name } = component
|
||||
if (name) {
|
||||
window.TinyLowcodeComponent[name] = component
|
||||
}
|
||||
})
|
||||
|
||||
let App = null
|
||||
|
||||
const renderer = {
|
||||
|
|
@ -129,6 +133,7 @@ const create = () => {
|
|||
}
|
||||
|
||||
export const createRender = (config) => {
|
||||
initRenderContext()
|
||||
const { dslMode, canvasOptions } = config
|
||||
const { styles = [], scripts = [] } = canvasOptions[dslMode]
|
||||
const { styles: thirdStyles = [], scripts: thirdScripts = [] } = window.thirdPartyDeps || {}
|
||||
|
|
@ -138,5 +143,3 @@ export const createRender = (config) => {
|
|||
...scripts.map((src) => addScript(src)).concat([...thirdStyles, ...styles].map((src) => addStyle(src)))
|
||||
]).finally(create)
|
||||
}
|
||||
|
||||
document.addEventListener('updateDependencies', updateDependencies)
|
||||
|
|
|
|||
|
|
@ -10,93 +10,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import CanvasContainer from './components/container/CanvasContainer.vue'
|
||||
import CanvasAction from './components/container/CanvasAction.vue'
|
||||
import CanvasDragItem from './components/container/CanvasDragItem.vue'
|
||||
import CanvasFooter from './components/container/CanvasFooter.vue'
|
||||
import CanvasResize from './components/container/CanvasResize.vue'
|
||||
import Builtin from './components/builtin/builtin.json'
|
||||
import RenderMain, { api as renderApi } from './components/render/RenderMain'
|
||||
import { createRender } from './components/render/runner'
|
||||
import {
|
||||
dragStart,
|
||||
updateRect,
|
||||
getContext,
|
||||
getNodePath,
|
||||
dragMove,
|
||||
setLocales,
|
||||
setState,
|
||||
deleteState,
|
||||
getRenderer,
|
||||
clearSelect,
|
||||
selectNode,
|
||||
hoverNode,
|
||||
insertNode,
|
||||
removeNode,
|
||||
addComponent,
|
||||
setPageCss,
|
||||
addScript,
|
||||
addStyle,
|
||||
getNode,
|
||||
getCurrent,
|
||||
setSchema,
|
||||
setUtils,
|
||||
updateUtils,
|
||||
deleteUtils,
|
||||
getSchema,
|
||||
setI18n,
|
||||
getCanvasType,
|
||||
setCanvasType,
|
||||
setProps,
|
||||
setGlobalState,
|
||||
getGlobalState,
|
||||
getDocument,
|
||||
canvasDispatch
|
||||
} from './components/container/container'
|
||||
|
||||
export {
|
||||
CanvasContainer,
|
||||
CanvasAction,
|
||||
CanvasFooter,
|
||||
CanvasDragItem,
|
||||
CanvasResize,
|
||||
RenderMain,
|
||||
renderApi,
|
||||
Builtin,
|
||||
dragStart,
|
||||
dragMove,
|
||||
updateRect,
|
||||
getContext,
|
||||
getNodePath,
|
||||
getNode,
|
||||
getCurrent,
|
||||
setSchema,
|
||||
setUtils,
|
||||
updateUtils,
|
||||
deleteUtils,
|
||||
getSchema,
|
||||
setLocales,
|
||||
setState,
|
||||
deleteState,
|
||||
setI18n,
|
||||
getRenderer,
|
||||
clearSelect,
|
||||
selectNode,
|
||||
insertNode,
|
||||
removeNode,
|
||||
hoverNode,
|
||||
addComponent,
|
||||
setPageCss,
|
||||
addScript,
|
||||
addStyle,
|
||||
getCanvasType,
|
||||
setCanvasType,
|
||||
setProps,
|
||||
setGlobalState,
|
||||
getGlobalState,
|
||||
getDocument,
|
||||
canvasDispatch,
|
||||
createRender
|
||||
}
|
||||
|
||||
export default CanvasContainer
|
||||
export { default as CanvasContainer } from './components/container/CanvasContainer.vue'
|
||||
export { default as CanvasDragItem } from './components/container/CanvasDragItem.vue'
|
||||
export { default as CanvasFooter } from './components/container/CanvasFooter.vue'
|
||||
export { createRender } from './components/render/runner'
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@ export default defineConfig({
|
|||
'@': path.resolve(__dirname, 'src')
|
||||
}
|
||||
},
|
||||
define: {
|
||||
'process.env': {}
|
||||
},
|
||||
plugins: [
|
||||
vue({
|
||||
template: {
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
:modal="false"
|
||||
:fullscreen="true"
|
||||
:append-to-body="true"
|
||||
title="Schema 本地与线上差异"
|
||||
title="Schema 线上与本地差异"
|
||||
>
|
||||
<vue-monaco
|
||||
v-if="state.compareVisible"
|
||||
|
|
@ -82,8 +82,8 @@ import {
|
|||
FormItem as TinyFormItem
|
||||
} from '@opentiny/vue'
|
||||
import { theme } from '@opentiny/tiny-engine-controller/adapter'
|
||||
import { useLayout } from '@opentiny/tiny-engine-controller'
|
||||
import { getSchema, setSchema } from '@opentiny/tiny-engine-canvas'
|
||||
import { useLayout, useNotify, useCanvas } from '@opentiny/tiny-engine-controller'
|
||||
import { constants } from '@opentiny/tiny-engine-utils'
|
||||
import VueMonaco from './VueMonaco.vue'
|
||||
|
||||
export default {
|
||||
|
|
@ -106,6 +106,7 @@ export default {
|
|||
},
|
||||
emits: ['update:visible'],
|
||||
setup(props, { emit, attrs }) {
|
||||
const { COMPONENT_NAME } = constants
|
||||
const formState = reactive({
|
||||
deployInfo: '',
|
||||
version: '',
|
||||
|
|
@ -186,9 +187,10 @@ export default {
|
|||
const remote = await api.getBlockById(block?.id)
|
||||
const originalObj = remote?.content || {}
|
||||
state.originalCode = JSON.stringify(originalObj, null, 2)
|
||||
const getSchema = useCanvas().canvasApi.value.getSchema
|
||||
|
||||
// 转为普通对象,和线上代码顺序保持一致
|
||||
const pageSchema = getSchema() || {}
|
||||
const pageSchema = getSchema?.() || {}
|
||||
if (pageSchema.componentName === 'Block') {
|
||||
state.code = JSON.stringify(pageSchema, null, 2)
|
||||
} else {
|
||||
|
|
@ -212,10 +214,21 @@ export default {
|
|||
}
|
||||
|
||||
const save = () => {
|
||||
const pageSchema = JSON.parse(state.newCode)
|
||||
setSchema(pageSchema)
|
||||
|
||||
close()
|
||||
if (!state.newCode) {
|
||||
close()
|
||||
return
|
||||
}
|
||||
try {
|
||||
const pageSchema = JSON.parse(state.newCode)
|
||||
const setSchema = useCanvas().canvasApi.value.setSchema
|
||||
setSchema?.({ ...pageSchema, componentName: COMPONENT_NAME.Block })
|
||||
close()
|
||||
} catch (err) {
|
||||
useNotify({
|
||||
type: 'error',
|
||||
message: '代码静态检查有错误,请先修改后再保存'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import { capitalize } from '@vue/shared'
|
|||
import { extend } from '@opentiny/vue-renderless/common/object'
|
||||
import { Input as TinyInput, Form as TinyForm, FormItem as TinyFormItem, Popover as TinyPopover } from '@opentiny/vue'
|
||||
import { useLayout, useModal, useCanvas, useBlock } from '@opentiny/tiny-engine-controller'
|
||||
import { getSchema, getCurrent } from '@opentiny/tiny-engine-canvas'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -38,7 +37,8 @@ export default {
|
|||
const { pageState } = useCanvas()
|
||||
const { addBlockEvent, removeEventLink, getCurrentBlock, appendEventEmit } = useBlock()
|
||||
const { PLUGIN_NAME, activePlugin } = useLayout()
|
||||
const { schema } = getSchema()
|
||||
|
||||
const { schema } = useCanvas().canvasApi.value?.getSchema?.() || {}
|
||||
const events = schema?.events || []
|
||||
const eventsList = Object.entries(events).map(([key, value]) => {
|
||||
return {
|
||||
|
|
@ -88,7 +88,7 @@ export default {
|
|||
|
||||
const {
|
||||
schema: { id, componentName }
|
||||
} = getCurrent()
|
||||
} = useCanvas().canvasApi.value?.getCurrent?.() || {}
|
||||
|
||||
const newEvent = extend(true, {}, data.metaEvent, {
|
||||
linked: {
|
||||
|
|
@ -117,7 +117,7 @@ export default {
|
|||
const editEvent = (item, data) => {
|
||||
const {
|
||||
schema: { id, componentName }
|
||||
} = getCurrent()
|
||||
} = useCanvas().canvasApi.value?.getCurrent?.() || {}
|
||||
|
||||
const oldEventName = data.linkedEventName
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import { reactive, computed } from 'vue'
|
|||
import { extend } from '@opentiny/vue-renderless/common/object'
|
||||
import { Input as TinyInput, Popover as TinyPopover } from '@opentiny/vue'
|
||||
import { useLayout, useModal, useCanvas, useBlock, useHistory } from '@opentiny/tiny-engine-controller'
|
||||
import { getSchema, getCurrent } from '@opentiny/tiny-engine-canvas'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -36,10 +35,10 @@ export default {
|
|||
},
|
||||
setup(props) {
|
||||
const { confirm } = useModal()
|
||||
const { pageState } = useCanvas()
|
||||
const { pageState, canvasApi } = useCanvas()
|
||||
const { addBlockProperty, removePropertyLink, getCurrentBlock, editBlockProperty } = useBlock()
|
||||
const { PLUGIN_NAME, activePlugin } = useLayout()
|
||||
const { schema } = getSchema()
|
||||
const { schema } = canvasApi.value.getSchema?.() || {}
|
||||
|
||||
const state = reactive({
|
||||
newPropertyName: ''
|
||||
|
|
@ -68,7 +67,7 @@ export default {
|
|||
exec() {
|
||||
const {
|
||||
schema: { id, componentName }
|
||||
} = getCurrent()
|
||||
} = canvasApi.value?.getCurrent?.() || {}
|
||||
const newProperty = extend(true, {}, property, {
|
||||
property: state.newPropertyName || `${property.property}${id}`,
|
||||
linked: {
|
||||
|
|
@ -87,7 +86,7 @@ export default {
|
|||
const editProperty = (property) => {
|
||||
const {
|
||||
schema: { id, componentName }
|
||||
} = getCurrent()
|
||||
} = canvasApi.value?.getCurrent?.() || {}
|
||||
|
||||
// 如果之前有关联关系,则需要去除关联
|
||||
if (props.data?.linked) {
|
||||
|
|
|
|||
|
|
@ -103,14 +103,14 @@ import { inject, computed, watch, ref, reactive, provide } from 'vue'
|
|||
import { Popover, Tooltip } from '@opentiny/vue'
|
||||
import { IconWriting, IconHelpCircle, IconPlusCircle } from '@opentiny/vue-icon'
|
||||
import { typeOf } from '@opentiny/vue-renderless/common/type'
|
||||
import i18n from '../js/i18n'
|
||||
import i18n from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
import { MetaComponents } from '../index'
|
||||
import MetaBindVariable from './MetaBindVariable.vue'
|
||||
import MetaCodeEditor from './MetaCodeEditor.vue'
|
||||
import MultiTypeSelector from './MultiTypeSelector.vue'
|
||||
import { useHistory, useProperties, useResource, useLayout, useCanvas } from '@opentiny/tiny-engine-controller'
|
||||
import { generateFunction } from '@opentiny/tiny-engine-controller/utils'
|
||||
import { SCHEMA_DATA_TYPE, PAGE_STATUS, TYPES } from '../js/constants'
|
||||
import { SCHEMA_DATA_TYPE, PAGE_STATUS, TYPES } from '@opentiny/tiny-engine-controller/js/constants'
|
||||
|
||||
const hasRule = (required, rules) => {
|
||||
if (required) {
|
||||
|
|
@ -244,7 +244,7 @@ export default {
|
|||
})
|
||||
|
||||
const updateValue = (value) => {
|
||||
const { property } = props.property
|
||||
const { property, type } = props.property
|
||||
const { setProp } = useProperties()
|
||||
|
||||
// 是否双向绑定
|
||||
|
|
@ -283,7 +283,7 @@ export default {
|
|||
}
|
||||
|
||||
if (props.isTopLayer) {
|
||||
setProp(property, value)
|
||||
setProp(property, value, type)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,14 +78,13 @@
|
|||
<script lang="jsx">
|
||||
import { reactive, ref, watchEffect, onBeforeUnmount } from 'vue'
|
||||
import { Button, DialogBox, Popover, Search, Alert } from '@opentiny/vue'
|
||||
import { getGlobalConfig, useModal, usePage, useNotify } from '@opentiny/tiny-engine-controller'
|
||||
import { getGlobalConfig, useModal, usePage, useNotify, useCanvas } from '@opentiny/tiny-engine-controller'
|
||||
import { theme } from '@opentiny/tiny-engine-controller/adapter'
|
||||
import { getSchema } from '@opentiny/tiny-engine-canvas'
|
||||
import MetaListItems from './MetaListItems.vue'
|
||||
import { iconYes } from '@opentiny/vue-icon'
|
||||
import VueMonaco from './VueMonaco.vue'
|
||||
import { initCompletion } from '../js/completion'
|
||||
import { initLinter, lint } from '../js/linter'
|
||||
import { initCompletion } from '@opentiny/tiny-engine-controller/js/completion'
|
||||
import { initLinter, lint } from '@opentiny/tiny-engine-controller/js/linter'
|
||||
import { SvgButton } from '../index'
|
||||
|
||||
export default {
|
||||
|
|
@ -125,11 +124,12 @@ export default {
|
|||
bindLifeCycles: {},
|
||||
editorValue: '{}',
|
||||
hasError: false,
|
||||
linterWorker: null
|
||||
linterWorker: null,
|
||||
completionProvider: null
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
state.bindLifeCycles = props.bindLifeCycles || getSchema()?.lifeCycles || {}
|
||||
state.bindLifeCycles = props.bindLifeCycles || useCanvas().canvasApi.value?.getSchema()?.lifeCycles || {}
|
||||
})
|
||||
|
||||
const searchLifeCyclesList = (value) => {
|
||||
|
|
@ -141,7 +141,7 @@ export default {
|
|||
}
|
||||
|
||||
const syncLifeCycle = () => {
|
||||
const currentSchema = getSchema()
|
||||
const currentSchema = useCanvas().canvasApi.value?.getSchema?.()
|
||||
const pageContent = getPageContent()
|
||||
const { id, fileName } = pageContent
|
||||
if (id === currentSchema.id || fileName === currentSchema.fileName) {
|
||||
|
|
@ -164,7 +164,8 @@ export default {
|
|||
|
||||
const openLifeCyclesPanel = (item) => {
|
||||
state.title = item
|
||||
const bindLifeCycleSource = props.bindLifeCycles?.[item] || getSchema().lifeCycles?.[item]
|
||||
const bindLifeCycleSource =
|
||||
props.bindLifeCycles?.[item] || useCanvas().canvasApi.value?.getSchema?.()?.lifeCycles?.[item]
|
||||
state.editorValue =
|
||||
bindLifeCycleSource?.value ||
|
||||
`function ${item} (${item === 'setup' ? '{ props, state, watch, onMounted }' : ''}) {} `
|
||||
|
|
@ -210,7 +211,7 @@ export default {
|
|||
return
|
||||
}
|
||||
// Lowcode API 提示
|
||||
initCompletion(editorRef.value.getMonaco())
|
||||
state.completionProvider = initCompletion(editorRef.value.getMonaco(), editorRef.value.getEditor()?.getModel())
|
||||
|
||||
// 初始化 ESLint worker
|
||||
state.linterWorker = initLinter(editor, editorRef.value.getMonaco(), state)
|
||||
|
|
@ -226,6 +227,9 @@ export default {
|
|||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
state.completionProvider?.forEach?.((provider) => {
|
||||
provider.dispose()
|
||||
})
|
||||
// 终止 ESLint worker
|
||||
state.linterWorker?.terminate?.()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
</slot>
|
||||
|
||||
<tiny-dialog-box
|
||||
v-if="dialogShouldInitialize"
|
||||
:visible="state.isVisible"
|
||||
title="变量绑定"
|
||||
width="48%"
|
||||
|
|
@ -123,15 +124,14 @@ import { reactive, ref, computed, nextTick, watch } from 'vue'
|
|||
import { camelize, capitalize } from '@vue/shared'
|
||||
import { Button, DialogBox, Search, Switch, Input, Tooltip, Alert } from '@opentiny/vue'
|
||||
import { useHttp } from '@opentiny/tiny-engine-http'
|
||||
import { getSchema, getGlobalState, setState, getNode, getCurrent } from '@opentiny/tiny-engine-canvas'
|
||||
import { useCanvas, useResource, useLayout, useApp, useProperties, useData } from '@opentiny/tiny-engine-controller'
|
||||
import { theme } from '@opentiny/tiny-engine-controller/adapter'
|
||||
import { constants } from '@opentiny/tiny-engine-utils'
|
||||
import SvgButton from './SvgButton.vue'
|
||||
import { parse, traverse, generate } from '../js/ast'
|
||||
import { DEFAULT_LOOP_NAME } from '../js/constants.js'
|
||||
import { parse, traverse, generate } from '@opentiny/tiny-engine-controller/js/ast'
|
||||
import { DEFAULT_LOOP_NAME } from '@opentiny/tiny-engine-controller/js/constants'
|
||||
import MonacoEditor from './VueMonaco.vue'
|
||||
import { formatString } from '../js/ast.js'
|
||||
import { formatString } from '@opentiny/tiny-engine-controller/js/ast'
|
||||
|
||||
const { EXPRESSION_TYPE } = constants
|
||||
|
||||
|
|
@ -149,6 +149,12 @@ const CONSTANTS = {
|
|||
}
|
||||
|
||||
const getJsSlot = () => {
|
||||
const { getNode, getCurrent } = useCanvas().canvasApi.value || {}
|
||||
|
||||
if (!getNode || !getCurrent) {
|
||||
return [false, {}]
|
||||
}
|
||||
|
||||
const jsSlot = getNode(getCurrent()?.parent?.id, true)?.parent
|
||||
|
||||
return [jsSlot?.type === 'JSSlot', jsSlot]
|
||||
|
|
@ -181,6 +187,10 @@ export default {
|
|||
modelValue: {
|
||||
type: [String, Number, Boolean, Array, Object, Date],
|
||||
default: ''
|
||||
},
|
||||
lazyLoad: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
|
|
@ -393,10 +403,9 @@ export default {
|
|||
const confirm = () => {
|
||||
let variableContent = state.isEditorEditMode ? editor.value?.getEditor().getValue() : state.variable
|
||||
|
||||
const { setSaved, canvasApi } = useCanvas()
|
||||
// 如果新旧值不一样就显示未保存状态
|
||||
if (oldValue !== variableContent) {
|
||||
const { setSaved } = useCanvas()
|
||||
|
||||
setSaved(false)
|
||||
variableContent = formatString(variableContent, 'javascript')
|
||||
}
|
||||
|
|
@ -406,14 +415,14 @@ export default {
|
|||
|
||||
if (variableContent) {
|
||||
if (state.bindPrefix === CONSTANTS.DATASOUCEPREFIX) {
|
||||
const pageSchema = getSchema()
|
||||
const pageSchema = canvasApi.value.getSchema()
|
||||
const stateName = state.variable.replace(`${CONSTANTS.STATE}`, '')
|
||||
const staticData = state.variableContent.map(({ _id, ...other }) => other)
|
||||
|
||||
pageSchema.state[stateName] = staticData
|
||||
|
||||
// 设置画布上下文环境,让画布触发更新渲染
|
||||
setState({ [stateName]: staticData })
|
||||
canvasApi.value.setState({ [stateName]: staticData })
|
||||
|
||||
// 这里在setup生命周期函数内部处理用户真实环境中的数据源请求
|
||||
genRemoteMethodToLifeSetup(stateName, state.dataSouce, pageSchema)
|
||||
|
|
@ -442,11 +451,13 @@ export default {
|
|||
return ''
|
||||
}
|
||||
|
||||
const dialogShouldInitialize = ref(!props.lazyLoad)
|
||||
const open = () => {
|
||||
dialogShouldInitialize.value = true
|
||||
state.isVisible = true
|
||||
state.variableName = bindKey.value
|
||||
state.variable = getInitVariable()
|
||||
state.variables = getSchema()?.state || {}
|
||||
state.variables = useCanvas().canvasApi.value.getSchema()?.state || {}
|
||||
state.bindPrefix = CONSTANTS.STATE
|
||||
state.variableContent = state.variables[bindKey.value]
|
||||
nextTick(() => window.dispatchEvent(new Event('resize')))
|
||||
|
|
@ -454,6 +465,8 @@ export default {
|
|||
|
||||
const selectItem = (item) => {
|
||||
state.active = item.id
|
||||
const { canvasApi } = useCanvas()
|
||||
|
||||
if (item.id === 'function') {
|
||||
state.bindPrefix = CONSTANTS.THIS
|
||||
const { PLUGIN_NAME, getPluginApi } = useLayout()
|
||||
|
|
@ -469,7 +482,7 @@ export default {
|
|||
state.variables = bridge
|
||||
} else if (item.id === 'props') {
|
||||
state.bindPrefix = CONSTANTS.PROPS
|
||||
const properties = getSchema()?.schema?.properties
|
||||
const properties = canvasApi.value.getSchema()?.schema?.properties
|
||||
const bindProperties = {}
|
||||
properties?.forEach(({ content }) => {
|
||||
content.forEach(({ property }) => {
|
||||
|
|
@ -495,7 +508,7 @@ export default {
|
|||
state.bindPrefix = CONSTANTS.STORE
|
||||
state.variables = {}
|
||||
|
||||
const stores = getGlobalState()
|
||||
const stores = canvasApi.value.getGlobalState()
|
||||
stores.forEach(({ id, state: storeState = {}, getters = {} }) => {
|
||||
const loadProp = (prop) => {
|
||||
const propBinding = `${id}.${prop}`
|
||||
|
|
@ -516,7 +529,7 @@ export default {
|
|||
state.variables = params.reduce((variables, param) => ({ ...variables, [param]: param }), {})
|
||||
} else {
|
||||
state.bindPrefix = CONSTANTS.STATE
|
||||
state.variables = getSchema()?.[item.id]
|
||||
state.variables = canvasApi.value.getSchema()?.[item.id]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -527,6 +540,7 @@ export default {
|
|||
remove,
|
||||
cancel,
|
||||
confirm,
|
||||
dialogShouldInitialize,
|
||||
open,
|
||||
selectItem,
|
||||
state,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<script>
|
||||
import { ref, watchEffect } from 'vue'
|
||||
import { ButtonGroup } from '@opentiny/vue'
|
||||
import i18n from '../js/i18n'
|
||||
import i18n from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
|
||||
export default {
|
||||
name: 'MetaButtonGroup',
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
<script>
|
||||
import { ref, watchEffect } from 'vue'
|
||||
import { Cascader } from '@opentiny/vue'
|
||||
import i18n from '../js/i18n'
|
||||
import i18n from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
|
||||
export default {
|
||||
name: 'MetaCascader',
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<script>
|
||||
import { ref, watchEffect, computed } from 'vue'
|
||||
import { CheckboxGroup } from '@opentiny/vue'
|
||||
import i18n from '../js/i18n'
|
||||
import i18n from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
|
||||
export default {
|
||||
name: 'MetaCheckboxGroup',
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="editor-wrap">
|
||||
<slot>
|
||||
<slot :open="open">
|
||||
<div v-if="buttonShowContent" :class="['full-width', { 'empty-color': value === '' }]" @click="open">
|
||||
<span>{{ value === '' ? buttonLabel : value?.slice(0, 30) }}</span>
|
||||
<svg-icon class="edit-icon" name="flow-edit"></svg-icon>
|
||||
<span class="text-content text-ellipsis-multiple">{{ value === '' ? buttonLabel : value }}</span>
|
||||
<svg-icon class="edit-icon" name="edit"></svg-icon>
|
||||
</div>
|
||||
<tiny-button v-else class="edit-btn" @click="open">
|
||||
{{ buttonLabel }}
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
width="50vw"
|
||||
class="meta-code-editor-dialog-box"
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div class="source-code">
|
||||
<div v-if="editorTipsTitle" class="header-tips-container">
|
||||
|
|
@ -45,7 +46,13 @@
|
|||
</div>
|
||||
<template #footer>
|
||||
<div class="btn-box">
|
||||
<tiny-button plain type="danger" v-if="language === 'json' && showFormatBtn" @click="formatCode">
|
||||
<tiny-button
|
||||
v-if="language === 'json' && showFormatBtn"
|
||||
class="format-btn"
|
||||
plain
|
||||
type="danger"
|
||||
@click="formatCode"
|
||||
>
|
||||
{{ $t('common.format') }}
|
||||
</tiny-button>
|
||||
<div>
|
||||
|
|
@ -63,8 +70,8 @@ import { reactive, ref, computed, watchEffect, nextTick } from 'vue'
|
|||
import { Button, DialogBox } from '@opentiny/vue'
|
||||
import { iconChevronDown, iconChevronUp } from '@opentiny/vue-icon'
|
||||
import VueMonaco from './VueMonaco.vue'
|
||||
import i18n from '../js/i18n'
|
||||
import { formatString } from '../js/ast.js'
|
||||
import i18n from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
import { formatString } from '@opentiny/tiny-engine-controller/js/ast'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -139,7 +146,7 @@ export default {
|
|||
|
||||
watchEffect(() => {
|
||||
const { modelValue, dataType } = props
|
||||
const val = dataType ? modelValue?.value : modelValue
|
||||
const val = dataType ? modelValue?.value || '' : modelValue
|
||||
value.value = typeof val === 'string' ? val : JSON.stringify(val, null, 2)
|
||||
})
|
||||
|
||||
|
|
@ -269,20 +276,32 @@ export default {
|
|||
}
|
||||
.btn-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-end;
|
||||
&:has(.format-btn) {
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
.full-width {
|
||||
border: 1px solid #adb0b8;
|
||||
border-radius: 6px;
|
||||
padding: 4px 8px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid var(--ti-lowcode-meta-codeEditor-border-color);
|
||||
border-radius: 6px;
|
||||
&:hover {
|
||||
border-color: var(--ti-lowcode-meta-codeEditor-border-hover-color);
|
||||
}
|
||||
.text-content {
|
||||
--ellipsis-line: 1;
|
||||
}
|
||||
&.empty-color {
|
||||
color: var(--ti-lowcode-common-text-desc-color);
|
||||
}
|
||||
.edit-icon {
|
||||
margin-left: 4px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
color: var(--ti-lowcode-common-text-main-color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="head-content">
|
||||
<meta-input v-model="state.text" type="textarea" @change="change"></meta-input>
|
||||
<meta-input v-model="state.text" type="textarea" @update:modelValue="change"></meta-input>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import { ref, inject, watchEffect, reactive } from 'vue'
|
|||
import { Input, Tooltip, Form, FormItem } from '@opentiny/vue'
|
||||
import { useProperties, useCanvas, useModal } from '@opentiny/tiny-engine-controller'
|
||||
import SvgICons from '@opentiny/vue-icon'
|
||||
import { verifyJsVarName } from '../js/verification'
|
||||
import { verifyJsVarName } from '@opentiny/tiny-engine-controller/js/verification'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
<script>
|
||||
import { ref, watchEffect, computed } from 'vue'
|
||||
import { RadioGroup, RadioButton } from '@opentiny/vue'
|
||||
import i18n from '../js/i18n'
|
||||
import i18n from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
|
||||
export default {
|
||||
name: 'MetaRadioGroup',
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
<script>
|
||||
import { onMounted, ref, watchEffect } from 'vue'
|
||||
import { useMessage, useCanvas } from '@opentiny/tiny-engine-controller'
|
||||
import { getSchema } from '@opentiny/tiny-engine-canvas'
|
||||
import MetaCodeEditor from './MetaCodeEditor.vue'
|
||||
import MetaBindVariable from './MetaBindVariable.vue'
|
||||
|
||||
|
|
@ -91,7 +90,7 @@ export default {
|
|||
let newValue = value
|
||||
|
||||
if (value?.type === CONSTANT.JSEXPRESSION) {
|
||||
const pageSchema = getSchema()
|
||||
const pageSchema = useCanvas().canvasApi.value.getSchema()
|
||||
const stateName = value?.value?.replace(CONSTANT.STATE, '')
|
||||
newValue = pageSchema?.state?.[stateName]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
<script>
|
||||
import { computed, reactive, watchEffect } from 'vue'
|
||||
import { Select, Option, OptionGroup, Tooltip } from '@opentiny/vue'
|
||||
import i18n from '../js/i18n'
|
||||
import i18n from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@
|
|||
<script>
|
||||
import { ref, watchEffect, nextTick } from 'vue'
|
||||
import { Popover } from '@opentiny/vue'
|
||||
import { useProperties, useResource, useModal } from '@opentiny/tiny-engine-controller'
|
||||
import { updateRect } from '@opentiny/tiny-engine-canvas'
|
||||
import { useProperties, useResource, useModal, useCanvas } from '@opentiny/tiny-engine-controller'
|
||||
import { iconHelpCircle } from '@opentiny/vue-icon'
|
||||
|
||||
export default {
|
||||
|
|
@ -121,7 +120,7 @@ export default {
|
|||
})
|
||||
}
|
||||
|
||||
updateRect()
|
||||
useCanvas().canvasApi.value.updateRect()
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
<script setup>
|
||||
import { nextTick } from 'vue'
|
||||
import { updateRect } from '@opentiny/tiny-engine-canvas'
|
||||
import { useProperties, useResource } from '@opentiny/tiny-engine-controller'
|
||||
import { useProperties, useResource, useCanvas } from '@opentiny/tiny-engine-controller'
|
||||
import MetaArrayItem from './MetaArrayItem.vue'
|
||||
|
||||
const { children: schemaChildren, componentName, props } = useProperties().getSchema()
|
||||
|
|
@ -26,7 +25,7 @@ const updateColumns = (columns) => {
|
|||
})
|
||||
|
||||
useProperties().getSchema().children = children
|
||||
nextTick(updateRect)
|
||||
nextTick(useCanvas().canvasApi.value.updateRect)
|
||||
}
|
||||
|
||||
updateColumns(props?.columns)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<template>
|
||||
<div>
|
||||
<div :class="['toolbar', { _full: fullscreen }]">
|
||||
<div :class="['editor-container', { 'editor-container-full': fullscreen }]">
|
||||
<div class="toolbar">
|
||||
<div class="toolbar-start">
|
||||
<slot name="toolbarStart"></slot>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<slot name="buttons"></slot>
|
||||
<tiny-tooltip v-if="showFormatBtn && options.language === 'json'" content="格式化" placement="top">
|
||||
|
|
@ -8,17 +11,17 @@
|
|||
</tiny-tooltip>
|
||||
<span v-if="showFullScreenBtn">
|
||||
<tiny-tooltip v-if="!fullscreen" content="全屏" placement="top">
|
||||
<public-icon name="full-screen" @click="fullscreen = true"></public-icon>
|
||||
<public-icon name="full-screen" @click="switchFullScreen(true)"></public-icon>
|
||||
</tiny-tooltip>
|
||||
<tiny-tooltip v-else content="退出全屏" placement="top">
|
||||
<public-icon name="cancel-full-screen" @click="fullscreen = false"></public-icon>
|
||||
<public-icon name="cancel-full-screen" @click="switchFullScreen(false)"></public-icon>
|
||||
</tiny-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<monaco-editor
|
||||
ref="editor"
|
||||
:class="fullscreen ? 'fullscreen' : 'iniline'"
|
||||
class="editor"
|
||||
:value="value"
|
||||
:options="editorOptions"
|
||||
language="javascript"
|
||||
|
|
@ -110,12 +113,17 @@ export default {
|
|||
editor.value.getEditor().dispose()
|
||||
})
|
||||
|
||||
const switchFullScreen = (value) => {
|
||||
fullscreen.value = value
|
||||
}
|
||||
|
||||
return {
|
||||
editorOptions,
|
||||
editor,
|
||||
getEditor,
|
||||
getEditorValue,
|
||||
fullscreen,
|
||||
switchFullScreen,
|
||||
getValue,
|
||||
formatCode
|
||||
}
|
||||
|
|
@ -124,41 +132,45 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.editor-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.editor-container-full {
|
||||
position: fixed;
|
||||
top: var(--base-top-panel-height);
|
||||
bottom: 0;
|
||||
left: calc(var(--base-nav-panel-width) + var(--base-left-panel-width));
|
||||
right: var(--base-left-panel-width);
|
||||
z-index: 10;
|
||||
padding: 10px 16px 16px 16px;
|
||||
background-color: var(--ti-lowcode-common-component-bg);
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
justify-content: flex-end;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
z-index: 3000 !important;
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
color: var(--ti-lowcode-component-svg-button-color);
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
:hover {
|
||||
color: var(--ti-lowcode-component-svg-button-hover-color);
|
||||
}
|
||||
}
|
||||
&._full {
|
||||
position: fixed;
|
||||
top: 35px;
|
||||
z-index: 1;
|
||||
padding-right: 15px;
|
||||
right: var(--base-left-panel-width);
|
||||
}
|
||||
}
|
||||
.iniline {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.fullscreen {
|
||||
position: fixed;
|
||||
top: 35px;
|
||||
bottom: 0;
|
||||
left: calc(var(--base-nav-panel-width) + 1px);
|
||||
right: var(--base-left-panel-width);
|
||||
z-index: 2500;
|
||||
}
|
||||
.public-icon {
|
||||
font-size: 18px;
|
||||
margin-left: 10px;
|
||||
|
||||
.editor {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--ti-lowcode-state-management-monaco-editor-border-color);
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<ul
|
||||
v-if="state.data.length"
|
||||
:class="['block-list', 'lowcode-scrollbar', { 'is-small-list': blockStyle === 'mini' }, { isShortcutPanel }]"
|
||||
@mouseleave="state.hover = false"
|
||||
>
|
||||
|
|
@ -122,12 +123,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</ul>
|
||||
<search-empty :isShow="!state.data.length" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, watch, inject, reactive } from 'vue'
|
||||
import { iconSetting, iconPlus } from '@opentiny/vue-icon'
|
||||
import { Tooltip, Progress, Popover } from '@opentiny/vue'
|
||||
import SearchEmpty from './SearchEmpty.vue'
|
||||
import SvgButton from './SvgButton.vue'
|
||||
|
||||
const defaultImg =
|
||||
|
|
@ -140,7 +143,8 @@ export default {
|
|||
IconSetting: iconSetting(),
|
||||
IconPlus: iconPlus(),
|
||||
TinyPopover: Popover,
|
||||
SvgButton
|
||||
SvgButton,
|
||||
SearchEmpty
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
|
|
@ -344,7 +348,7 @@ export default {
|
|||
position: fixed;
|
||||
z-index: 9999;
|
||||
top: 50px;
|
||||
left: calc(var(--base-left-panel-width, 268px) + var(--base-nav-panel-width) + 10px);
|
||||
left: calc(var(--base-left-panel-width) + var(--base-nav-panel-width) + 10px);
|
||||
max-width: 500px;
|
||||
max-height: 136px;
|
||||
padding: 12px;
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export default {
|
|||
<style lang="less" scoped>
|
||||
.plugin-setting {
|
||||
position: absolute;
|
||||
left: calc(var(--base-left-panel-width, 268px) - 6px);
|
||||
left: calc(var(--base-left-panel-width) - 6px);
|
||||
top: 0;
|
||||
width: var(--base-collection-panel-width);
|
||||
height: 100%;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,18 @@
|
|||
<template>
|
||||
<div>
|
||||
<tiny-dialog-box :append-to-body="true" :visible="visible" title="新建区块" width="500" @close="cancel">
|
||||
<tiny-dialog-box
|
||||
:append-to-body="true"
|
||||
:close-on-click-modal="false"
|
||||
:visible="visible"
|
||||
title="新建区块"
|
||||
width="500"
|
||||
@close="cancel"
|
||||
>
|
||||
<tiny-form
|
||||
show-message
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
ref="formRef"
|
||||
label-width="120px"
|
||||
:label-align="true"
|
||||
label-position="left"
|
||||
|
|
@ -33,10 +41,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, computed } from 'vue'
|
||||
import { reactive, computed, ref } from 'vue'
|
||||
import { Input, Form, FormItem, Button, DialogBox, Select } from '@opentiny/vue'
|
||||
import { useBlock, useLayout, useCanvas, useModal } from '@opentiny/tiny-engine-controller'
|
||||
import { REGEXP_BLOCK_NAME } from '../js/verification'
|
||||
import { REGEXP_BLOCK_NAME } from '@opentiny/tiny-engine-controller/js/verification'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
@ -64,6 +72,7 @@ export default {
|
|||
const { PLUGIN_NAME, activePlugin } = useLayout()
|
||||
const { isSaved } = useCanvas()
|
||||
const { confirm } = useModal()
|
||||
const formRef = ref(null)
|
||||
|
||||
const categoryList = computed(() =>
|
||||
getCategoryList().map((item) => ({ ...item, value: item.id, label: item.name }))
|
||||
|
|
@ -84,15 +93,21 @@ export default {
|
|||
cancel()
|
||||
}
|
||||
const addBlock = () => {
|
||||
if (isSaved()) {
|
||||
handleAddBlock()
|
||||
return
|
||||
}
|
||||
confirm({
|
||||
message: '当前画布内容尚未保存,新建区块会将画布切换至新区块中,是否要继续切换?',
|
||||
exec: () => {
|
||||
handleAddBlock()
|
||||
formRef.value.validate((valid) => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
|
||||
if (isSaved()) {
|
||||
handleAddBlock()
|
||||
return
|
||||
}
|
||||
confirm({
|
||||
message: '当前画布内容尚未保存,新建区块会将画布切换至新区块中,是否要继续切换?',
|
||||
exec: () => {
|
||||
handleAddBlock()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +122,7 @@ export default {
|
|||
return {
|
||||
formData,
|
||||
categoryList,
|
||||
formRef,
|
||||
rules,
|
||||
addBlock,
|
||||
cancel,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div v-if="isShow" class="empty-wrap">
|
||||
<svg-icon class="empty-icon" name="empty"></svg-icon>
|
||||
<p class="empty-text">暂无数据</p>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
/**
|
||||
* 控制搜索空数据显示
|
||||
*/
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<script>
|
||||
import * as monacoEditor from 'monaco-editor'
|
||||
import { watch, onMounted, nextTick, onBeforeUnmount, ref } from 'vue'
|
||||
import { formatString } from '../js/ast.js'
|
||||
import { formatString } from '@opentiny/tiny-engine-controller/js/ast'
|
||||
|
||||
export default {
|
||||
name: 'MonacoEditor',
|
||||
|
|
|
|||
|
|
@ -79,8 +79,9 @@ import BlockDeployDialog from './component/BlockDeployDialog.vue'
|
|||
import ProgressBar from './component/ProgressBar.vue'
|
||||
import MetaButtonGroup from './component/MetaButtonGroup.vue'
|
||||
import MetaTableColumns from './component/MetaTableColumns.vue'
|
||||
import SearchEmpty from './component/SearchEmpty.vue'
|
||||
|
||||
import i18n, { i18nKeyMaps } from './js/i18n.js'
|
||||
import i18n, { i18nKeyMaps } from '@opentiny/tiny-engine-controller/js/i18n'
|
||||
|
||||
import enUs from './i18n/en-us.json'
|
||||
import zhCn from './i18n/zh-cn.json'
|
||||
|
|
@ -90,6 +91,20 @@ const { mergeLocaleMessage } = i18n.global
|
|||
mergeLocaleMessage(i18nKeyMaps.enUS, enUs)
|
||||
mergeLocaleMessage(i18nKeyMaps.zhCN, zhCn)
|
||||
|
||||
const globalComponents = {
|
||||
SaveNewBlock,
|
||||
ConfigGroup,
|
||||
ConfigItem
|
||||
}
|
||||
|
||||
export const injectGlobalComponents = {
|
||||
install: (app) => {
|
||||
Object.entries(globalComponents).forEach(([name, component]) => {
|
||||
app.component(name, component)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const MetaComponents = {
|
||||
MetaArrayItem,
|
||||
MetaBindI18n,
|
||||
|
|
@ -131,7 +146,8 @@ export const MetaComponents = {
|
|||
MetaIpSection,
|
||||
MetaRelatedEditor,
|
||||
MetaRelatedColumns,
|
||||
MetaTableColumns
|
||||
MetaTableColumns,
|
||||
SearchEmpty
|
||||
}
|
||||
|
||||
export {
|
||||
|
|
@ -192,5 +208,6 @@ export {
|
|||
BindI18n,
|
||||
BlockDeployDialog,
|
||||
ProgressBar,
|
||||
MetaTableColumns
|
||||
MetaTableColumns,
|
||||
SearchEmpty
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-common",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.2",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
|
@ -10,12 +10,10 @@
|
|||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./js/*": "./js/*.js"
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"js"
|
||||
"dist"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
@ -29,29 +27,24 @@
|
|||
"license": "MIT",
|
||||
"homepage": "https://opentiny.design/tiny-engine",
|
||||
"dependencies": {
|
||||
"@babel/generator": "7.18.13",
|
||||
"@babel/parser": "7.18.13",
|
||||
"@babel/traverse": "7.18.13",
|
||||
"@opentiny/tiny-engine-canvas": "workspace:*",
|
||||
"@opentiny/tiny-engine-controller": "workspace:*",
|
||||
"@opentiny/tiny-engine-http": "workspace:*",
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@opentiny/tiny-engine-utils": "workspace:*",
|
||||
"@opentiny/vue": "~3.10.0",
|
||||
"@opentiny/vue-icon": "~3.10.0",
|
||||
"@opentiny/vue-locale": "~3.10.0",
|
||||
"@opentiny/vue-renderless": "~3.10.0",
|
||||
"@vue/shared": "^3.3.4",
|
||||
"css-tree": "^2.3.1",
|
||||
"monaco-editor": "0.33.0",
|
||||
"prettier": "2.7.1",
|
||||
"vue": "3.2.45",
|
||||
"vue-draggable-next": "2.1.0",
|
||||
"vue-i18n": "9.2.2"
|
||||
"vue-draggable-next": "2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.10",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"vite": "^4.3.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentiny/vue": "^3.14.0",
|
||||
"@opentiny/vue-icon": "^3.14.0",
|
||||
"@opentiny/vue-renderless": "^3.14.0",
|
||||
"vue": "^3.4.15"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@ export default defineConfig({
|
|||
plugins: [vue(), vueJsx()],
|
||||
publicDir: false,
|
||||
resolve: {},
|
||||
define: {
|
||||
'process.env': {}
|
||||
},
|
||||
build: {
|
||||
cssCodeSplit: false,
|
||||
lib: {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
* 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 { parse, parseExpression } from '@babel/parser'
|
||||
import generate from '@babel/generator'
|
||||
|
|
@ -17,6 +17,7 @@ import prettier from 'prettier'
|
|||
import parserHtml from 'prettier/parser-html'
|
||||
import parseCss from 'prettier/parser-postcss'
|
||||
import parserBabel from 'prettier/parser-babel'
|
||||
import prettierConfig from './config-files/prettierrc'
|
||||
|
||||
const METHOD_REGEXP = /function.*?\(/
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ export const insertName = (name, content) => content.replace(METHOD_REGEXP, `fun
|
|||
|
||||
export const removeName = (content) => content.replace(METHOD_REGEXP, 'function (')
|
||||
|
||||
export const string2Ast = (string = '') => parse(string, { sourceType: 'module', plugins: ['typescript'] })
|
||||
export const string2Ast = (string = '') => parse(string, { sourceType: 'module', plugins: ['typescript', 'jsx'] })
|
||||
|
||||
export const ast2String = (ast) => generate(ast, { retainLines: true }).code
|
||||
|
||||
|
|
@ -33,10 +34,7 @@ const formatScript = (string) => {
|
|||
const options = {
|
||||
parser: 'babel',
|
||||
plugins: [parserBabel],
|
||||
printWidth: 120,
|
||||
singleQuote: true,
|
||||
semi: false,
|
||||
trailingComma: 'none'
|
||||
...prettierConfig
|
||||
}
|
||||
try {
|
||||
// 低码中的编辑器大多只会输入js值,并不是一个完整的javascript表达式,无法格式化,因此需要特殊处理预格式化该种情形
|
||||
|
|
@ -53,21 +51,21 @@ const formatJson = (string) =>
|
|||
parser: 'json',
|
||||
plugins: [parserBabel],
|
||||
trailingComma: 'es5',
|
||||
tabWidth: 2,
|
||||
semi: false,
|
||||
singleQuote: true
|
||||
...prettierConfig
|
||||
})
|
||||
|
||||
const formatHtml = (string) =>
|
||||
prettier.format(string, {
|
||||
parser: 'html',
|
||||
plugins: [parserBabel, parserHtml]
|
||||
plugins: [parserBabel, parserHtml],
|
||||
...prettierConfig
|
||||
})
|
||||
|
||||
const formatCss = (string) =>
|
||||
prettier.format(string, {
|
||||
parser: 'css',
|
||||
plugins: [parseCss]
|
||||
plugins: [parseCss],
|
||||
...prettierConfig
|
||||
})
|
||||
|
||||
const formatterMap = {
|
||||
|
|
@ -11,7 +11,8 @@
|
|||
*/
|
||||
|
||||
import { PAGE_STATUS } from './constants'
|
||||
import { useEditorInfo, useResource } from '@opentiny/tiny-engine-controller'
|
||||
import useEditorInfo from '../src/useEditorInfo'
|
||||
import useResource from '../src/useResource'
|
||||
|
||||
export const getCanvasStatus = (data) => {
|
||||
// 写死ID 待删除
|
||||
|
|
@ -10,7 +10,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import { useCanvas, useResource } from '@opentiny/tiny-engine-controller'
|
||||
import useCanvas from '../src/useCanvas'
|
||||
import useResource from '../src/useResource'
|
||||
|
||||
const keyWords = [
|
||||
'state',
|
||||
|
|
@ -157,7 +158,7 @@ const getWords = (model, position) => {
|
|||
const lastWord = model.getWordUntilPosition(lastPosition).word
|
||||
? model.getWordUntilPosition(lastPosition)
|
||||
: getCurrentChar(model, lastPosition)
|
||||
if (!/[\w\.]/.test(lastWord.word)) break
|
||||
if (!/[\w.]/.test(lastWord.word)) break
|
||||
words.push(lastWord)
|
||||
lastPosition.column = lastWord.startColumn
|
||||
}
|
||||
|
|
@ -172,9 +173,14 @@ const getRange = (position, words) => ({
|
|||
endColumn: words[words.length - 1].endColumn
|
||||
})
|
||||
|
||||
export const initCompletion = (monacoInstance) => {
|
||||
export const initCompletion = (monacoInstance, editorModel, conditionFn) => {
|
||||
const completionItemProvider = {
|
||||
provideCompletionItems(model, position, _context, _token) {
|
||||
if (editorModel && model.id !== editorModel.id) {
|
||||
return {
|
||||
suggestions: []
|
||||
}
|
||||
}
|
||||
const words = getWords(model, position)
|
||||
const wordContent = words.map((item) => item.word).join('')
|
||||
const range = getRange(position, words)
|
||||
|
|
@ -185,9 +191,10 @@ export const initCompletion = (monacoInstance) => {
|
|||
const snippetSuggestions = getSnippetsSuggestions(monacoInstance, range, wordContent)
|
||||
// 用户变量数据提示 e.g. this.dataSourceMap.xxx.load()
|
||||
const userSuggestions = getUserSuggestions(monacoInstance, range, wordContent)
|
||||
|
||||
return {
|
||||
suggestions: [...apiSuggestions, ...snippetSuggestions, ...userSuggestions]
|
||||
suggestions: [...apiSuggestions, ...snippetSuggestions, ...userSuggestions].filter((item) =>
|
||||
conditionFn ? conditionFn(item) : true
|
||||
)
|
||||
}
|
||||
},
|
||||
triggerCharacters: ['.']
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import eslintRecommended from '@eslint/js/src/configs/eslint-recommended.js'
|
||||
export default {
|
||||
...eslintRecommended.rules,
|
||||
'no-console': 'error',
|
||||
'no-debugger': 'error',
|
||||
'space-before-function-paren': 'off',
|
||||
'no-use-before-define': 'error'
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
semi: false,
|
||||
singleQuote: true,
|
||||
printWidth: 120,
|
||||
trailingComma: 'none',
|
||||
endOfLine: 'auto',
|
||||
tabWidth: 2
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
|
||||
import * as cssTree from 'css-tree'
|
||||
import { hyphenate } from '@opentiny/tiny-engine-controller/utils'
|
||||
import { hyphenate } from '../utils'
|
||||
|
||||
/**
|
||||
* 传入 css 字符串,得到以选择器为 Key,css 规则为 value 的 object
|
||||
|
|
@ -11,7 +11,9 @@
|
|||
*/
|
||||
|
||||
import { useHttp } from '@opentiny/tiny-engine-http'
|
||||
import { usePage, useCanvas, useNotify } from '@opentiny/tiny-engine-controller'
|
||||
import usePage from '../src/usePage'
|
||||
import useCanvas from '../src/useCanvas'
|
||||
import useNotify from '../src/useNotify'
|
||||
import { isVsCodeEnv } from './environments'
|
||||
import { generateRouter, generatePage } from './vscodeGenerateFile'
|
||||
|
||||
|
|
@ -22,8 +24,13 @@ const http = useHttp()
|
|||
* @param { json } params {"event_type": design_error,"url": "elit in reprehenderit enim incididunt" }
|
||||
* @returns { Promise }
|
||||
*/
|
||||
export const requestEvent = (params) =>
|
||||
http.post('/platform-center/api/platform/monitoring/event', params).catch(() => {})
|
||||
export const requestEvent = (url, params) => {
|
||||
if (!url) {
|
||||
return
|
||||
}
|
||||
|
||||
return http.post(url, params).catch(() => {})
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面更新
|
||||
|
|
@ -1,27 +1,29 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
* 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 { PROD, BASE_URL } from './environments'
|
||||
import eslintWorkerUrl from './worker-files/eslint.worker?worker&url'
|
||||
|
||||
export const initLinter = (editor, monacoInstance, state) => {
|
||||
let workerUrl = `${BASE_URL}monaco-linter/eslint.worker.js`
|
||||
let workerUrl = new URL(eslintWorkerUrl, import.meta.url)
|
||||
|
||||
// 线上环境,存在 worker 资源跨域的情况
|
||||
if (PROD) {
|
||||
const workerBlob = new Blob([`importScripts('${workerUrl}');`], { type: 'application/javascript' })
|
||||
if (workerUrl.origin !== location.origin) {
|
||||
const workerBlob = new Blob([`import('${workerUrl}');`], {
|
||||
type: 'application/javascript'
|
||||
})
|
||||
workerUrl = window.URL.createObjectURL(workerBlob)
|
||||
}
|
||||
|
||||
const worker = new Worker(workerUrl)
|
||||
const worker = new Worker(workerUrl, { type: 'module' })
|
||||
|
||||
// 监听 ESLint web worker 的返回
|
||||
worker.onmessage = function (event) {
|
||||
|
|
@ -1,17 +1,19 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
* 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 { requestEvent } from './http.js'
|
||||
|
||||
let monitorUrl = ''
|
||||
|
||||
/**
|
||||
* 全局js异常埋点上报
|
||||
* @param errorMessage 异常信息
|
||||
|
|
@ -35,7 +37,7 @@ const getUrlUnit = () => {
|
|||
|
||||
const globalMonitoring = () => {
|
||||
window.onerror = function (errorMessage, scriptURI, lineNo, columnNo, error) {
|
||||
requestEvent({
|
||||
requestEvent(monitorUrl, {
|
||||
event_type: 'design_JSError',
|
||||
url: window.location.href,
|
||||
unit: getUrlUnit(),
|
||||
|
|
@ -67,7 +69,7 @@ const promiseMonitoring = () => {
|
|||
}
|
||||
}
|
||||
|
||||
requestEvent({
|
||||
requestEvent(monitorUrl, {
|
||||
event_type: 'design_promiseError',
|
||||
url: window.location.href,
|
||||
unit: getUrlUnit(),
|
||||
|
|
@ -91,8 +93,12 @@ const promiseMonitoring = () => {
|
|||
*/
|
||||
|
||||
export const iframeMonitoring = () => {
|
||||
if (!monitorUrl) {
|
||||
return false
|
||||
}
|
||||
|
||||
window.frames[0].onerror = function (errorMessage, scriptURI, lineNo, columnNo, error) {
|
||||
requestEvent({
|
||||
requestEvent(monitorUrl, {
|
||||
event_type: 'design_iframeError',
|
||||
url: window.location.href,
|
||||
unit: getUrlUnit(),
|
||||
|
|
@ -106,7 +112,8 @@ export const iframeMonitoring = () => {
|
|||
}
|
||||
}
|
||||
|
||||
export const initMonitor = () => {
|
||||
export const initMonitor = (url) => {
|
||||
monitorUrl = url
|
||||
globalMonitoring()
|
||||
promiseMonitoring()
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
import { constants } from '@opentiny/tiny-engine-utils'
|
||||
import { isDevelopEnv } from './environments'
|
||||
import { useResource } from '@opentiny/tiny-engine-controller'
|
||||
import useResource from '../src/useResource'
|
||||
// prefer old unicode hacks for backward compatibility
|
||||
|
||||
const { COMPONENT_NAME } = constants
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* 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 { Linter } from 'eslint-linter-browserify'
|
||||
import eslintRule from '../config-files/eslint-rule'
|
||||
|
||||
const defaultConfig = {
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
},
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
}
|
||||
}
|
||||
|
||||
const config = {
|
||||
...defaultConfig,
|
||||
rules: {
|
||||
...eslintRule,
|
||||
// JS 面板中,仅定义 function,但可能不使用该方法
|
||||
'no-unused-vars': 'off',
|
||||
'no-alert': 'off',
|
||||
'no-console': 'off'
|
||||
},
|
||||
settings: {}
|
||||
}
|
||||
|
||||
// 错误的等级,ESLint 与 monaco 的存在差异,做一层映射
|
||||
const severityMap = {
|
||||
2: 'Error',
|
||||
1: 'Warning'
|
||||
}
|
||||
const linter = new Linter()
|
||||
|
||||
self.addEventListener('message', (event) => {
|
||||
const { code, version } = event.data
|
||||
|
||||
const ruleDefines = linter.getRules()
|
||||
const errs = linter.verify(code, config)
|
||||
|
||||
const markers = errs.map(({ ruleId = '', line, endLine, column, endColumn, message, severity }) => ({
|
||||
code: {
|
||||
value: ruleId || '',
|
||||
target: ruleDefines.get(ruleId)?.meta?.docs?.url || ''
|
||||
},
|
||||
startLineNumber: line,
|
||||
endLineNumber: endLine,
|
||||
startColumn: column,
|
||||
endColumn: endColumn,
|
||||
message: message,
|
||||
severity: severityMap[severity],
|
||||
source: 'ESLint'
|
||||
}))
|
||||
|
||||
// ESLint 静态检查结果,发回主线程
|
||||
self.postMessage({ markers, version })
|
||||
})
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-controller",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.3",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
|
@ -10,10 +10,12 @@
|
|||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"files": [
|
||||
"dist"
|
||||
"dist",
|
||||
"js"
|
||||
],
|
||||
"exports": {
|
||||
".": "./dist/index.js",
|
||||
"./js/": "./dist/js/",
|
||||
"./utils": "./dist/utils.js",
|
||||
"./adapter": "./dist/adapter.js"
|
||||
},
|
||||
|
|
@ -29,19 +31,29 @@
|
|||
"license": "MIT",
|
||||
"homepage": "https://opentiny.design/tiny-engine",
|
||||
"dependencies": {
|
||||
"@opentiny/tiny-engine-canvas": "workspace:*",
|
||||
"@opentiny/tiny-engine-common": "workspace:*",
|
||||
"@opentiny/tiny-engine-http": "workspace:*",
|
||||
"@opentiny/tiny-engine-utils": "workspace:*",
|
||||
"@babel/generator": "~7.23.2",
|
||||
"@babel/parser": "~7.23.2",
|
||||
"@babel/traverse": "~7.23.2",
|
||||
"@opentiny/tiny-engine-builtin-component": "workspace:*",
|
||||
"@opentiny/vue": "~3.10.0",
|
||||
"@opentiny/vue-renderless": "~3.10.0",
|
||||
"@opentiny/tiny-engine-http": "workspace:*",
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@opentiny/tiny-engine-utils": "workspace:*",
|
||||
"@vue/shared": "^3.3.4",
|
||||
"vue": "3.2.45"
|
||||
"css-tree": "^2.3.1",
|
||||
"eslint-linter-browserify": "8.57.0",
|
||||
"prettier": "2.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.10",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"glob": "^10.3.4",
|
||||
"vite": "^4.3.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentiny/vue": "^3.14.0",
|
||||
"@opentiny/vue-locale": "^3.14.0",
|
||||
"@opentiny/vue-renderless": "^3.14.0",
|
||||
"vue": "^3.4.15",
|
||||
"vue-i18n": "^9.9.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,17 +15,16 @@ import { hyphenate } from '@vue/shared'
|
|||
import { extend, copyArray } from '@opentiny/vue-renderless/common/object'
|
||||
import { format } from '@opentiny/vue-renderless/common/date'
|
||||
import { remove } from '@opentiny/vue-renderless/common/array'
|
||||
import { getCanvasStatus } from '@opentiny/tiny-engine-common/js/index'
|
||||
import { ast2String, parseExpression } from '@opentiny/tiny-engine-common/js/ast'
|
||||
import { getCssObjectFromStyleStr } from '@opentiny/tiny-engine-common/js/css'
|
||||
import { constants } from '@opentiny/tiny-engine-utils'
|
||||
import { getCanvasStatus } from '../js/canvas'
|
||||
import { ast2String, parseExpression } from '../js/ast'
|
||||
import { getCssObjectFromStyleStr } from '../js/css'
|
||||
import useCanvas from './useCanvas'
|
||||
import useTranslate from './useTranslate'
|
||||
import useEditorInfo from './useEditorInfo'
|
||||
import useBreadcrumb from './useBreadcrumb'
|
||||
import useLayout from './useLayout'
|
||||
import { getGlobalConfig } from './globalConfig'
|
||||
import { getSchema, getCurrent } from '@opentiny/tiny-engine-canvas'
|
||||
|
||||
const { SORT_TYPE, SCHEMA_DATA_TYPE, BLOCK_OPENNESS } = constants
|
||||
|
||||
|
|
@ -279,7 +278,7 @@ const initBlock = async (block = {}, _langs = {}, isEdit) => {
|
|||
// 把区块的schema传递给画布
|
||||
await resetBlockCanvasState({ pageSchema: getBlockPageSchema(block) })
|
||||
// 这一步操作很重要,让区块管理面板和画布共同维护同一份区块schema
|
||||
block.content = getSchema()
|
||||
block.content = useCanvas().canvasApi.value?.getSchema()
|
||||
|
||||
setCurrentBlock(block)
|
||||
setBreadcrumbBlock([block[nameCn] || block.label], block.histories)
|
||||
|
|
@ -362,7 +361,7 @@ const createEmptyBlock = ({ name_cn, label, path, categories }) => {
|
|||
}
|
||||
|
||||
const setComponentLinkedValue = ({ propertyName, value }) => {
|
||||
const { schema } = getCurrent()
|
||||
const { schema } = useCanvas().canvasApi.value?.getCurrent() || {}
|
||||
|
||||
if (!propertyName || !schema) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@
|
|||
*/
|
||||
|
||||
/* eslint-disable no-new-func */
|
||||
import { reactive } from 'vue'
|
||||
import { setSchema, renderApi } from '@opentiny/tiny-engine-canvas'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { constants } from '@opentiny/tiny-engine-utils'
|
||||
import useHistory from './useHistory'
|
||||
|
||||
|
|
@ -52,12 +51,20 @@ const defaultSchema = {
|
|||
outputs: []
|
||||
}
|
||||
|
||||
const canvasApi = ref({})
|
||||
const isCanvasApiReady = ref(false)
|
||||
|
||||
const initCanvasApi = (newCanvasApi) => {
|
||||
canvasApi.value = newCanvasApi
|
||||
isCanvasApiReady.value = true
|
||||
}
|
||||
|
||||
const pageState = reactive({ ...defaultPageState, loading: true })
|
||||
// 重置画布数据
|
||||
const resetCanvasState = async (state = {}) => {
|
||||
Object.assign(pageState, defaultPageState, state)
|
||||
|
||||
await setSchema(pageState.pageSchema)
|
||||
await canvasApi.value?.setSchema(pageState.pageSchema)
|
||||
}
|
||||
|
||||
// 页面重置画布数据
|
||||
|
|
@ -151,10 +158,11 @@ export default function () {
|
|||
resetPageCanvasState,
|
||||
resetBlockCanvasState,
|
||||
clearCurrentState,
|
||||
getDataSourceMap: renderApi.getDataSourceMap,
|
||||
setDataSourceMap: renderApi.setDataSourceMap,
|
||||
getCurrentSchema,
|
||||
setCurrentSchema,
|
||||
getCurrentPage
|
||||
getCurrentPage,
|
||||
initCanvasApi,
|
||||
canvasApi,
|
||||
isCanvasApiReady
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ const helpState = {
|
|||
datasource: 11,
|
||||
i18n: 12,
|
||||
page: 2,
|
||||
script: 8
|
||||
script: 8,
|
||||
stylePanel: 6
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
import { reactive, isProxy, toRaw, watch } from 'vue'
|
||||
import useCanvas from './useCanvas'
|
||||
import { setSchema, getSchema } from '@opentiny/tiny-engine-canvas'
|
||||
|
||||
const schema2String = (schema) => {
|
||||
if (isProxy(schema)) {
|
||||
|
|
@ -62,7 +61,7 @@ const push = (schema) => {
|
|||
|
||||
const go = (addend, valid) => {
|
||||
historyState.index = historyState.index + addend
|
||||
setSchema(string2Schema(list[historyState.index]))
|
||||
useCanvas().canvasApi.value?.setSchema(string2Schema(list[historyState.index]))
|
||||
|
||||
// 不是锁定状态,撤销操作后,传递第二个标识位,将 list 的长度减一,置灰 undoredo 操作按钮
|
||||
if (typeof valid === 'boolean') {
|
||||
|
|
@ -84,17 +83,6 @@ const forward = () => {
|
|||
}
|
||||
}
|
||||
|
||||
const addHistory = (schema) => {
|
||||
if (!schema) {
|
||||
useCanvas().setSaved(false)
|
||||
push(getSchema())
|
||||
} else {
|
||||
clear()
|
||||
// 初始 schema 需要设置为第一条历史记录
|
||||
push(schema)
|
||||
}
|
||||
}
|
||||
|
||||
const clear = () => {
|
||||
list.splice(0)
|
||||
Object.assign(historyState, {
|
||||
|
|
@ -104,6 +92,17 @@ const clear = () => {
|
|||
})
|
||||
}
|
||||
|
||||
const addHistory = (schema) => {
|
||||
if (!schema) {
|
||||
useCanvas().setSaved(false)
|
||||
push(useCanvas().canvasApi.value?.getSchema())
|
||||
} else {
|
||||
clear()
|
||||
// 初始 schema 需要设置为第一条历史记录
|
||||
push(schema)
|
||||
}
|
||||
}
|
||||
|
||||
// 监控下标,判断是否允许前进后退标志
|
||||
watch(
|
||||
() => historyState.index,
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@
|
|||
*/
|
||||
|
||||
import { toRaw, nextTick, shallowReactive, ref } from 'vue'
|
||||
import { getNode, setState, updateRect } from '@opentiny/tiny-engine-canvas'
|
||||
import { constants } from '@opentiny/tiny-engine-utils'
|
||||
import useCanvas from './useCanvas'
|
||||
import useResource from './useResource'
|
||||
import useTranslate from './useTranslate'
|
||||
|
||||
const { COMPONENT_NAME } = constants
|
||||
const propsUpdateKey = ref(0)
|
||||
|
||||
const otherBaseKey = {
|
||||
|
|
@ -150,11 +151,18 @@ const properties = shallowReactive({
|
|||
parent: null
|
||||
})
|
||||
|
||||
const isPageOrBlock = (schema) => [COMPONENT_NAME.Block, COMPONENT_NAME.Page].includes(schema?.componentName)
|
||||
|
||||
const getProps = (schema, parent) => {
|
||||
// 现在选中的节点和当前节点一样,不需要重新计算
|
||||
if (schema && properties.schema !== schema) {
|
||||
// 1 现在选中的节点和当前节点一样,不需要重新计算, 2 默认进来由于scheme和properities.schema相等,因此判断如果是“页面或者区块”需要进入if判断
|
||||
if (schema && (properties.schema !== schema || isPageOrBlock(schema))) {
|
||||
const { props, componentName } = schema
|
||||
const { schema: metaSchema, content, properties } = useResource().getMaterial(componentName)
|
||||
// 若选中的是page或者 blcok,没有对应schema,ComponentName 给 div 设置根节点属性
|
||||
const {
|
||||
schema: metaSchema,
|
||||
content,
|
||||
properties
|
||||
} = useResource().getMaterial(isPageOrBlock(schema) ? 'div' : componentName)
|
||||
const schemaProps = properties || metaSchema?.properties || content?.schema?.properties || []
|
||||
const propGroups = [...schemaProps]
|
||||
|
||||
|
|
@ -169,22 +177,29 @@ const getProps = (schema, parent) => {
|
|||
properties.parent = parent
|
||||
}
|
||||
|
||||
const setProp = (name, value) => {
|
||||
const setProp = (name, value, type) => {
|
||||
if (!properties.schema) {
|
||||
return
|
||||
}
|
||||
|
||||
properties.schema.props = properties.schema.props || {}
|
||||
|
||||
if (value === '' || value === undefined || value === null) {
|
||||
if ((value === '' && type !== 'String') || value === undefined || value === null) {
|
||||
delete properties.schema.props[name]
|
||||
} else {
|
||||
properties.schema.props[name] = value
|
||||
}
|
||||
|
||||
// 没有父级,或者不在节点上面,要更新内容。就用setState
|
||||
getNode(properties.schema.id, true).parent || setState(useCanvas().getPageSchema().state)
|
||||
const { getNode, setState, updateRect } = useCanvas().canvasApi.value || {}
|
||||
getNode(properties.schema.id, true)?.parent || setState(useCanvas().getPageSchema().state)
|
||||
propsUpdateKey.value++
|
||||
|
||||
// 更新根节点props不用updateRect
|
||||
if (!properties.schema.id) {
|
||||
return
|
||||
}
|
||||
|
||||
nextTick(updateRect)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ import { reactive } from 'vue'
|
|||
import { getGlobalConfig } from './globalConfig'
|
||||
import { useHttp } from '@opentiny/tiny-engine-http'
|
||||
import { utils, constants } from '@opentiny/tiny-engine-utils'
|
||||
import { Builtin, addScript, addStyle, canvasDispatch } from '@opentiny/tiny-engine-canvas'
|
||||
import { getCanvasStatus } from '@opentiny/tiny-engine-common/js/index'
|
||||
import { meta as BuiltinComponentMaterials } from '@opentiny/tiny-engine-builtin-component'
|
||||
import { getCanvasStatus } from '../js/canvas'
|
||||
import useApp from './useApp'
|
||||
import useCanvas from './useCanvas'
|
||||
import useTranslate from './useTranslate'
|
||||
|
|
@ -138,6 +137,7 @@ const registerBlock = async (data, notFetchResouce) => {
|
|||
return block
|
||||
} else {
|
||||
if (!blockResource.get(label)) {
|
||||
const { addScript, addStyle } = useCanvas().canvasApi.value
|
||||
const promises = scripts
|
||||
.filter((item) => item.includes('umd.js'))
|
||||
.map(addScript)
|
||||
|
|
@ -372,6 +372,7 @@ const fetchResource = async ({ isInit = true } = {}) => {
|
|||
const { id, type } = useEditorInfo().useInfo()
|
||||
useApp().appInfoState.selectedId = id
|
||||
|
||||
const { Builtin } = useCanvas().canvasApi.value
|
||||
Builtin.data.materials.components[0].children.map(registerComponent)
|
||||
BuiltinComponentMaterials.components[0].children.map(registerComponent)
|
||||
|
||||
|
|
@ -451,7 +452,7 @@ const updateCanvasDependencies = (blocks) => {
|
|||
getBlockDeps(block.content.dependencies)
|
||||
})
|
||||
|
||||
canvasDispatch('updateDependencies', { detail: resState.thirdPartyDeps })
|
||||
useCanvas().canvasApi.value?.canvasDispatch('updateDependencies', { detail: resState.thirdPartyDeps })
|
||||
}
|
||||
|
||||
export default function () {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
|
||||
import { Modal } from '@opentiny/vue'
|
||||
import { VITE_ORIGIN } from '@opentiny/tiny-engine-common/js/environments'
|
||||
import { VITE_ORIGIN } from '../js/environments'
|
||||
import useCanvas from './useCanvas'
|
||||
import { getGlobalConfig } from './globalConfig'
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@
|
|||
import { reactive, ref } from 'vue'
|
||||
import { useHttp } from '@opentiny/tiny-engine-http'
|
||||
import { utils } from '@opentiny/tiny-engine-utils'
|
||||
import { setLocales } from '@opentiny/tiny-engine-canvas'
|
||||
import { isVsCodeEnv } from '@opentiny/tiny-engine-common/js/environments'
|
||||
import { isVsCodeEnv } from '../js/environments'
|
||||
import { constants } from '@opentiny/tiny-engine-utils'
|
||||
import { generateI18n } from '@opentiny/tiny-engine-common/js/vscodeGenerateFile'
|
||||
import { generateI18n } from '../js/vscodeGenerateFile'
|
||||
import useResource from './useResource'
|
||||
import { PROP_DATA_TYPE } from '../utils'
|
||||
import useCanvas from './useCanvas'
|
||||
|
||||
const { HOST_TYPE } = constants
|
||||
const state = reactive({
|
||||
|
|
@ -101,7 +101,7 @@ const ensureI18n = (obj, send) => {
|
|||
}
|
||||
})
|
||||
|
||||
setLocales(messages, true)
|
||||
useCanvas().canvasApi.value?.setLocales(messages, true)
|
||||
} catch (e) {
|
||||
// 不需要处理,有报错的词条会在画布初始化的时候统一调setLocales这个方法
|
||||
}
|
||||
|
|
@ -171,7 +171,7 @@ const initAppI18n = async (appId) => {
|
|||
host: appId,
|
||||
hostType: HOST_TYPE.App
|
||||
})
|
||||
setLocales(i18nResource.messages)
|
||||
useCanvas().canvasApi.value?.setLocales(i18nResource.messages)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ const initBlockI18n = async (blockId) => {
|
|||
host: blockId,
|
||||
hostType: HOST_TYPE.Block
|
||||
})
|
||||
setLocales(i18nResource.messages)
|
||||
useCanvas().canvasApi.value?.setLocales(i18nResource.messages)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ const initBlockLocalI18n = async (langs = {}) => {
|
|||
hostType: HOST_TYPE.Block,
|
||||
local: true
|
||||
})
|
||||
setLocales(i18nResource.messages)
|
||||
useCanvas().canvasApi.value?.setLocales(i18nResource.messages)
|
||||
}
|
||||
|
||||
const format = (str = '', params = {}) => str.replace(/\$\{(.+?)\}/g, (substr, key) => params[key] || '')
|
||||
|
|
|
|||
|
|
@ -14,26 +14,40 @@ import { defineConfig } from 'vite'
|
|||
import path from 'path'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import { glob } from 'glob'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const jsEntries = glob.sync('./js/**/*.js').map((file) => {
|
||||
return [file.slice(0, file.length - path.extname(file).length), fileURLToPath(new URL(file, import.meta.url))]
|
||||
})
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [vue(), vueJsx()],
|
||||
publicDir: false,
|
||||
resolve: {},
|
||||
base: './',
|
||||
define: {
|
||||
'import.meta': 'import.meta',
|
||||
'import.meta.env.MODE': 'import.meta.env.MODE',
|
||||
'import.meta.env.PROD': 'import.meta.env.PROD',
|
||||
'import.meta.env.BASE_URL': 'import.meta.env.BASE_URL'
|
||||
},
|
||||
build: {
|
||||
cssCodeSplit: false,
|
||||
lib: {
|
||||
entry: {
|
||||
index: path.resolve(__dirname, './src/index.js'),
|
||||
adapter: path.resolve(__dirname, './adapter.js'),
|
||||
utils: path.resolve(__dirname, './utils.js')
|
||||
utils: path.resolve(__dirname, './utils.js'),
|
||||
...Object.fromEntries(jsEntries)
|
||||
},
|
||||
name: 'controller',
|
||||
fileName: (formats, entryName) => `${entryName}.js`,
|
||||
formats: ['es']
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['vue', /@opentiny\/tiny-engine.*/, /@opentiny\/vue.*/]
|
||||
external: ['vue', 'vue-i18n', /@opentiny\/tiny-engine.*/, /@opentiny\/vue.*/, /^prettier.*/, /^@babel.*/]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,4 +2,11 @@
|
|||
|
||||
NODE_ENV=production
|
||||
VITE_CDN_DOMAIN=https://npm.onmicrosoft.cn
|
||||
VITE_LOCAL_IMPORT_MAPS=false
|
||||
VITE_LOCAL_BUNDLE_DEPS=false
|
||||
# VITE_ORIGIN=
|
||||
|
||||
# 错误监控上报 url
|
||||
VITE_ERROR_MONITOR_URL=/platform-center/api/platform/monitoring/event
|
||||
# 是否开启错误监控
|
||||
VITE_ERROR_MONITOR=false
|
||||
|
|
|
|||
|
|
@ -2,5 +2,7 @@
|
|||
|
||||
NODE_ENV=development
|
||||
VITE_CDN_DOMAIN=https://npm.onmicrosoft.cn
|
||||
VITE_LOCAL_IMPORT_MAPS=false
|
||||
VITE_LOCAL_BUNDLE_DEPS=false
|
||||
# request data via alpha service
|
||||
# VITE_ORIGIN=
|
||||
# VITE_ORIGIN=
|
||||
|
|
|
|||
|
|
@ -2,4 +2,6 @@
|
|||
|
||||
NODE_ENV=production
|
||||
VITE_CDN_DOMAIN=https://npm.onmicrosoft.cn
|
||||
#VITE_ORIGIN=
|
||||
VITE_LOCAL_IMPORT_MAPS=false
|
||||
VITE_LOCAL_BUNDLE_DEPS=false
|
||||
#VITE_ORIGIN=
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" xml:space="preserve" isSvg="true">
|
||||
<path d="M14 7c0 3.87-3.13 7-7 7s-7-3.13-7-7 3.13-7 7-7 7 3.13 7 7z" style="fill-rule: evenodd; clip-rule: evenodd;"></path>
|
||||
<path d="M9.96 9.29c.09.09.14.21.14.34 0 .13-.05.25-.14.33a.47.47 0 0 1-.67 0L7 7.67 4.71 9.96c-.18.18-.49.18-.67 0a.483.483 0 0 1 0-.67L6.33 7 4.04 4.71c-.09-.09-.14-.21-.14-.34s.05-.25.14-.34c.18-.18.49-.18.67 0L7 6.33l2.29-2.29c.19-.18.49-.18.67 0 .09.09.14.21.14.34s-.05.25-.14.34L7.67 7l2.29 2.29z" style="fill: rgb(255, 255, 255);"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 576 B |
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>国际化</title>
|
||||
<g id="国际化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="编组" transform="translate(2.000000, 2.000000)" stroke="#191919">
|
||||
<circle id="椭圆形" cx="6" cy="6" r="6"></circle>
|
||||
<path d="M1.61538462,6.69230769 C3.61538462,5.76923077 5.61538462,5.30769231 7.61538462,5.30769231 C9.61538462,5.30769231 11.6153846,5.76923077 13.6153846,6.69230769" id="直线" transform="translate(7.615385, 6.000000) rotate(90.000000) translate(-7.615385, -6.000000) "></path>
|
||||
<path d="M-1.61538462,6.69230769 C0.384615385,5.76923077 2.38461538,5.30769231 4.38461538,5.30769231 C6.38461538,5.30769231 8.38461538,5.76923077 10.3846154,6.69230769" id="直线备份" transform="translate(4.384615, 6.000000) scale(-1, 1) rotate(90.000000) translate(-4.384615, -6.000000) "></path>
|
||||
<path d="M0.461538462,4.61538462 C2.30769231,4.30769231 4.15384615,4.15384615 6,4.15384615 C7.84615385,4.15384615 9.69230769,4.30769231 11.5384615,4.61538462" id="直线-13" stroke-linecap="round" transform="translate(6.000000, 4.384615) scale(1, -1) translate(-6.000000, -4.384615) "></path>
|
||||
<path d="M0.461538462,7.84615385 C2.30769231,7.53846154 4.15384615,7.38461538 6,7.38461538 C7.84615385,7.38461538 9.69230769,7.53846154 11.5384615,7.84615385" id="直线-13备份" stroke-linecap="round"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>编组 7备份</title>
|
||||
<g id="ICon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="编组-7备份">
|
||||
<rect id="矩形" fill="currentColor" fill-rule="nonzero" opacity="0" x="0" y="0" width="24" height="24"></rect>
|
||||
<path d="M12.0003,2.00015 C14.6848308,2.00015 16.8613,4.17625357 16.8613,6.86115 L16.8613,6.86115 L16.861,9.24915 L17,9.24985 C18.5970631,9.24985 19.9036168,10.4993657 19.9949049,12.073641 L20,12.24985 L20,18.99985 C20,20.6567698 18.6565074,21.99985 17,21.99985 L17,21.99985 L7,21.99985 C5.34349256,21.99985 4,20.6567698 4,18.99985 L4,18.99985 L4,12.24985 C4,10.5936364 5.34378644,9.24985 7,9.24985 L7,9.24985 L7.138,9.24915 L7.1383,6.86115 C7.1383,4.24864046 9.19888513,2.11813926 11.7837168,2.00488536 L12.0003,2.00015 Z M7.87310737,10.7499992 L7,10.74985 C6.17221356,10.74985 5.5,11.4220636 5.5,12.24985 L5.5,12.24985 L5.5,18.99985 C5.5,19.8282396 6.17181662,20.49985 7,20.49985 L7,20.49985 L17,20.49985 C17.8281834,20.49985 18.5,19.8282396 18.5,18.99985 L18.5,18.99985 L18.5,12.24985 C18.5,11.4220636 17.8277864,10.74985 17,10.74985 L17,10.74985 L16.126,10.74915 L16.1113,10.75015 L7.8883,10.75015 C7.88322385,10.75015 7.87815949,10.7500996 7.87310737,10.7499992 Z M12.0003,3.50015 C10.1432663,3.50015 8.6383,5.00461073 8.6383,6.86115 L8.6383,6.86115 L8.638,9.24925 L15.361,9.24925 L15.3613,6.86115 C15.3613,5.06661755 13.9551107,3.60084673 12.1847022,3.5051226 L12.1847022,3.5051226 L12.0003,3.50015 Z" id="形状结合" fill="currentColor" fill-rule="nonzero"></path>
|
||||
<g id="编组-4" transform="translate(9.000000, 12.200000)" fill="currentColor">
|
||||
<circle id="椭圆形" cx="2.95" cy="1.77" r="1.77"></circle>
|
||||
<path d="M5.9,6.1890106 C5.9,5.44324225 5.62326654,4.76210845 5.16688577,4.24269538 C4.62623603,3.62737464 3.83347166,3.2390106 2.95,3.2390106 C2.0722897,3.2390106 1.28410749,3.6223259 0.743723518,4.23068636 C0.281025729,4.75158825 0,5.43748089 0,6.1890106 C0,6.95798112 5.9,7.02717331 5.9,6.1890106 Z" id="椭圆形"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -4,7 +4,6 @@
|
|||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="https://npm.onmicrosoft.cn/@opentiny/vue-theme@3.11/index.css" rel="stylesheet" />
|
||||
<style type="text/css">
|
||||
.loading-warp {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ export default {
|
|||
canvasOptions: {
|
||||
Angular: {},
|
||||
Vue: {
|
||||
material: ['http://localhost:8080/mock/bundle.json'],
|
||||
material: ['/mock/bundle.json'],
|
||||
scripts: [],
|
||||
styles: ['http://localhost:8080/tiny-vue.css']
|
||||
styles: ['/tiny-vue.css']
|
||||
},
|
||||
React: {},
|
||||
HTML: {},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.0-beta.4",
|
||||
"description": "TinyEngine enables developers to customize low-code platforms, build low-bit platforms online in real time, and support secondary development or integration of low-bit platform capabilities.",
|
||||
"homepage": "https://opentiny.design/tiny-engine",
|
||||
"keywords": [
|
||||
|
|
@ -30,13 +30,14 @@
|
|||
"author": "OpenTiny Team",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "7.18.13",
|
||||
"@babel/generator": "7.18.13",
|
||||
"@babel/parser": "7.18.13",
|
||||
"@babel/traverse": "7.18.13",
|
||||
"@babel/core": "~7.23.2",
|
||||
"@babel/generator": "~7.23.2",
|
||||
"@babel/parser": "~7.23.2",
|
||||
"@babel/traverse": "~7.23.2",
|
||||
"@opentiny/tiny-engine-canvas": "workspace:*",
|
||||
"@opentiny/tiny-engine-common": "workspace:*",
|
||||
"@opentiny/tiny-engine-controller": "workspace:*",
|
||||
"@opentiny/tiny-engine-dsl-vue": "workspace:*",
|
||||
"@opentiny/tiny-engine-http": "workspace:*",
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@opentiny/tiny-engine-plugin-block": "workspace:*",
|
||||
|
|
@ -77,37 +78,36 @@
|
|||
"@opentiny/tiny-engine-toolbar-setting": "workspace:*",
|
||||
"@opentiny/tiny-engine-utils": "workspace:*",
|
||||
"@opentiny/tiny-engine-webcomponent-core": "workspace:*",
|
||||
"@opentiny/vue": "~3.11.0",
|
||||
"@opentiny/vue-design-smb": "~3.11.0",
|
||||
"@opentiny/vue-renderless": "~3.11.0",
|
||||
"@opentiny/vue-theme": "~3.11.0",
|
||||
"@opentiny/vue": "~3.14.0",
|
||||
"@opentiny/vue-design-smb": "~3.14.0",
|
||||
"@opentiny/vue-renderless": "~3.14.0",
|
||||
"@opentiny/vue-theme": "~3.14.0",
|
||||
"@vue/babel-plugin-jsx": "1.1.1",
|
||||
"@vue/repl": "^2.9.0",
|
||||
"@vueuse/core": "^9.6.0",
|
||||
"element-resize-detector": "^1.2.4",
|
||||
"eslint-linter-browserify": "8.57.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"html2canvas": "^1.4.1",
|
||||
"jszip": "^3.10.1",
|
||||
"monaco-editor": "0.33.0",
|
||||
"prettier": "2.7.1",
|
||||
"sortablejs": "^1.14.0",
|
||||
"vue": "3.2.45",
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-draggable-next": "2.1.0",
|
||||
"vue-i18n": "9.2.2",
|
||||
"xlsx": "^0.18.5"
|
||||
"vue": "3.4.23",
|
||||
"vue-i18n": "^9.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@babel/eslint-parser": "^7.21.3",
|
||||
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
||||
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@types/node": "^18.0.0",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^1.3.2",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"assert": "^2.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild-plugin-copy": "^2.1.1",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-plugin-vue": "^8.0.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
|
|
@ -120,9 +120,11 @@
|
|||
"rollup-plugin-polyfill-node": "^0.12.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-visualizer": "^5.8.3",
|
||||
"shelljs": "^0.8.5",
|
||||
"svg-sprite-loader": "^6.0.11",
|
||||
"vite": "^4.3.7",
|
||||
"vite-plugin-monaco-editor": "^1.0.10",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vite-plugin-static-copy": "^0.16.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vue-eslint-parser": "^8.0.1"
|
||||
},
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue