forked from opentiny/tiny-engine
Compare commits
61 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 |
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
name: AI Code Review
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
review:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: anc95/ChatGPT-CodeReview@main
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
LANGUAGE: Chinese
|
||||
OPENAI_API_ENDPOINT: https://api.openai.com/v1
|
||||
MODEL: gpt-3.5-turbo
|
||||
MAX_TOKENS: 4096
|
||||
MAX_PATCH_LENGTH: 10000
|
||||
|
|
@ -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/
|
||||
```
|
||||
|
||||
## 里程碑
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-mock",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
"lint": "eslint --fix ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentiny/tiny-engine-dsl-vue": "1.0.2",
|
||||
"@opentiny/tiny-engine-dsl-vue": "^1.0.3",
|
||||
"@seald-io/nedb": "^4.0.2",
|
||||
"fs-extra": "^11.1.1",
|
||||
"glob": "^10.3.4",
|
||||
|
|
|
|||
|
|
@ -769,7 +769,7 @@
|
|||
{
|
||||
"componentName": "TinyTimeLine",
|
||||
"props": {
|
||||
"active": "2",
|
||||
"active": 2,
|
||||
"data": [
|
||||
{
|
||||
"name": "基础配置"
|
||||
|
|
@ -1525,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": [
|
||||
{
|
||||
|
|
@ -1550,7 +1550,7 @@
|
|||
{
|
||||
"componentName": "TinyCol",
|
||||
"props": {
|
||||
"span": "8"
|
||||
"span": 8
|
||||
},
|
||||
"id": "b9d051a5",
|
||||
"children": [
|
||||
|
|
@ -1563,7 +1563,7 @@
|
|||
{
|
||||
"componentName": "TinyCol",
|
||||
"props": {
|
||||
"span": "5",
|
||||
"span": 5,
|
||||
"style": "display: flex;"
|
||||
},
|
||||
"id": "02352776",
|
||||
|
|
@ -1597,7 +1597,7 @@
|
|||
{
|
||||
"componentName": "TinyCol",
|
||||
"props": {
|
||||
"span": "7"
|
||||
"span": 7
|
||||
},
|
||||
"id": "82b6c659",
|
||||
"children": [
|
||||
|
|
@ -1665,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",
|
||||
|
|
@ -1690,7 +1690,7 @@
|
|||
],
|
||||
"fileName": "createVm",
|
||||
"meta": {
|
||||
"id": 1977,
|
||||
"id": "NTJ4MjvqoVj8OVsc",
|
||||
"parentId": "0",
|
||||
"group": "staticPages",
|
||||
"occupier": {
|
||||
|
|
@ -1787,7 +1787,7 @@
|
|||
},
|
||||
{
|
||||
"componentName": "TinyPlusFrozenPage",
|
||||
"package": "@opentiny/vuee",
|
||||
"package": "@opentiny/vue",
|
||||
"exportName": "FrozenPage",
|
||||
"destructuring": true,
|
||||
"version": "3.4.1"
|
||||
|
|
@ -1925,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",
|
||||
|
|
@ -1967,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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-block-build",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"description": "translate block to webcomponent template",
|
||||
"main": "./dist/web-components.es.js",
|
||||
"scripts": {
|
||||
|
|
@ -32,9 +32,9 @@
|
|||
"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.4.15",
|
||||
"vue-i18n": "^9.9.0"
|
||||
|
|
|
|||
|
|
@ -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,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-builtin-component",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
|
|
@ -20,12 +20,14 @@
|
|||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine-canvas",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
|
@ -28,25 +28,24 @@
|
|||
"dependencies": {
|
||||
"@babel/core": "7.18.13",
|
||||
"@opentiny/tiny-engine-builtin-component": "workspace:*",
|
||||
"@opentiny/tiny-engine-common": "workspace:*",
|
||||
"@opentiny/tiny-engine-controller": "workspace:*",
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@opentiny/tiny-engine-utils": "workspace:*",
|
||||
"@opentiny/tiny-engine-webcomponent-core": "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"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,14 +27,46 @@
|
|||
</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" ref="optionRef" class="corner-mark-right" :style="fixStyle">
|
||||
<template v-if="!isModal">
|
||||
|
|
@ -68,7 +100,7 @@
|
|||
<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>
|
||||
|
|
@ -85,6 +117,7 @@ import {
|
|||
IconEyeclose
|
||||
} from '@opentiny/vue-icon'
|
||||
import {
|
||||
canvasState,
|
||||
getCurrent,
|
||||
removeNodeById,
|
||||
selectNode,
|
||||
|
|
@ -347,15 +380,14 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
const getStyleValues = (selectState, siteCanvasWidth, siteCanvasHeight) => {
|
||||
const getStyleValues = (selectState, canvasSize, labelWidth, optionWidth) => {
|
||||
const { left, top, width, height, doc } = selectState
|
||||
const labelRect = labelRef.value.getBoundingClientRect()
|
||||
const optionRect = optionRef.value.getBoundingClientRect()
|
||||
const { width: canvasWidth, height: canvasHeight } = canvasSize
|
||||
// 标签宽度和工具操作条宽度之和加上间距
|
||||
const fullRectWidth = labelRect.width + optionRect.width + OPTION_SPACE
|
||||
const fullRectWidth = labelWidth + optionWidth + OPTION_SPACE
|
||||
|
||||
// 是否 将label 标签放置到底部,判断 top 距离
|
||||
const isLabelAtBottom = top <= LABEL_HEIGHT
|
||||
const isLabelAtBottom = top < LABEL_HEIGHT
|
||||
const labelAlign = new Align({
|
||||
alignLeft: true,
|
||||
horizontalValue: 0,
|
||||
|
|
@ -364,7 +396,7 @@ export default {
|
|||
})
|
||||
|
||||
// 是否将操作栏放置到底部,判断当前选中组件底部与页面底部的距离。
|
||||
const isOptionAtBottom = siteCanvasHeight - top - height > OPTION_BAR_HEIGHT
|
||||
const isOptionAtBottom = canvasHeight - top - height >= OPTION_BAR_HEIGHT
|
||||
const optionAlign = new Align({
|
||||
alignLeft: false,
|
||||
horizontalValue: 0,
|
||||
|
|
@ -378,13 +410,13 @@ export default {
|
|||
// 选中框宽度小于标签宽度和工具操作条宽度之和加上间距
|
||||
|
||||
// 如果labe宽度大于选中框宽度,并且label右侧已经超出画布,则label对齐右侧
|
||||
const isLabelAlignRight = labelRect.width > width && left + labelRect.width + scrollBarWidth > siteCanvasWidth
|
||||
const isLabelAlignRight = labelWidth > width && left + labelWidth + scrollBarWidth > canvasWidth
|
||||
if (isLabelAlignRight) {
|
||||
labelAlign.align(positions.RIGHT)
|
||||
}
|
||||
|
||||
// 如果option宽度大于选中框宽度,并且option左侧已经超出画布,则option对齐左侧
|
||||
const isOptionAlignLeft = optionRect.width > width && left + width - optionRect.width < 0
|
||||
const isOptionAlignLeft = optionWidth > width && left + width - optionWidth < 0
|
||||
if (isOptionAlignLeft) {
|
||||
optionAlign.align(positions.LEFT)
|
||||
}
|
||||
|
|
@ -392,14 +424,14 @@ export default {
|
|||
if (isLabelAtBottom === isOptionAtBottom) {
|
||||
// 标签框和工具操作框都在顶部或者都在底部
|
||||
|
||||
if (left + fullRectWidth < siteCanvasWidth) {
|
||||
if (left + fullRectWidth < canvasWidth) {
|
||||
// 都放在左侧
|
||||
labelAlign.align(positions.LEFT)
|
||||
optionAlign.align(positions.LEFT, labelRect.width + OPTION_SPACE)
|
||||
optionAlign.align(positions.LEFT, labelWidth + OPTION_SPACE)
|
||||
} else {
|
||||
// 都放在右侧
|
||||
optionAlign.align(positions.RIGHT)
|
||||
labelAlign.align(positions.RIGHT, optionRect.width + OPTION_SPACE)
|
||||
labelAlign.align(positions.RIGHT, optionWidth + OPTION_SPACE)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -407,10 +439,10 @@ export default {
|
|||
labelAlign.align(positions.LEFT, Math.min(-left, width - fullRectWidth))
|
||||
}
|
||||
|
||||
if (left + width + scrollBarWidth > siteCanvasWidth) {
|
||||
if (left + width + scrollBarWidth > canvasWidth) {
|
||||
optionAlign.align(
|
||||
positions.RIGHT,
|
||||
Math.min(left + width + scrollBarWidth - siteCanvasWidth, width - fullRectWidth)
|
||||
Math.min(left + width + scrollBarWidth - canvasWidth, width - fullRectWidth)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -422,8 +454,7 @@ export default {
|
|||
}
|
||||
|
||||
watchPostEffect(async () => {
|
||||
let { left } = props.selectState
|
||||
const { top, width, height, doc } = props.selectState
|
||||
const { left, top, width, height, doc } = props.selectState
|
||||
|
||||
// nextTick后ref才能获取到元素。需要把监听的依赖放在await之前,否则无法监听变化
|
||||
await nextTick()
|
||||
|
|
@ -438,15 +469,17 @@ export default {
|
|||
return
|
||||
}
|
||||
|
||||
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
|
||||
const scale = useLayout().getScale()
|
||||
const canvasRect = canvasState.iframe.getBoundingClientRect()
|
||||
const { width: labelWidth } = labelRef.value.getBoundingClientRect()
|
||||
const { width: optionWidth } = optionRef.value.getBoundingClientRect()
|
||||
|
||||
left -= ((1 - scale) / 2) * siteCanvasRect.width
|
||||
|
||||
// canvas容器中,iframe以及iframe之外的元素clientRect的尺寸都是缩放过的,除以scale得到原始大小
|
||||
const { labelStyleValue, optionStyleValue } = getStyleValues(
|
||||
{ left, top, width, height, doc },
|
||||
siteCanvasRect.width * scale,
|
||||
siteCanvasRect.height
|
||||
{ width: canvasRect.width / scale, height: canvasRect.height / scale },
|
||||
labelWidth / scale,
|
||||
optionWidth / scale
|
||||
)
|
||||
|
||||
labelStyle.value = labelStyleValue
|
||||
|
|
@ -540,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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -178,8 +180,8 @@ export default {
|
|||
}
|
||||
}
|
||||
// 设置弹窗
|
||||
const settingModle = () => {
|
||||
showSettingModle.value = true
|
||||
const settingModel = () => {
|
||||
showSettingModel.value = true
|
||||
}
|
||||
|
||||
const updateI18n = (message) => {
|
||||
|
|
@ -236,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,13 +17,12 @@ 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
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -98,6 +99,7 @@ const initialLineState = {
|
|||
width: 0,
|
||||
left: 0,
|
||||
position: '',
|
||||
forbidden: false,
|
||||
id: '',
|
||||
config: null,
|
||||
doc: null
|
||||
|
|
@ -320,19 +322,19 @@ export const scrollToNode = (element) => {
|
|||
if (element) {
|
||||
const container = getDocument().documentElement
|
||||
const { clientWidth, clientHeight } = container
|
||||
const { x, y, width, height } = element.getBoundingClientRect()
|
||||
const { left, right, top, bottom, width, height } = element.getBoundingClientRect()
|
||||
const option = {}
|
||||
|
||||
if (x < 0) {
|
||||
option.left = container.scrollLeft + x - SCROLL_MARGIN
|
||||
} else if (x > clientWidth) {
|
||||
option.left = x + width - clientWidth + SCROLL_MARGIN
|
||||
if (right < 0) {
|
||||
option.left = container.scrollLeft + left - SCROLL_MARGIN
|
||||
} else if (left > clientWidth) {
|
||||
option.left = container.scrollLeft + left - clientWidth + width + SCROLL_MARGIN
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
option.top = container.scrollTop + y - SCROLL_MARGIN
|
||||
} else if (y > clientHeight) {
|
||||
option.top = y + height - clientHeight + 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') {
|
||||
|
|
@ -346,16 +348,13 @@ const setSelectRect = (element) => {
|
|||
element = element || getDocument().body
|
||||
|
||||
const { left, height, top, width } = getRect(element)
|
||||
const { x, y } = getOffset(element)
|
||||
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
|
||||
const componentName = getCurrent().schema?.componentName || ''
|
||||
const scale = useLayout().getScale()
|
||||
clearHover()
|
||||
Object.assign(selectState, {
|
||||
width: width * scale,
|
||||
height: height * scale,
|
||||
top: top * scale + y - siteCanvasRect.y,
|
||||
left: left * scale + x - siteCanvasRect.x,
|
||||
width,
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
componentName,
|
||||
doc: getDocument()
|
||||
})
|
||||
|
|
@ -416,6 +415,23 @@ export const allowInsert = (configure = hoverState.configure || {}, data = dragS
|
|||
return flag
|
||||
}
|
||||
|
||||
const isAncestor = (ancestor, descendant) => {
|
||||
const ancestorId = typeof ancestor === 'string' ? ancestor : ancestor.id
|
||||
let descendantId = typeof descendant === 'string' ? descendant : descendant.id
|
||||
|
||||
while (descendantId) {
|
||||
const { parent } = getNode(descendantId, true) || {}
|
||||
|
||||
if (parent.id === ancestorId) {
|
||||
return true
|
||||
}
|
||||
|
||||
descendantId = parent.id
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 获取位置信息,返回状态
|
||||
const lineAbs = 20
|
||||
const getPosLine = (rect, configure) => {
|
||||
|
|
@ -423,6 +439,7 @@ const getPosLine = (rect, configure) => {
|
|||
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
|
||||
|
|
@ -433,12 +450,21 @@ const getPosLine = (rect, configure) => {
|
|||
} else if (mousePos.x > rect.right - xAbs) {
|
||||
type = POSITION.RIGHT
|
||||
} else if (configure.isContainer) {
|
||||
type = allowInsert() ? POSITION.IN : POSITION.FORBID
|
||||
type = POSITION.IN
|
||||
if (!allowInsert()) {
|
||||
forbidden = true
|
||||
}
|
||||
} else {
|
||||
type = POSITION.BOTTOM
|
||||
}
|
||||
|
||||
return { type }
|
||||
// 如果被拖拽的节点不是新增的,并且是放置的节点的祖先节点,则禁止插入
|
||||
const draggedId = dragState.data?.id
|
||||
if (draggedId && isAncestor(draggedId, lineState.id)) {
|
||||
forbidden = true
|
||||
}
|
||||
|
||||
return { type, forbidden }
|
||||
}
|
||||
|
||||
const isBodyEl = (element) => element.nodeName === 'BODY'
|
||||
|
|
@ -452,9 +478,6 @@ const setHoverRect = (element, data) => {
|
|||
const configure = getConfigure(componentName)
|
||||
const rect = getRect(element)
|
||||
const { left, height, top, width } = rect
|
||||
const { x, y } = getOffset(element)
|
||||
const siteCanvasRect = document.querySelector('.site-canvas').getBoundingClientRect()
|
||||
const scale = useLayout().getScale()
|
||||
|
||||
hoverState.configure = configure
|
||||
|
||||
|
|
@ -483,21 +506,24 @@ const setHoverRect = (element, data) => {
|
|||
if (childEle) {
|
||||
const childRect = getRect(childEle)
|
||||
const { left, height, top, width } = childRect
|
||||
const { x, y } = getOffset(childEle)
|
||||
const posLine = getPosLine(childRect, lineState.configure)
|
||||
Object.assign(lineState, {
|
||||
width: width * scale,
|
||||
height: height * scale,
|
||||
top: top * scale + y - siteCanvasRect.y,
|
||||
left: left * scale + x - siteCanvasRect.x,
|
||||
position: canvasState.type === 'absolute' || getPosLine(childRect, lineState.configure).type
|
||||
width,
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
position: canvasState.type === 'absolute' || posLine.type,
|
||||
forbidden: posLine.forbidden
|
||||
})
|
||||
} else {
|
||||
const posLine = getPosLine(rect, configure)
|
||||
Object.assign(lineState, {
|
||||
width: width * scale,
|
||||
height: height * scale,
|
||||
top: top * scale + y - siteCanvasRect.y,
|
||||
left: left * scale + x - siteCanvasRect.x,
|
||||
position: canvasState.type === 'absolute' || getPosLine(rect, configure).type
|
||||
width,
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
position: canvasState.type === 'absolute' || posLine.type,
|
||||
forbidden: posLine.forbidden
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -506,10 +532,10 @@ const setHoverRect = (element, data) => {
|
|||
|
||||
// 设置元素hover状态
|
||||
Object.assign(hoverState, {
|
||||
width: width * scale,
|
||||
height: height * scale,
|
||||
top: top * scale + y - siteCanvasRect.y,
|
||||
left: left * scale + x - siteCanvasRect.x,
|
||||
width,
|
||||
height,
|
||||
top,
|
||||
left,
|
||||
componentName
|
||||
})
|
||||
return undefined
|
||||
|
|
@ -670,13 +696,12 @@ export const copyNode = (id) => {
|
|||
|
||||
export const onMouseUp = () => {
|
||||
const { draging, data } = dragState
|
||||
const { position } = lineState
|
||||
const { position, forbidden } = lineState
|
||||
const absolute = canvasState.type === 'absolute'
|
||||
const sourceId = data?.id
|
||||
const lineId = lineState.id
|
||||
const allowInsert = position !== POSITION.FORBID
|
||||
|
||||
if (draging && allowInsert) {
|
||||
if (draging && !forbidden) {
|
||||
const { parent, node } = getNode(lineId, true) || {} // target
|
||||
const targetNode = { parent, node, data: toRaw(data) }
|
||||
|
||||
|
|
@ -823,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()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -424,5 +424,3 @@ export const api = {
|
|||
setDataSourceMap,
|
||||
setGlobalState
|
||||
}
|
||||
|
||||
window.api = api
|
||||
|
|
|
|||
|
|
@ -598,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
|
||||
|
|
@ -617,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)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -628,19 +646,9 @@ 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'
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
@ -130,7 +129,7 @@ export default {
|
|||
})
|
||||
|
||||
watchEffect(() => {
|
||||
state.bindLifeCycles = props.bindLifeCycles || getSchema()?.lifeCycles || {}
|
||||
state.bindLifeCycles = props.bindLifeCycles || useCanvas().canvasApi.value?.getSchema()?.lifeCycles || {}
|
||||
})
|
||||
|
||||
const searchLifeCyclesList = (value) => {
|
||||
|
|
@ -142,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) {
|
||||
|
|
@ -165,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 }' : ''}) {} `
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -70,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: {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
.toolbar {
|
||||
.editor-container {
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
z-index: 3000 !important;
|
||||
.buttons {
|
||||
color: var(--ti-lowcode-component-svg-button-color);
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: var(--ti-lowcode-component-svg-button-hover-color);
|
||||
}
|
||||
}
|
||||
&._full {
|
||||
position: fixed;
|
||||
top: var(--base-top-panel-height);
|
||||
z-index: 1;
|
||||
padding-right: 15px;
|
||||
right: var(--base-left-panel-width);
|
||||
}
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
.iniline {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.fullscreen {
|
||||
|
||||
.editor-container-full {
|
||||
position: fixed;
|
||||
top: var(--base-top-panel-height);
|
||||
bottom: 0;
|
||||
left: calc(var(--base-nav-panel-width) + 1px);
|
||||
left: calc(var(--base-nav-panel-width) + var(--base-left-panel-width));
|
||||
right: var(--base-left-panel-width);
|
||||
z-index: 2500;
|
||||
z-index: 10;
|
||||
padding: 10px 16px 16px 16px;
|
||||
background-color: var(--ti-lowcode-common-component-bg);
|
||||
height: auto !important;
|
||||
}
|
||||
.public-icon {
|
||||
font-size: 18px;
|
||||
margin-left: 10px;
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
margin-bottom: 4px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
color: var(--ti-lowcode-component-svg-button-color);
|
||||
cursor: pointer;
|
||||
:hover {
|
||||
color: var(--ti-lowcode-component-svg-button-hover-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
<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"
|
||||
|
|
@ -37,7 +44,7 @@
|
|||
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: {
|
||||
|
|
|
|||
|
|
@ -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.1",
|
||||
"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,31 +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-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": {
|
||||
"vue": "^3.4.15",
|
||||
"vue-i18n": "^9.9.0"
|
||||
"@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: {
|
||||
|
|
|
|||
|
|
@ -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.*?\(/
|
||||
|
||||
|
|
@ -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',
|
||||
|
|
@ -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.2",
|
||||
"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,21 +31,29 @@
|
|||
"license": "MIT",
|
||||
"homepage": "https://opentiny.design/tiny-engine",
|
||||
"dependencies": {
|
||||
"@babel/generator": "~7.23.2",
|
||||
"@babel/parser": "~7.23.2",
|
||||
"@babel/traverse": "~7.23.2",
|
||||
"@opentiny/tiny-engine-builtin-component": "workspace:*",
|
||||
"@opentiny/tiny-engine-canvas": "workspace:*",
|
||||
"@opentiny/tiny-engine-common": "workspace:*",
|
||||
"@opentiny/tiny-engine-http": "workspace:*",
|
||||
"@opentiny/tiny-engine-i18n-host": "workspace:*",
|
||||
"@opentiny/tiny-engine-utils": "workspace:*",
|
||||
"@opentiny/vue": "~3.10.0",
|
||||
"@opentiny/vue-renderless": "~3.10.0",
|
||||
"@vue/shared": "^3.3.4"
|
||||
"@vue/shared": "^3.3.4",
|
||||
"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": {
|
||||
"vue": "^3.4.15"
|
||||
"@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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,7 +11,6 @@
|
|||
*/
|
||||
|
||||
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'
|
||||
|
|
@ -192,6 +191,7 @@ const setProp = (name, value, type) => {
|
|||
}
|
||||
|
||||
// 没有父级,或者不在节点上面,要更新内容。就用setState
|
||||
const { getNode, setState, updateRect } = useCanvas().canvasApi.value || {}
|
||||
getNode(properties.schema.id, true)?.parent || setState(useCanvas().getPageSchema().state)
|
||||
propsUpdateKey.value++
|
||||
|
||||
|
|
|
|||
|
|
@ -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,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 |
|
|
@ -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="%VITE_CDN_DOMAIN%/@opentiny/vue-theme@3.11/index.css" rel="stylesheet" />
|
||||
<style type="text/css">
|
||||
.loading-warp {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@opentiny/tiny-engine",
|
||||
"version": "1.0.0-beta.3",
|
||||
"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,21 +78,22 @@
|
|||
"@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.4.15",
|
||||
"vue": "3.4.23",
|
||||
"vue-i18n": "^9.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -101,7 +103,7 @@
|
|||
"@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",
|
||||
|
|
@ -118,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"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@
|
|||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": false,
|
||||
"isContainer": true,
|
||||
"isModal": false,
|
||||
"isPopper": false,
|
||||
"nestingRule": {
|
||||
|
|
@ -632,7 +632,7 @@
|
|||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": false,
|
||||
"isContainer": true,
|
||||
"isModal": false,
|
||||
"isPopper": false,
|
||||
"nestingRule": {
|
||||
|
|
@ -1089,7 +1089,7 @@
|
|||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": false,
|
||||
"isContainer": true,
|
||||
"isModal": false,
|
||||
"isPopper": false,
|
||||
"nestingRule": {
|
||||
|
|
@ -1805,7 +1805,9 @@
|
|||
},
|
||||
"widget": {
|
||||
"component": "MetaCodeEditor",
|
||||
"props": {}
|
||||
"props": {
|
||||
"dataType": "JSFunction"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -4137,6 +4139,9 @@
|
|||
"contentMenu": {
|
||||
"actions": []
|
||||
}
|
||||
},
|
||||
"configure": {
|
||||
"isContainer": true
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -4495,6 +4500,9 @@
|
|||
"contentMenu": {
|
||||
"actions": []
|
||||
}
|
||||
},
|
||||
"configure": {
|
||||
"isContainer": true
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -5977,7 +5985,7 @@
|
|||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": true,
|
||||
"isContainer": false,
|
||||
"isModal": false,
|
||||
"nestingRule": {
|
||||
"childWhitelist": "",
|
||||
|
|
@ -6392,7 +6400,7 @@
|
|||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": true,
|
||||
"isContainer": false,
|
||||
"isModal": false,
|
||||
"nestingRule": {
|
||||
"childWhitelist": "",
|
||||
|
|
@ -8181,7 +8189,7 @@
|
|||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": true,
|
||||
"isContainer": false,
|
||||
"isModal": false,
|
||||
"nestingRule": {
|
||||
"childWhitelist": "",
|
||||
|
|
@ -8948,7 +8956,9 @@
|
|||
"cols": 12,
|
||||
"widget": {
|
||||
"component": "MetaCodeEditor",
|
||||
"props": {}
|
||||
"props": {
|
||||
"language": "json"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"zh_CN": ""
|
||||
|
|
@ -8994,7 +9004,7 @@
|
|||
"loop": true,
|
||||
"condition": true,
|
||||
"styles": true,
|
||||
"isContainer": true,
|
||||
"isContainer": false,
|
||||
"clickCapture": false,
|
||||
"isModal": false,
|
||||
"nestingRule": {
|
||||
|
|
@ -12134,6 +12144,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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"blocks": [],
|
||||
|
|
@ -13152,6 +14023,38 @@
|
|||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"zh_CN": "日期选择"
|
||||
},
|
||||
"icon": "datepick",
|
||||
"screenshot": "",
|
||||
"snippetName": "TinyDatePicker",
|
||||
"schema": {
|
||||
"componentName": "TinyDatePicker",
|
||||
"props": {
|
||||
"placeholder": "请输入",
|
||||
"modelValue": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": {
|
||||
"zh_CN": "数字输入框"
|
||||
},
|
||||
"icon": "numeric",
|
||||
"screenshot": "",
|
||||
"snippetName": "TinyNumeric",
|
||||
"schema": {
|
||||
"componentName": "TinyNumeric",
|
||||
"props": {
|
||||
"allow-empty": true,
|
||||
"placeholder": "请输入",
|
||||
"controlsPosition": "right",
|
||||
"step": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
// importScripts 不支持 esm, 此处使用 umd, 对外暴露的变量名:linter,需要填写openTiny的cdn地址
|
||||
importScripts('')
|
||||
|
||||
// 根据公司的编码规范内置了 config/rules, 可以进一步定制
|
||||
const config = {
|
||||
...self.linter.config,
|
||||
rules: {
|
||||
...self.linter.config.rules,
|
||||
// JS 面板中,仅定义 function,但可能不使用该方法
|
||||
'no-unused-vars': 'off',
|
||||
'no-alert': 'off',
|
||||
'no-console': 'off'
|
||||
},
|
||||
settings: {}
|
||||
}
|
||||
|
||||
// 错误的等级,ESLint 与 monaco 的存在差异,做一层映射
|
||||
const severityMap = {
|
||||
2: 'Error',
|
||||
1: 'Warning'
|
||||
}
|
||||
|
||||
self.addEventListener('message', (event) => {
|
||||
const { code, version } = event.data
|
||||
|
||||
const ruleDefines = self.linter.esLinter.getRules()
|
||||
const errs = self.linter.esLinter.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 })
|
||||
})
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
import path from 'node:path'
|
||||
import { readJsonSync } from 'fs-extra'
|
||||
import { installPackageTemporary } from '../vite-plugins/installPackageTemporary'
|
||||
import { configServerAddProxy } from '../vite-plugins/configureServerAddProxy'
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
import {
|
||||
getCdnPathNpmInfoForSingleFile,
|
||||
getPackageNeedToInstallAndFilesUsingSameVersion,
|
||||
dedupeCopyFiles,
|
||||
copyfileToDynamicSrcMapper
|
||||
} from './locateCdnNpmInfo'
|
||||
|
||||
export function extraBundleCdnLink(filename, originCdnPrefix) {
|
||||
const result = []
|
||||
const bundle = readJsonSync(filename)
|
||||
bundle.data?.materials?.components?.forEach((component) => {
|
||||
if (component.npm) {
|
||||
const possibleUrl = [component.npm.script, component.npm.css]
|
||||
possibleUrl.forEach((url) => {
|
||||
if (url?.startsWith(originCdnPrefix) && !result.includes(url)) {
|
||||
result.push(url)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
export function replaceBundleCdnLink(bundle, fileMap) {
|
||||
bundle.data?.materials?.components?.forEach((component) => {
|
||||
if (component.npm) {
|
||||
const possibleUrl = ['script', 'css']
|
||||
possibleUrl.forEach((key) => {
|
||||
const matchRule = fileMap.find((rule) => component.npm[key] === rule.originUrl)
|
||||
if (matchRule) {
|
||||
component.npm[key] = matchRule.newUrl
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function copyBundleDeps({
|
||||
bundleFile,
|
||||
targetBundleFile,
|
||||
originCdnPrefix,
|
||||
base,
|
||||
dir = 'material-static',
|
||||
bundleTempDir = 'bundle-deps/material-static'
|
||||
}) {
|
||||
const cdnFiles = extraBundleCdnLink(bundleFile, originCdnPrefix).map((url) =>
|
||||
getCdnPathNpmInfoForSingleFile(url, originCdnPrefix, base, dir, false, bundleTempDir)
|
||||
)
|
||||
const { packages: packageNeedToInstall, files } = getPackageNeedToInstallAndFilesUsingSameVersion(cdnFiles)
|
||||
|
||||
const plugin = (isDev) => {
|
||||
return [
|
||||
...(isDev ? configServerAddProxy(targetBundleFile, targetBundleFile.replace(/\.([^.]+?$)/, '-local.$1')) : []),
|
||||
...installPackageTemporary(packageNeedToInstall, bundleTempDir),
|
||||
...viteStaticCopy({
|
||||
targets: [
|
||||
...dedupeCopyFiles(files).map(copyfileToDynamicSrcMapper),
|
||||
{
|
||||
src: bundleFile,
|
||||
dest: path.dirname(targetBundleFile),
|
||||
transform: (content) => {
|
||||
const json = JSON.parse(content)
|
||||
replaceBundleCdnLink(json, files)
|
||||
return JSON.stringify(json, null, 2)
|
||||
},
|
||||
rename: (filename, fileExtension) =>
|
||||
isDev ? `${filename}-local.${fileExtension}` : path.basename(targetBundleFile),
|
||||
overwrite: true // 覆盖public的
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
||||
return {
|
||||
plugin
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
import {
|
||||
getPackageNeedToInstallAndFilesUsingSameVersion,
|
||||
copyfileToDynamicSrcMapper,
|
||||
dedupeCopyFiles,
|
||||
getCdnPathNpmInfoForPackage,
|
||||
getCdnPathNpmInfoForSingleFile
|
||||
} from './locateCdnNpmInfo'
|
||||
import { importmapPlugin } from '../externalDeps'
|
||||
import { installPackageTemporary } from '../vite-plugins/installPackageTemporary'
|
||||
|
||||
export const copyLocalImportMap = ({
|
||||
importMap,
|
||||
styleUrls,
|
||||
originCdnPrefix,
|
||||
base,
|
||||
dir = 'import-map-static',
|
||||
bundleTempDir = 'bundle-deps/design-core-import-map',
|
||||
packageCopy = [] // 值为importMap的imports的左值 (非右值的地址上的包名)
|
||||
}) => {
|
||||
const importMapFiles = Object.entries(importMap.imports)
|
||||
.filter(([_libKey, libPath]) => libPath.startsWith(originCdnPrefix))
|
||||
.map(([libKey, libPath]) => {
|
||||
if (packageCopy.includes(libKey)) {
|
||||
return getCdnPathNpmInfoForPackage(libPath, originCdnPrefix, base, dir, true, bundleTempDir)
|
||||
}
|
||||
return getCdnPathNpmInfoForSingleFile(libPath, originCdnPrefix, base, dir, false, bundleTempDir)
|
||||
})
|
||||
const styleFiles = styleUrls
|
||||
.filter((styleUrl) => styleUrl.startsWith(originCdnPrefix))
|
||||
.map((url) => getCdnPathNpmInfoForSingleFile(url, originCdnPrefix, base, dir, false), bundleTempDir)
|
||||
|
||||
const { packages: packageNeedToInstall, files } = getPackageNeedToInstallAndFilesUsingSameVersion(
|
||||
importMapFiles.concat(styleFiles)
|
||||
)
|
||||
|
||||
return [
|
||||
...installPackageTemporary(packageNeedToInstall, bundleTempDir),
|
||||
...viteStaticCopy({
|
||||
targets: dedupeCopyFiles(files).map(copyfileToDynamicSrcMapper)
|
||||
}),
|
||||
{
|
||||
config(config, { command }) {
|
||||
// 处理devAlias带CDN域名, 另外需要使得本地vue和importMap的vue是同一个实例
|
||||
if (command === 'serve') {
|
||||
config.resolve.alias = [
|
||||
...config.resolve.alias,
|
||||
{
|
||||
find: /^vue$/,
|
||||
replacement: `http://localhost:${config.server.port || 8080}/${
|
||||
files.find(({ originUrl }) => importMap.imports.vue === originUrl).newUrl
|
||||
}` // 实际端口号需要更具本地启动修改
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
importmapPlugin(
|
||||
{
|
||||
imports: Object.fromEntries(
|
||||
Object.entries(importMap.imports).map(([k, v]) => [k, files.find((f) => f.originUrl === v)?.newUrl ?? v])
|
||||
)
|
||||
},
|
||||
styleUrls.map((url) => styleFiles.find((f) => f.originUrl === url).newUrl ?? url)
|
||||
)
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
import path from 'node:path'
|
||||
import { readJsonSync } from 'fs-extra'
|
||||
import {
|
||||
getPackageNeedToInstallAndFilesUsingSameVersion,
|
||||
copyfileToDynamicSrcMapper,
|
||||
dedupeCopyFiles,
|
||||
getCdnPathNpmInfoForPackage,
|
||||
getCdnPathNpmInfoForSingleFile
|
||||
} from './locateCdnNpmInfo'
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
import { installPackageTemporary } from '../vite-plugins/installPackageTemporary'
|
||||
|
||||
export function extraPreviewImport(filename, originCdnPrefix) {
|
||||
const result = []
|
||||
const importMap = readJsonSync(filename)
|
||||
Object.entries(importMap.imports)?.forEach(([_key, location]) => {
|
||||
const url = location.replace('${VITE_CDN_DOMAIN}', originCdnPrefix).replace('${opentinyVueVersion}', '~3.14')
|
||||
if (url?.startsWith(originCdnPrefix) && !result.includes(url)) {
|
||||
result.push(url)
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
export function replacePreviewImport(importMap, fileMap, originCdnPrefix) {
|
||||
return {
|
||||
imports: Object.fromEntries(
|
||||
Object.entries(importMap.imports)?.map(([key, location]) => {
|
||||
// 这里的替换占位符规则等同于packages/design-core/src/preview/src/preview/importMap.js, 两边修改需要同步
|
||||
const url = location.replace('${VITE_CDN_DOMAIN}', originCdnPrefix).replace('${opentinyVueVersion}', '~3.14')
|
||||
const matchRule = fileMap.find((rule) => url === rule.originUrl)
|
||||
if (matchRule) {
|
||||
return [key, matchRule.newUrl]
|
||||
}
|
||||
return [key, location]
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function extraPreviewImportFile(filename, targetFileName, originCdnPrefix) {
|
||||
return (fileMap) => [
|
||||
{
|
||||
src: filename,
|
||||
dest: path.dirname(targetFileName),
|
||||
transform: (content) => {
|
||||
return JSON.stringify(replacePreviewImport(JSON.parse(content), fileMap, originCdnPrefix), null, 2)
|
||||
},
|
||||
rename: path.basename(targetFileName)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export function copyPreviewImportMap({
|
||||
importMapJson,
|
||||
targetImportMapJson,
|
||||
originCdnPrefix,
|
||||
base,
|
||||
dir = 'preview-import-map-static',
|
||||
bundleTempDir = 'bundle-deps/preview-import-map',
|
||||
packageCopyLib = [] // 值为cdn地址上的包名
|
||||
}) {
|
||||
const cdnFiles = extraPreviewImport(importMapJson, originCdnPrefix).map((url) => {
|
||||
const { packageName } = url.match(
|
||||
new RegExp(`^${originCdnPrefix}/?(?<packageName>.+?)@(?<versionDemand>[^/]+)(?<filePathInPackage>.*?)$`)
|
||||
).groups
|
||||
if (packageCopyLib.includes(packageName)) {
|
||||
return getCdnPathNpmInfoForPackage(url, originCdnPrefix, base, dir, true, bundleTempDir)
|
||||
}
|
||||
return getCdnPathNpmInfoForSingleFile(url, originCdnPrefix, base, dir, false, bundleTempDir)
|
||||
})
|
||||
const { packages: packageNeedToInstall, files } = getPackageNeedToInstallAndFilesUsingSameVersion(cdnFiles)
|
||||
return [
|
||||
...installPackageTemporary(packageNeedToInstall, bundleTempDir),
|
||||
...viteStaticCopy({
|
||||
targets: [
|
||||
...dedupeCopyFiles(files).map(copyfileToDynamicSrcMapper),
|
||||
...extraPreviewImportFile(importMapJson, targetImportMapJson, originCdnPrefix)(files)
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export * from './copyBundleDeps'
|
||||
export * from './copyImportMap'
|
||||
export * from './copyPreviewImportMap'
|
||||
export * from './utils'
|
||||
export * from './locateCdnNpmInfo'
|
||||
export * from './replaceImportPath.mjs'
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
import fg from 'fast-glob'
|
||||
import { normalizePath } from 'vite'
|
||||
import { readJsonSync } from 'fs-extra'
|
||||
import { babelReplaceImportPathWithCertainFileName } from './replaceImportPath.mjs'
|
||||
|
||||
function transform(content, filename) {
|
||||
if (filename.endsWith('.js')) {
|
||||
const result = babelReplaceImportPathWithCertainFileName(content, filename, console)
|
||||
return result.code || content
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
function onlyFiles(globString) {
|
||||
// viteStaticCopy 自带的glob匹配无法过滤目录, 手动过滤目录作为数组传入
|
||||
return fg.sync(globString + '/**/*', { onlyFiles: true }).map((p) => normalizePath(p))
|
||||
}
|
||||
|
||||
function replaceTailSlash(pathStr) {
|
||||
// 替换尾部的 / 可以把目录当文件复制
|
||||
return pathStr.replace(/\/$/, '')
|
||||
}
|
||||
|
||||
export function copyfileToDynamicSrcMapper({ src, dest, transform, rename, folder, ...rest }) {
|
||||
// viteStaticCopy 自带的glob匹配无法过滤目录, 手动过滤目录作为数组传入,但是不存在的包需要推迟glob的时机到安装文件后
|
||||
return {
|
||||
...rest,
|
||||
get src() {
|
||||
// 注意对象不能被解构,否则getter无法动态计算
|
||||
return src || onlyFiles(folder)
|
||||
},
|
||||
dest,
|
||||
transform,
|
||||
rename
|
||||
}
|
||||
}
|
||||
|
||||
// 生成复制单个文件所需要的信息
|
||||
export function getCdnPathNpmInfoForSingleFile(
|
||||
url, // cdn托管的npm文件地址数组
|
||||
originCdnPrefix, // cdn的前缀
|
||||
base, // build构建的base(BASE_URL)参数
|
||||
dir, // 复制到目标的文件目录
|
||||
transformIContent = false, // 是否需要转换内容, 如果传入url实际为目录则不会转会
|
||||
tempDir = 'bundle-deps' // 新安装包的安装目录
|
||||
) {
|
||||
const baseSlash = base.endsWith('/') ? '' : '/'
|
||||
const { packageName, versionDemand, filePathInPackage } = url.match(
|
||||
new RegExp(`^${originCdnPrefix}/?(?<packageName>.+?)@(?<versionDemand>[^/]+)(?<filePathInPackage>.*?)$`)
|
||||
).groups
|
||||
let version = versionDemand
|
||||
let isFolder = filePathInPackage.endsWith('/')
|
||||
let src = replaceTailSlash(`node_modules/${packageName}${filePathInPackage}`)
|
||||
const sourceExist = fs.existsSync(path.resolve(src))
|
||||
let sourceExistExternal = false
|
||||
if (sourceExist) {
|
||||
const stat = fs.statSync(path.resolve(src))
|
||||
if (stat.isDirectory()) {
|
||||
isFolder = true
|
||||
}
|
||||
const content = readJsonSync(`node_modules/${packageName}/package.json`)
|
||||
version = content.version // 忽略请求的包版本,使用本地包版本号
|
||||
} else {
|
||||
src = tempDir + '/' + src
|
||||
sourceExistExternal = fs.existsSync(path.resolve(src)) // 安装过的不重新安装, 当且仅当所有包都安装过
|
||||
if (sourceExistExternal) {
|
||||
const packageJson = readJsonSync(`${tempDir}/node_modules/${packageName}/package.json`)
|
||||
version = packageJson.version // 如果重新安装这个版本号还需要刷新
|
||||
}
|
||||
}
|
||||
const updateVersion = (version) => {
|
||||
const destPackageDir = `${dir}/${packageName}@${version}`
|
||||
const destFullPath = `${destPackageDir}${filePathInPackage}`
|
||||
const destFullPathWithoutTailSlash = replaceTailSlash(destFullPath)
|
||||
const dest = path.dirname(destFullPathWithoutTailSlash)
|
||||
const rename = dest.startsWith(destPackageDir) ? null : path.basename(destFullPathWithoutTailSlash) // 版本号被截断,需要补充回去
|
||||
return {
|
||||
version,
|
||||
newUrl: `${base}${baseSlash}${destFullPath}`,
|
||||
dest,
|
||||
rename
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
originUrl: url,
|
||||
// newUrl, // overwrite by updateVersion(version)
|
||||
src,
|
||||
// dest, // overwrite by updateVersion(version)
|
||||
packageName,
|
||||
// version, // overwrite by updateVersion(version)
|
||||
versionDemand,
|
||||
filePathInPackage,
|
||||
sourceExist,
|
||||
sourceExistExternal,
|
||||
...updateVersion(version),
|
||||
updateVersion,
|
||||
transform: transformIContent && !isFolder ? transform : null
|
||||
}
|
||||
}
|
||||
|
||||
export function getCdnPathNpmInfoForPackage(
|
||||
url, // cdn托管的npm文件地址数组
|
||||
originCdnPrefix, // cdn的前缀
|
||||
base, // build构建的base(BASE_URL)参数
|
||||
dir, // 复制到目标的文件目录
|
||||
transformIContent = false, // 是否需要转换内容
|
||||
tempDir = 'bundle-deps' // 新安装包的安装目录
|
||||
) {
|
||||
const baseSlash = base.endsWith('/') ? '' : '/'
|
||||
const { packageName, versionDemand, filePathInPackage } = url.match(
|
||||
new RegExp(`^${originCdnPrefix}/?(?<packageName>.+?)@(?<versionDemand>[^/]+)(?<filePathInPackage>.*?)$`)
|
||||
).groups
|
||||
let version = versionDemand
|
||||
let src = `node_modules/${packageName}`
|
||||
const sourceExist = fs.existsSync(path.resolve(src))
|
||||
let sourceExistExternal = false
|
||||
if (sourceExist) {
|
||||
const content = readJsonSync(`${src}/package.json`)
|
||||
version = content.version // 忽略请求的包版本,使用本地包版本号
|
||||
} else {
|
||||
src = tempDir + '/' + src
|
||||
sourceExistExternal = fs.existsSync(path.resolve(src)) // 安装过的不重新安装, 当且仅当所有包都安装过
|
||||
if (sourceExistExternal) {
|
||||
const packageJson = readJsonSync(`${src}/package.json`)
|
||||
version = packageJson.version // 如果重新安装这个版本号还需要刷新
|
||||
}
|
||||
}
|
||||
const updateVersion = (version) => {
|
||||
const packageDir = `${dir}/${packageName}@${version}`
|
||||
const packageDirBasename = path.basename(packageDir)
|
||||
return {
|
||||
version,
|
||||
newUrl: `${base}${baseSlash}${dir}/${packageName}@${version}${filePathInPackage}`,
|
||||
dest: path.dirname(packageDir),
|
||||
rename: (_filename, _fileExtension, fullPath) => `${packageDirBasename}${fullPath.replace(src, '')}`
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
folder: src,
|
||||
originUrl: url,
|
||||
// newUrl, // overwrite by updateVersion(version)
|
||||
src: sourceExist || sourceExistExternal ? onlyFiles(src) : null,
|
||||
// dest, // overwrite by updateVersion(version)
|
||||
packageName,
|
||||
// version, // overwrite by updateVersion(version)
|
||||
versionDemand,
|
||||
filePathInPackage,
|
||||
sourceExist,
|
||||
sourceExistExternal,
|
||||
...updateVersion(version),
|
||||
updateVersion,
|
||||
transform: transformIContent ? transform : null
|
||||
}
|
||||
}
|
||||
|
||||
export function dedupeCopyFiles(files) {
|
||||
return files.reduce((acc, cur) => {
|
||||
//去重,分别处理字符串和数组
|
||||
if (
|
||||
(cur.folder && !acc.some((item) => !!item.folder && item.folder === cur.folder && item.dest === cur.dest)) || // 文件夹拷贝
|
||||
(typeof cur.src === 'string' && !acc.some((item) => item.src === cur.src && item.dest === cur.dest)) // 文件拷贝
|
||||
) {
|
||||
acc.push(cur)
|
||||
}
|
||||
return acc
|
||||
}, [])
|
||||
}
|
||||
|
||||
export function getPackageNeedToInstallAndFilesUsingSameVersion(files) {
|
||||
const packageNeedToInstall = files
|
||||
.filter((item) => !item.sourceExist)
|
||||
.map(({ packageName, version, sourceExistExternal: exist }) => ({ packageName, version, exist }))
|
||||
.reduce((acc, cur) => {
|
||||
// 同个包避免多个版本只保留一个版本
|
||||
if (!acc.some(({ packageName }) => cur.packageName === packageName)) {
|
||||
acc.push(cur)
|
||||
}
|
||||
return acc
|
||||
}, [])
|
||||
let newFiles = null
|
||||
if (packageNeedToInstall.length) {
|
||||
// 确保同个包多个版本只能从一个版本引用文件
|
||||
newFiles = files.map((file) => {
|
||||
const samePackageDifferentVersion = packageNeedToInstall.find(
|
||||
({ packageName, version }) => packageName === file.packageName && version !== file.version
|
||||
)
|
||||
if (samePackageDifferentVersion) {
|
||||
return {
|
||||
...file,
|
||||
...file.updateVersion(samePackageDifferentVersion.version)
|
||||
}
|
||||
}
|
||||
return file
|
||||
})
|
||||
}
|
||||
return {
|
||||
packages: packageNeedToInstall,
|
||||
files: newFiles ?? files
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { parse } from '@babel/core'
|
||||
import traversePkg from '@babel/traverse'
|
||||
import generatePkg from '@babel/generator'
|
||||
const traverse = traversePkg.default
|
||||
const generate = generatePkg.default
|
||||
|
||||
export function relativePathPattern(relativePath) {
|
||||
return './' + (path.sep === '/' ? relativePath : relativePath.replace(/\\/g, '/'))
|
||||
}
|
||||
|
||||
export function resolvePath(importPath, currentFilePath) {
|
||||
if (['js', 'mjs'].some(suffix =>importPath.endsWith(suffix))) { // 文件名已经带有.js,.mjs后缀
|
||||
return importPath
|
||||
}
|
||||
const parentPath = path.resolve(currentFilePath, '../')
|
||||
const filePrefix = path.resolve(parentPath, importPath)
|
||||
|
||||
if (fs.existsSync(filePrefix)) {
|
||||
const stat = fs.statSync(filePrefix)
|
||||
if (stat.isDirectory()) {
|
||||
let mainFileName = 'index.js'
|
||||
|
||||
const packageFile = path.resolve(filePrefix, 'package.json')
|
||||
|
||||
if (fs.existsSync(packageFile)) {
|
||||
const packageFileContent = fs.readFileSync(packageFile, { encoding: 'utf-8' })
|
||||
const packageJson = JSON.parse(packageFileContent)
|
||||
mainFileName = packageJson.module || packageJson.main || mainFileName
|
||||
}
|
||||
|
||||
const mainFile = path.resolve(filePrefix, mainFileName)
|
||||
if (fs.existsSync(mainFile)) {
|
||||
return relativePathPattern(path.relative(parentPath, mainFile))
|
||||
}
|
||||
return null
|
||||
}
|
||||
return importPath
|
||||
}
|
||||
const possibleSuffix = ['.js', '.mjs']
|
||||
const suffix = possibleSuffix.find(suf => fs.existsSync(filePrefix + suf))
|
||||
if (suffix) {
|
||||
return relativePathPattern(path.relative(path.resolve(currentFilePath, '../'), filePrefix + suffix))
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// babel 替换 js的相对地址引用为确定文件后缀
|
||||
export function babelReplaceImportPathWithCertainFileName(content, currentFilePath, logger = console) {
|
||||
let fileChangedMark = false
|
||||
let result = {
|
||||
code: null,
|
||||
success: [],
|
||||
error: []
|
||||
}
|
||||
const ast = parse(content, { sourceType: 'module' })
|
||||
traverse(ast, {
|
||||
ImportOrExportDeclaration: (astPath) => {
|
||||
const node = astPath.node
|
||||
if (!node.source) {
|
||||
return
|
||||
}
|
||||
const importPath = node.source.value
|
||||
if(importPath.startsWith('.')) {
|
||||
const certainPath = resolvePath(importPath, currentFilePath)
|
||||
if(!certainPath) {
|
||||
logger.warn(`File not found: ${importPath} used in ${currentFilePath}`)
|
||||
result.error.push(importPath)
|
||||
}
|
||||
if(certainPath !== importPath) {
|
||||
node.source.value = certainPath
|
||||
fileChangedMark = true
|
||||
result.success.push({before: importPath, after: certainPath})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
if (fileChangedMark) {
|
||||
const { code } = generate(ast, {
|
||||
jsescOption: {
|
||||
quotes: 'single'
|
||||
}
|
||||
})
|
||||
result.code = code
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export function getBaseUrlFromCli(fallback = '') {
|
||||
// 理论上要从resolvedConfig阶段的钩子里面拿到base,由于插件嵌套插件,子插件的配置项需要在resolveConfig前传入这里,无法等resolvedConfig,故手动获取命令行base
|
||||
const index = process.argv?.indexOf('--base')
|
||||
return index > -1 ? process.argv[index + 1] || fallback : fallback
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
export function configServerAddProxy(path, target) {
|
||||
return [
|
||||
{
|
||||
name: 'vite-plugin-config-server-add-proxy',
|
||||
configureServer(server) {
|
||||
server.middlewares.use((req, _res, next) => {
|
||||
if (req.url.includes(path)) {
|
||||
req.url = req.url.replace(path, target)
|
||||
}
|
||||
next()
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue