mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-04-05 19:41:40 +08:00
Compare commits
75 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
18524d89fb | ||
|
840c2c3c7d | ||
|
9b546645f3 | ||
|
38ea57c6cb | ||
|
c8fc2f7bfb | ||
|
b715a87f40 | ||
|
f17ef325b1 | ||
|
4ddc55aa6d | ||
|
2a714ae9cc | ||
|
d53a479b21 | ||
|
f5742c107a | ||
|
9c7d711c16 | ||
|
11c027c71b | ||
|
16f1c47db6 | ||
|
72108e0019 | ||
|
0c207c7b83 | ||
|
f671c670db | ||
|
a293bd8d3f | ||
|
7dad6720e4 | ||
|
402f05f3d6 | ||
|
0736646c63 | ||
|
8d0040da53 | ||
|
6f5bb84c04 | ||
|
63fe6ec68b | ||
|
ff07147270 | ||
|
c8e1cffca9 | ||
|
5ba2a73c70 | ||
|
a4d021d2fb | ||
|
3c66319b03 | ||
|
775fcf5693 | ||
|
f5315122e4 | ||
|
90abde57cc | ||
|
91cde30d75 | ||
|
2114b71d47 | ||
|
94d0ed1fd0 | ||
|
4026c0c305 | ||
|
6d2b9d5f21 | ||
|
f2f9044be0 | ||
|
ebc873d6f3 | ||
|
4d77b669ba | ||
|
6f2c6b151d | ||
|
6e2b5aea47 | ||
|
098351bb21 | ||
|
a0e7ee7292 | ||
|
3fbcbf25ca | ||
|
413134b21d | ||
|
6d82c0f730 | ||
|
900b701c80 | ||
|
9cabbe8c7c | ||
|
155c4a75b3 | ||
|
aec80388f0 | ||
|
51b62cfe92 | ||
|
8136477dd9 | ||
|
877a4eaa49 | ||
|
7fa3181376 | ||
|
c524cd4086 | ||
|
5c0cfe44dd | ||
|
51ca1e60af | ||
|
e234428965 | ||
|
701a9d6f30 | ||
|
e8461f91e6 | ||
|
e9c6a3bb2f | ||
|
215ef93173 | ||
|
34878d26f8 | ||
|
040b787e8f | ||
|
b215062177 | ||
|
ad2545c2e2 | ||
|
df1cb5f3e7 | ||
|
8b1201626d | ||
|
ab7df6c21e | ||
|
895c461e2b | ||
|
1baec3f1d4 | ||
|
552df3a614 | ||
|
1bcefdb1e8 | ||
|
e57fc7b718 |
126
CHANGELOG.md
126
CHANGELOG.md
@ -1,3 +1,129 @@
|
||||
## [1.5.12](https://github.com/Tencent/tmagic-editor/compare/v1.5.11...v1.5.12) (2025-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **design:** card没有slots时隐藏对应slot ([4ddc55a](https://github.com/Tencent/tmagic-editor/commit/4ddc55aa6de4bafb978a621ab9b69af1e0c36d78))
|
||||
* **editor:** 数据源修改后,依赖重新收集不准确 ([9c7d711](https://github.com/Tencent/tmagic-editor/commit/9c7d711c167c5e8ee1e9d8a8e89d66d245070dee))
|
||||
* **editor:** 获取关联组件的方法默认值 ([f5742c1](https://github.com/Tencent/tmagic-editor/commit/f5742c107a68389c0828de991e7f5e9745e20d67))
|
||||
* **vue-components:** button删除调试代码,text支持富文本 ([2a714ae](https://github.com/Tencent/tmagic-editor/commit/2a714ae9cc89b7c88528c8afe9270ad774d7755d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **cli:** 如果识别不要组件文件,则默认从npm包的default导入 ([b715a87](https://github.com/Tencent/tmagic-editor/commit/b715a87f409856ed396b3e35eb4102776329531e))
|
||||
|
||||
|
||||
|
||||
## [1.5.11](https://github.com/Tencent/tmagic-editor/compare/v1.5.10...v1.5.11) (2025-03-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dep:** 依赖收集不能过滤id/name ([0c207c7](https://github.com/Tencent/tmagic-editor/commit/0c207c7b834ae25c16038a8ca431154afb4ccda1))
|
||||
* **dep:** 数据源方法收集判断 ([72108e0](https://github.com/Tencent/tmagic-editor/commit/72108e00193698c8e7087b115f36e10216a0f386))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **vue-runtime-help:** useDsl/useEditorDsl添加app默认参数 ([f671c67](https://github.com/Tencent/tmagic-editor/commit/f671c670db84631abb1f7d9e4fbf432637de2947))
|
||||
|
||||
|
||||
|
||||
## [1.5.10](https://github.com/Tencent/tmagic-editor/compare/v1.5.9...v1.5.10) (2025-03-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **data-source:** 处理异步动态加载数据源时,初始化数据源还未加载完毕的情况 ([3c66319](https://github.com/Tencent/tmagic-editor/commit/3c66319b03c42305c66b0c6a87307fe747d9f90e))
|
||||
* **editor:** 样式配置宽度不能为负 ([775fcf5](https://github.com/Tencent/tmagic-editor/commit/775fcf5693eef051e5899aceae7873c1afa0e60c))
|
||||
* **stage:** 防止runtime重复注册 ([63fe6ec](https://github.com/Tencent/tmagic-editor/commit/63fe6ec68be444082cb16aac76d6b2fe9ee5724f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** hook函数调用添加node参数 ([5ba2a73](https://github.com/Tencent/tmagic-editor/commit/5ba2a73c7035d84688be0b0f1c0b4467558518c3))
|
||||
* **core, editor:** 删除公共的点击事件实现,由组件自行添加 ([c8e1cff](https://github.com/Tencent/tmagic-editor/commit/c8e1cffca9b12c124c34d75ee9187a03c6f61599))
|
||||
* **core:** app添加dsl-change事件 ([a4d021d](https://github.com/Tencent/tmagic-editor/commit/a4d021d2fb1fec113496733380d99e0f9deb132f))
|
||||
* **core:** node新增registerMethod方法,用于组件注册供其他组件通过事件配置调用 ([ff07147](https://github.com/Tencent/tmagic-editor/commit/ff0714727044c41148babcec977ca89058169501))
|
||||
* **reate-runtime-help,vue-runtime-help:** 新增组件状态hook ([6f5bb84](https://github.com/Tencent/tmagic-editor/commit/6f5bb84c04f9b4b5b2145ce6c559445563a60e6c))
|
||||
* **runtime:** vue2 h传参与vue3不一样,需要自定义render ([90abde5](https://github.com/Tencent/tmagic-editor/commit/90abde57cc01218b483c94faf29f88996fb75c20))
|
||||
* **runtime:** 支持页面切换 ([4026c0c](https://github.com/Tencent/tmagic-editor/commit/4026c0c305937b060de21ec74355a1be46e25dbf))
|
||||
* **vue-components,react-components:** 增加点击事件,使用组件状态hook ([0736646](https://github.com/Tencent/tmagic-editor/commit/0736646c63067b3b19125b356f462d658673eaa7))
|
||||
* **vue-container:** 支持自定义render ([91cde30](https://github.com/Tencent/tmagic-editor/commit/91cde30d75de866ade3f48f48b2c0d1251fe2b36))
|
||||
|
||||
|
||||
|
||||
## [1.5.9](https://github.com/Tencent/tmagic-editor/compare/v1.5.8...v1.5.9) (2025-02-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** 编辑器销毁不应该移除依赖收集任务的事件监听 ([6e2b5ae](https://github.com/Tencent/tmagic-editor/commit/6e2b5aea47cc1059d4b92a85b9801d7af4f9b3b9))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **table:** formatter添加index信息 ([4d77b66](https://github.com/Tencent/tmagic-editor/commit/4d77b669baf68f3346aa64d52dea6f75712b1af4))
|
||||
* **table:** 支持type: index的序号列 ([6f2c6b1](https://github.com/Tencent/tmagic-editor/commit/6f2c6b151d59aca8899742c724c44dbde7d01a89))
|
||||
|
||||
|
||||
|
||||
## [1.5.8](https://github.com/Tencent/tmagic-editor/compare/v1.5.7...v1.5.8) (2025-02-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **editor:** 组件配置列大小缓存不生效 ([6d82c0f](https://github.com/Tencent/tmagic-editor/commit/6d82c0f730ff0ad7dc36b39b7c0d2534672b05c3))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **editor:** 优化依赖收集状态显示,新增剩余任务数量显示 ([413134b](https://github.com/Tencent/tmagic-editor/commit/413134b21d3966bf7f1dbb1da6e2596f2c582bff))
|
||||
|
||||
|
||||
|
||||
## [1.5.7](https://github.com/Tencent/tmagic-editor/compare/v1.5.6...v1.5.7) (2025-02-11)
|
||||
|
||||
|
||||
|
||||
## [1.5.6](https://github.com/Tencent/tmagic-editor/compare/v1.5.5...v1.5.6) (2025-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **core:** deep-state-observer update 的data与初始化时相同,导致get data为空 ([701a9d6](https://github.com/Tencent/tmagic-editor/commit/701a9d6f3043f77048f6b9be3bc2305adb14d57e))
|
||||
* **editor:** 修改数据源可能造成页面卡死 ([e9c6a3b](https://github.com/Tencent/tmagic-editor/commit/e9c6a3bb2fd5b3b4cecffcedef47a020dba0fde2))
|
||||
* **editor:** 已经配置了的样式无法删除 ([e8461f9](https://github.com/Tencent/tmagic-editor/commit/e8461f91e62031f87dbc976f41e873f2bcc3c00c))
|
||||
* **editor:** 编辑器组件销毁后重置依赖收集 ([51ca1e6](https://github.com/Tencent/tmagic-editor/commit/51ca1e60af1ca89e6b5966825e6c0ed3707f4582))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **editor:** 优化浏览器变小时各列大小变化 ([877a4ea](https://github.com/Tencent/tmagic-editor/commit/877a4eaa49b6826e04426e162049db14f6a4f15e))
|
||||
|
||||
|
||||
|
||||
## [1.5.5](https://github.com/Tencent/tmagic-editor/compare/v1.5.4...v1.5.5) (2025-01-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **dep:** 性能优化,收集时节点配置中id与name不需要做判断 ([b215062](https://github.com/Tencent/tmagic-editor/commit/b215062177a607ae53e9ef10ffad092f4f506f82))
|
||||
* **editor:** 优化依赖收集,数据源代码块分开收集 ([040b787](https://github.com/Tencent/tmagic-editor/commit/040b787e8f138759e2acfed4071ffa7cf70eea59))
|
||||
|
||||
|
||||
|
||||
## [1.5.4](https://github.com/Tencent/tmagic-editor/compare/v1.5.3...v1.5.4) (2025-01-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **element-plus-adapter:** 只有当前没注册loading指令时才注册 ([8b12016](https://github.com/Tencent/tmagic-editor/commit/8b1201626dd2ff410e919da2baec58b0c332303d))
|
||||
* **element-plus-adapter:** 增加loading指令 ([1bcefdb](https://github.com/Tencent/tmagic-editor/commit/1bcefdb1e8ca851bdd322de860546a906298b02b))
|
||||
|
||||
|
||||
|
||||
## [1.5.3](https://github.com/Tencent/tmagic-editor/compare/v1.5.2...v1.5.3) (2025-01-06)
|
||||
|
||||
|
||||
|
41
package.json
41
package.json
@ -1,12 +1,12 @@
|
||||
{
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.12",
|
||||
"name": "tmagic",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@9.12.3",
|
||||
"packageManager": "pnpm@9.15.4",
|
||||
"scripts": {
|
||||
"bootstrap": "pnpm i && pnpm build",
|
||||
"clean:top": "rimraf */**/dist */**/types */dist coverage dwt* temp",
|
||||
"clean:top": "rimraf */**/dist */**/types */dist coverage dwt* temp packages/cli/lib",
|
||||
"clean:modules": "rimraf node_modules **/node_modules **/**/node_modules",
|
||||
"clean:all": "pnpm clean:top && pnpm clean:modules",
|
||||
"lint": "eslint . --ext .js,.vue,.ts,.tsx",
|
||||
@ -17,7 +17,7 @@
|
||||
"pg:vue2": "pnpm playground:vue2",
|
||||
"playground:react": "pnpm --filter \"runtime-react\" build:libs && pnpm --filter \"runtime-react\" --filter \"tmagic-playground\" dev:react",
|
||||
"pg:react": "pnpm playground:react",
|
||||
"build": "pnpm build:dts && pnpm --filter \"@tmagic/*\" build",
|
||||
"build": "pnpm build:dts && node scripts/build.mjs",
|
||||
"build:dts": "pnpm --filter \"@tmagic/cli\" build && tsc -p tsconfig.build-browser.json && vue-tsc --declaration --emitDeclarationOnly --project tsconfig.build-vue.json && rollup -c rollup.dts.config.js && rimraf temp",
|
||||
"check:type": "tsc --incremental --noEmit -p tsconfig.check.json && vue-tsc --noEmit -p tsconfig.check-vue.json",
|
||||
"build:playground": "pnpm --filter \"runtime-vue3\" build && pnpm --filter \"tmagic-playground\" build",
|
||||
@ -49,42 +49,43 @@
|
||||
"@types/node": "18.19.61",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitest/coverage-v8": "^2.1.4",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"@vitest/coverage-v8": "^2.1.9",
|
||||
"@vue/compiler-sfc": "^3.5.13",
|
||||
"c8": "^7.14.0",
|
||||
"commitizen": "^4.3.1",
|
||||
"conventional-changelog-cli": "^4.1.0",
|
||||
"cosmiconfig": "^8.3.6",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"element-plus": "^2.9.0",
|
||||
"element-plus": "^2.9.7",
|
||||
"enquirer": "^2.4.1",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-tencent": "^1.1.1",
|
||||
"eslint-config-tencent": "^1.1.2",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||
"eslint-plugin-vue": "^9.30.0",
|
||||
"eslint-plugin-vue": "^9.33.0",
|
||||
"execa": "^4.1.0",
|
||||
"highlight.js": "^11.10.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
"husky": "^7.0.4",
|
||||
"jsdom": "^19.0.0",
|
||||
"lint-staged": "^11.2.6",
|
||||
"minimist": "^1.2.8",
|
||||
"picocolors": "^1.1.1",
|
||||
"prettier": "^2.8.8",
|
||||
"recast": "^0.20.5",
|
||||
"recast": "^0.23.11",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^4.24.3",
|
||||
"rollup-plugin-dts": "^6.1.1",
|
||||
"semver": "^7.6.3",
|
||||
"rollup": "^4.38.0",
|
||||
"rollup-plugin-dts": "^6.2.1",
|
||||
"semver": "^7.7.1",
|
||||
"serialize-javascript": "^6.0.2",
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.6.3",
|
||||
"vite": "^6.0.3",
|
||||
"vitepress": "^1.5.0",
|
||||
"vitest": "^2.1.8",
|
||||
"vue": "^3.5.12",
|
||||
"vue-tsc": "^2.1.10"
|
||||
"typescript": "^5.8.2",
|
||||
"vite": "^6.2.4",
|
||||
"vitepress": "^1.6.3",
|
||||
"vitest": "^3.1.1",
|
||||
"vue": "^3.5.13",
|
||||
"vue-tsc": "^2.2.8"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.12",
|
||||
"name": "@tmagic/cli",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
@ -31,7 +31,7 @@
|
||||
"esbuild": "^0.21.5",
|
||||
"fs-extra": "^11.2.0",
|
||||
"picocolors": "^1.1.1",
|
||||
"recast": "^0.23.9",
|
||||
"recast": "^0.23.11",
|
||||
"tslib": "^2.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -11,11 +11,14 @@ export default class Core {
|
||||
public options: UserConfig;
|
||||
|
||||
public moduleMainFilePath: ModuleMainFilePath = {
|
||||
componentPackage: {},
|
||||
componentMap: {},
|
||||
pluginPakcage: {},
|
||||
pluginMap: {},
|
||||
configMap: {},
|
||||
valueMap: {},
|
||||
eventMap: {},
|
||||
datasourcePackage: {},
|
||||
datasourceMap: {},
|
||||
dsConfigMap: {},
|
||||
dsValueMap: {},
|
||||
|
@ -54,11 +54,14 @@ export interface NpmConfig {
|
||||
}
|
||||
|
||||
export interface ModuleMainFilePath {
|
||||
componentPackage: Record<string, string>;
|
||||
componentMap: Record<string, string>;
|
||||
pluginPakcage: Record<string, string>;
|
||||
pluginMap: Record<string, string>;
|
||||
configMap: Record<string, string>;
|
||||
valueMap: Record<string, string>;
|
||||
eventMap: Record<string, string>;
|
||||
datasourcePackage: Record<string, string>;
|
||||
datasourceMap: Record<string, string>;
|
||||
dsConfigMap: Record<string, string>;
|
||||
dsValueMap: Record<string, string>;
|
||||
|
@ -5,33 +5,84 @@ import { EntryType } from '../types';
|
||||
|
||||
export const prepareEntryFile = async (app: App) => {
|
||||
const { moduleMainFilePath, options } = app;
|
||||
const { componentFileAffix, dynamicImport, hooks, useTs = true } = options;
|
||||
const { dynamicImport, hooks, useTs = true } = options;
|
||||
|
||||
let contentMap: Record<string, string> = {
|
||||
'comp-entry': generateContent(useTs, EntryType.COMPONENT, moduleMainFilePath.componentMap, componentFileAffix),
|
||||
'comp-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.COMPONENT,
|
||||
moduleMainFilePath.componentPackage,
|
||||
moduleMainFilePath.componentMap,
|
||||
),
|
||||
'async-comp-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.COMPONENT,
|
||||
moduleMainFilePath.componentPackage,
|
||||
moduleMainFilePath.componentMap,
|
||||
componentFileAffix,
|
||||
dynamicImport,
|
||||
),
|
||||
'plugin-entry': generateContent(useTs, EntryType.PLUGIN, moduleMainFilePath.pluginMap),
|
||||
'async-plugin-entry': generateContent(useTs, EntryType.PLUGIN, moduleMainFilePath.pluginMap, '', dynamicImport),
|
||||
'config-entry': generateContent(useTs, EntryType.CONFIG, moduleMainFilePath.configMap),
|
||||
'value-entry': generateContent(useTs, EntryType.VALUE, moduleMainFilePath.valueMap),
|
||||
'event-entry': generateContent(useTs, EntryType.EVENT, moduleMainFilePath.eventMap),
|
||||
'datasource-entry': generateContent(useTs, EntryType.DATASOURCE, moduleMainFilePath.datasourceMap),
|
||||
'plugin-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.PLUGIN,
|
||||
moduleMainFilePath.pluginPakcage,
|
||||
moduleMainFilePath.pluginMap,
|
||||
),
|
||||
'async-plugin-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.PLUGIN,
|
||||
moduleMainFilePath.pluginPakcage,
|
||||
moduleMainFilePath.pluginMap,
|
||||
dynamicImport,
|
||||
),
|
||||
'config-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.CONFIG,
|
||||
moduleMainFilePath.componentPackage,
|
||||
moduleMainFilePath.configMap,
|
||||
),
|
||||
'value-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.VALUE,
|
||||
moduleMainFilePath.componentPackage,
|
||||
moduleMainFilePath.valueMap,
|
||||
),
|
||||
'event-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.EVENT,
|
||||
moduleMainFilePath.componentPackage,
|
||||
moduleMainFilePath.eventMap,
|
||||
),
|
||||
'datasource-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.DATASOURCE,
|
||||
moduleMainFilePath.datasourcePackage,
|
||||
moduleMainFilePath.datasourceMap,
|
||||
),
|
||||
'async-datasource-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.DATASOURCE,
|
||||
moduleMainFilePath.datasourcePackage,
|
||||
moduleMainFilePath.datasourceMap,
|
||||
'',
|
||||
dynamicImport,
|
||||
),
|
||||
'ds-config-entry': generateContent(useTs, EntryType.DS_CONFIG, moduleMainFilePath.dsConfigMap),
|
||||
'ds-value-entry': generateContent(useTs, EntryType.DS_VALUE, moduleMainFilePath.dsValueMap),
|
||||
'ds-event-entry': generateContent(useTs, EntryType.DS_EVENT, moduleMainFilePath.dsEventMap),
|
||||
'ds-config-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.DS_CONFIG,
|
||||
moduleMainFilePath.datasourcePackage,
|
||||
moduleMainFilePath.dsConfigMap,
|
||||
),
|
||||
'ds-value-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.DS_VALUE,
|
||||
moduleMainFilePath.datasourcePackage,
|
||||
moduleMainFilePath.dsValueMap,
|
||||
),
|
||||
'ds-event-entry': generateContent(
|
||||
useTs,
|
||||
EntryType.DS_EVENT,
|
||||
moduleMainFilePath.datasourcePackage,
|
||||
moduleMainFilePath.dsEventMap,
|
||||
),
|
||||
};
|
||||
|
||||
if (typeof hooks?.beforeWriteEntry === 'function') {
|
||||
@ -53,8 +104,8 @@ export const prepareEntryFile = async (app: App) => {
|
||||
export const generateContent = (
|
||||
useTs: boolean,
|
||||
type: EntryType,
|
||||
packageMap: Record<string, string> = {},
|
||||
map: Record<string, string> = {},
|
||||
componentFileAffix = '',
|
||||
dynamicImport = false,
|
||||
) => {
|
||||
const list: string[] = [];
|
||||
@ -62,14 +113,14 @@ export const generateContent = (
|
||||
|
||||
Object.entries(map).forEach(([key, packagePath]) => {
|
||||
const name = makeCamelCase(key);
|
||||
if (dynamicImport) {
|
||||
list.push(
|
||||
`'${key}': () => import('${packagePath}${packagePath.endsWith(componentFileAffix) ? '' : componentFileAffix}')`,
|
||||
);
|
||||
|
||||
if ([EntryType.CONFIG, EntryType.EVENT, EntryType.VALUE].includes(type) && packagePath === packageMap[key]) {
|
||||
importDeclarations.push(`import { ${type} as ${name} } from '${packageMap[key]}'`);
|
||||
list.push(`'${key}': ${name}`);
|
||||
} else if (dynamicImport) {
|
||||
list.push(`'${key}': () => import('${packagePath}')`);
|
||||
} else {
|
||||
importDeclarations.push(
|
||||
`import ${name} from '${packagePath}${packagePath.endsWith(componentFileAffix) ? '' : componentFileAffix}'`,
|
||||
);
|
||||
importDeclarations.push(`import ${name} from '${packagePath}'`);
|
||||
list.push(`'${key}': ${name}`);
|
||||
}
|
||||
});
|
||||
|
@ -38,20 +38,37 @@ const getRelativePath = (str: string, base: string) => (path.isAbsolute(str) ? p
|
||||
|
||||
const npmInstall = function (dependencies: Record<string, string>, cwd: string, npmConfig: NpmConfig = {}) {
|
||||
try {
|
||||
const { client = 'npm', registry, installArgs = '' } = npmConfig;
|
||||
const { client = 'npm', registry, installArgs = '', keepPackageJsonClean } = npmConfig;
|
||||
const install = {
|
||||
npm: 'install',
|
||||
yarn: 'add',
|
||||
pnpm: 'add',
|
||||
}[client];
|
||||
|
||||
const packages = Object.entries(dependencies)
|
||||
.map(([name, version]) => (version ? `${name}@${version}` : name))
|
||||
.join(' ');
|
||||
let packages = Object.entries(dependencies);
|
||||
|
||||
const newPackages = Object.entries(dependencies).filter(([name]) => {
|
||||
if (fs.existsSync(path.resolve(cwd, 'node_modules', name))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// keepPackageJsonClean会保留原始的package.json,这样配置的packages就不会被写入dependencies中
|
||||
// install 时会删除不在dependencies中的依赖,所以需要install packages中配置的所有包
|
||||
if (!keepPackageJsonClean || !newPackages.length) {
|
||||
packages = newPackages;
|
||||
}
|
||||
|
||||
if (!packages.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const packageNames = packages.map(([name, version]) => (version ? `${name}@${version}` : name)).join(' ');
|
||||
|
||||
const installArgsString = `${installArgs ? ` ${installArgs}` : ''}`;
|
||||
const registryString = `${registry ? ` --registry ${registry}` : ''}`;
|
||||
const command = `${client} ${install}${installArgsString} ${packages}${registryString}`;
|
||||
const command = `${client} ${install}${installArgsString} ${packageNames}${registryString}`;
|
||||
|
||||
execInfo(cwd);
|
||||
execInfo(command);
|
||||
@ -318,25 +335,30 @@ const parseEntry = function ({ ast, package: module, indexPath }: ParseEntryOpti
|
||||
const tokens = getASTTokenByTraverse({ ast, indexPath });
|
||||
let { config, value, event, component } = tokens;
|
||||
|
||||
if (!config) {
|
||||
if (typeof config === 'undefined') {
|
||||
info(`${module} 表单配置文件声明缺失`);
|
||||
}
|
||||
if (!value) {
|
||||
if (typeof value === 'undefined') {
|
||||
info(`${module} 初始化数据文件声明缺失`);
|
||||
}
|
||||
if (!event) {
|
||||
if (typeof event === 'undefined') {
|
||||
info(`${module} 事件声明文件声明缺失`);
|
||||
}
|
||||
if (!component) {
|
||||
info(`${module} 组件或数据源文件声明不合法`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const reg = /^.*[/\\]node_modules[/\\](.*)/;
|
||||
[, config] = config.match(reg) || [, config];
|
||||
[, value] = value.match(reg) || [, value];
|
||||
[, component] = component.match(reg) || [, component];
|
||||
[, event] = event.match(reg) || [, event];
|
||||
|
||||
if (config) {
|
||||
[, config] = config.match(reg) || [, config];
|
||||
}
|
||||
if (value) {
|
||||
[, value] = value.match(reg) || [, value];
|
||||
}
|
||||
if (component) {
|
||||
[, component] = component.match(reg) || [, component];
|
||||
}
|
||||
if (event) {
|
||||
[, event] = event.match(reg) || [, event];
|
||||
}
|
||||
|
||||
return {
|
||||
config,
|
||||
@ -347,10 +369,10 @@ const parseEntry = function ({ ast, package: module, indexPath }: ParseEntryOpti
|
||||
};
|
||||
|
||||
const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string }) => {
|
||||
let config = '';
|
||||
let value = '';
|
||||
let event = '';
|
||||
let component = '';
|
||||
let config: string | undefined;
|
||||
let value: string | undefined;
|
||||
let event: string | undefined;
|
||||
let component: string | undefined;
|
||||
const importSpecifiersMap: { [key: string]: string } = {};
|
||||
const exportSpecifiersMap: { [key: string]: string | undefined } = {};
|
||||
|
||||
@ -396,7 +418,11 @@ const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string
|
||||
visitExportDefaultDeclaration(p) {
|
||||
const { node } = p;
|
||||
const { declaration } = node as any;
|
||||
component = path.resolve(path.dirname(indexPath), importSpecifiersMap[declaration.name]);
|
||||
|
||||
if (importSpecifiersMap[declaration.name]) {
|
||||
component = path.resolve(path.dirname(indexPath), importSpecifiersMap[declaration.name]);
|
||||
}
|
||||
|
||||
this.traverse(p);
|
||||
},
|
||||
});
|
||||
@ -405,7 +431,10 @@ const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string
|
||||
const exportValue = exportSpecifiersMap[exportName];
|
||||
const importValue = importSpecifiersMap[exportName];
|
||||
const connectValue = exportValue ? importSpecifiersMap[exportValue] : '';
|
||||
const filePath = path.resolve(path.dirname(indexPath), connectValue || importValue || exportValue || '');
|
||||
|
||||
const fileName = connectValue || importValue || exportValue || '';
|
||||
|
||||
const filePath = fileName ? path.resolve(path.dirname(indexPath), fileName) : '';
|
||||
|
||||
if (exportName === EntryType.VALUE) {
|
||||
value = filePath;
|
||||
@ -463,7 +492,7 @@ const getDependencies = (dependencies: Record<string, string>, packagePath: stri
|
||||
|
||||
const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string, cwd: string, key?: string) => {
|
||||
const { options } = app;
|
||||
const { temp, componentFileAffix, datasoucreSuperClass } = options;
|
||||
const { temp, componentFileAffix = '', datasoucreSuperClass } = options;
|
||||
|
||||
let { name: moduleName } = splitNameVersion(packagePath);
|
||||
|
||||
@ -513,15 +542,45 @@ const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string
|
||||
|
||||
if (!key) return;
|
||||
|
||||
if (result.type === PackageType.COMPONENT) {
|
||||
if (result.type === PackageType.COMPONENT || !result.type) {
|
||||
packages.componentPackage[key] = moduleName;
|
||||
// 组件
|
||||
const entry = parseEntry({ ast, package: moduleName, indexPath });
|
||||
|
||||
if (entry.component) packages.componentMap[key] = getRelativePath(entry.component, temp);
|
||||
if (entry.config) packages.configMap[key] = getRelativePath(entry.config, temp);
|
||||
if (entry.event) packages.eventMap[key] = getRelativePath(entry.event, temp);
|
||||
if (entry.value) packages.valueMap[key] = getRelativePath(entry.value, temp);
|
||||
if (entry.component) {
|
||||
const packagePath = getRelativePath(entry.component, temp);
|
||||
packages.componentMap[key] = `${packagePath}${
|
||||
packagePath.endsWith(componentFileAffix) ? '' : componentFileAffix
|
||||
}`;
|
||||
} else {
|
||||
packages.componentMap[key] = moduleName;
|
||||
}
|
||||
|
||||
if (typeof entry.config === 'string') {
|
||||
if (entry.config) {
|
||||
packages.configMap[key] = getRelativePath(entry.config, temp);
|
||||
} else {
|
||||
packages.configMap[key] = moduleName;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof entry.event === 'string') {
|
||||
if (entry.event) {
|
||||
packages.eventMap[key] = getRelativePath(entry.event, temp);
|
||||
} else {
|
||||
packages.eventMap[key] = moduleName;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof entry.value === 'string') {
|
||||
if (entry.value) {
|
||||
packages.valueMap[key] = getRelativePath(entry.value, temp);
|
||||
} else {
|
||||
packages.valueMap[key] = moduleName;
|
||||
}
|
||||
}
|
||||
} else if (result.type === PackageType.DATASOURCE) {
|
||||
packages.datasourcePackage[key] = moduleName;
|
||||
// 数据源
|
||||
const entry = parseEntry({ ast, package: moduleName, indexPath });
|
||||
|
||||
@ -530,6 +589,7 @@ const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string
|
||||
if (entry.event) packages.dsEventMap[key] = getRelativePath(entry.event, temp);
|
||||
if (entry.value) packages.dsValueMap[key] = getRelativePath(entry.value, temp);
|
||||
} else if (result.type === PackageType.PLUGIN) {
|
||||
packages.pluginPakcage[key] = moduleName;
|
||||
// 插件
|
||||
packages.pluginMap[key] = getRelativePath(moduleName, temp);
|
||||
}
|
||||
@ -573,11 +633,14 @@ export const resolveAppPackages = (app: App): ModuleMainFilePath => {
|
||||
}
|
||||
|
||||
const packagesMap: ModuleMainFilePath = {
|
||||
componentPackage: {},
|
||||
componentMap: {},
|
||||
configMap: {},
|
||||
eventMap: {},
|
||||
valueMap: {},
|
||||
pluginPakcage: {},
|
||||
pluginMap: {},
|
||||
datasourcePackage: {},
|
||||
datasourceMap: {},
|
||||
dsConfigMap: {},
|
||||
dsEventMap: {},
|
||||
|
@ -7,6 +7,7 @@
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declaration": true,
|
||||
|
||||
"types": ["node"],
|
||||
},
|
||||
"include": ["./src"],
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.12",
|
||||
"name": "@tmagic/core",
|
||||
"type": "module",
|
||||
"main": "dist/tmagic-core.umd.cjs",
|
||||
@ -24,9 +24,6 @@
|
||||
"resetcss.css"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@ -35,9 +32,6 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/Tencent/tmagic-editor.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tmagic/data-source": "workspace:*",
|
||||
"@tmagic/dep": "workspace:*",
|
||||
@ -48,10 +42,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/events": "^3.0.0",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@types/node": "^18.19.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"vite": "^6.0.3"
|
||||
"@types/lodash-es": "^4.17.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "*"
|
||||
|
@ -49,6 +49,12 @@ export interface AppOptionsConfig {
|
||||
|
||||
class App extends EventEmitter {
|
||||
[x: string]: any;
|
||||
static nodeClassMap = new Map<string, typeof Node>();
|
||||
|
||||
public static registerNode<T extends typeof Node = typeof Node>(type: string, NodeClass: T) {
|
||||
App.nodeClassMap.set(type, NodeClass);
|
||||
}
|
||||
|
||||
public env: Env = new Env();
|
||||
public dsl?: MApp;
|
||||
public codeDsl?: CodeBlockDSL;
|
||||
@ -144,7 +150,12 @@ class App extends EventEmitter {
|
||||
this.dataSourceManager = createDataSourceManager(this, this.useMock);
|
||||
|
||||
this.codeDsl = config.codeBlocks;
|
||||
this.setPage(curPage || this.page?.data?.id);
|
||||
|
||||
const pageId = curPage || this.page?.data?.id;
|
||||
|
||||
super.emit('dsl-change', { dsl: config, curPage: pageId });
|
||||
|
||||
this.setPage(pageId);
|
||||
|
||||
if (this.dataSourceManager) {
|
||||
const dataSourceList = Array.from(this.dataSourceManager.dataSourceMap.values());
|
||||
@ -162,19 +173,22 @@ class App extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pageConfig === this.page?.data) return;
|
||||
|
||||
this.page?.destroy();
|
||||
if (this.page) {
|
||||
if (pageConfig === this.page.data) return;
|
||||
this.page.destroy();
|
||||
}
|
||||
|
||||
this.page = new Page({
|
||||
config: pageConfig,
|
||||
app: this,
|
||||
});
|
||||
|
||||
this.eventHelper?.removeNodeEvents();
|
||||
this.page.nodes.forEach((node) => {
|
||||
this.eventHelper?.bindNodeEvents(node);
|
||||
});
|
||||
if (this.eventHelper) {
|
||||
this.eventHelper.removeNodeEvents();
|
||||
for (const [, node] of this.page.nodes) {
|
||||
this.eventHelper.bindNodeEvents(node);
|
||||
}
|
||||
}
|
||||
|
||||
super.emit('page-change', this.page);
|
||||
}
|
||||
|
@ -30,7 +30,11 @@ class Env {
|
||||
isWeb = false;
|
||||
isOpenHarmony = false;
|
||||
|
||||
constructor(ua = globalThis.navigator.userAgent, options: Record<string, boolean | string> = {}) {
|
||||
constructor(ua = globalThis.navigator?.userAgent ?? '', options: Record<string, boolean | string> = {}) {
|
||||
if (!ua) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isIphone = ua.indexOf('iPhone') >= 0;
|
||||
|
||||
this.isIpad = /(iPad).*OS\s([\d_]+)/.test(ua);
|
||||
|
@ -32,38 +32,11 @@ import {
|
||||
type EventActionItem,
|
||||
type EventConfig,
|
||||
} from '@tmagic/schema';
|
||||
import { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, getIdFromEl } from '@tmagic/utils';
|
||||
import { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX } from '@tmagic/utils';
|
||||
|
||||
import type { default as TMagicApp } from './App';
|
||||
import FlowState from './FlowState';
|
||||
import type { default as TMagicNode } from './Node';
|
||||
import { COMMON_EVENT_PREFIX, isCommonMethod, triggerCommonMethod } from './utils';
|
||||
|
||||
const getCommonEventName = (commonEventName: string) => {
|
||||
if (commonEventName.startsWith(COMMON_EVENT_PREFIX)) return commonEventName;
|
||||
return `${COMMON_EVENT_PREFIX}${commonEventName}`;
|
||||
};
|
||||
|
||||
// 点击在组件内的某个元素上,需要向上寻找到当前组件
|
||||
const getDirectComponent = (element: HTMLElement | null, app: TMagicApp): TMagicNode | undefined => {
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = getIdFromEl()(element);
|
||||
|
||||
if (!id) {
|
||||
return getDirectComponent(element.parentElement, app);
|
||||
}
|
||||
|
||||
const node = app.getNode(
|
||||
id,
|
||||
element.dataset.tmagicIteratorContainerId?.split(','),
|
||||
element.dataset.tmagicIteratorIndex?.split(',').map((i) => globalThis.parseInt(i, 10)),
|
||||
);
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
export default class EventHelper extends EventEmitter {
|
||||
public app: TMagicApp;
|
||||
@ -75,19 +48,11 @@ export default class EventHelper extends EventEmitter {
|
||||
super();
|
||||
|
||||
this.app = app;
|
||||
|
||||
if (app.jsEngine === 'browser') {
|
||||
globalThis.document.body.addEventListener('click', this.commonClickEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.removeNodeEvents();
|
||||
this.removeAllListeners();
|
||||
|
||||
if (this.app.jsEngine === 'browser') {
|
||||
globalThis.document.body.removeEventListener('click', this.commonClickEventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public bindNodeEvents(node: TMagicNode) {
|
||||
@ -243,10 +208,6 @@ export default class EventHelper extends EventEmitter {
|
||||
const toNode = this.app.getNode(to);
|
||||
if (!toNode) throw `ID为${to}的组件不存在`;
|
||||
|
||||
if (isCommonMethod(methodName)) {
|
||||
return triggerCommonMethod(methodName, toNode);
|
||||
}
|
||||
|
||||
if (toNode.instance) {
|
||||
if (typeof toNode.instance[methodName] === 'function') {
|
||||
await toNode.instance[methodName](fromCpt, ...args);
|
||||
@ -259,17 +220,4 @@ export default class EventHelper extends EventEmitter {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private commonClickEventHandler = (e: MouseEvent) => {
|
||||
if (!e.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
const node = getDirectComponent(e.target as HTMLElement, this.app);
|
||||
|
||||
const eventName = `${getCommonEventName('click')}_${node?.data.id}`;
|
||||
if (node?.eventKeys.has(eventName)) {
|
||||
this.emit(node.eventKeys.get(eventName)!, node);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -32,6 +32,10 @@ interface EventCache {
|
||||
args: any[];
|
||||
}
|
||||
|
||||
interface Methods {
|
||||
[key: string]: (...args: any[]) => any;
|
||||
}
|
||||
|
||||
export interface NodeOptions {
|
||||
config: MNode;
|
||||
page?: Page;
|
||||
@ -45,7 +49,7 @@ class Node extends EventEmitter {
|
||||
[key: string]: any;
|
||||
};
|
||||
public events: EventConfig[] = [];
|
||||
public instance?: any;
|
||||
public instance?: any = {};
|
||||
public page?: Page;
|
||||
public parent?: Node;
|
||||
public app: TMagicApp;
|
||||
@ -69,6 +73,7 @@ class Node extends EventEmitter {
|
||||
const { events, style } = data;
|
||||
this.events = events || [];
|
||||
this.style = style || {};
|
||||
this.instance.config = data;
|
||||
this.emit('update-data', data);
|
||||
}
|
||||
|
||||
@ -76,6 +81,22 @@ class Node extends EventEmitter {
|
||||
this.eventQueue.push(event);
|
||||
}
|
||||
|
||||
public registerMethod(methods: Methods) {
|
||||
if (!methods) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.instance) {
|
||||
this.instance = {};
|
||||
}
|
||||
|
||||
for (const [key, fn] of Object.entries(methods)) {
|
||||
if (typeof fn === 'function') {
|
||||
this.instance[key] = fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async runHookCode(hook: string, params?: Record<string, any>) {
|
||||
if (typeof this.data[hook] === 'function') {
|
||||
// 兼容旧的数据格式
|
||||
@ -102,8 +123,9 @@ class Node extends EventEmitter {
|
||||
const { codeType = HookCodeType.CODE, codeId, params: itemParams = {} } = item;
|
||||
|
||||
let functionContent: ((...args: any[]) => any) | string | undefined;
|
||||
const functionParams: { app: TMagicApp; params: Record<string, any>; dataSource?: DataSource } = {
|
||||
const functionParams: { app: TMagicApp; node: Node; params: Record<string, any>; dataSource?: DataSource } = {
|
||||
app: this.app,
|
||||
node: this,
|
||||
params: params || itemParams,
|
||||
};
|
||||
|
||||
@ -136,12 +158,23 @@ class Node extends EventEmitter {
|
||||
this.listenLifeSafe();
|
||||
});
|
||||
|
||||
this.instance = instance;
|
||||
if (instance) {
|
||||
this.registerMethod(instance);
|
||||
if (instance.config) {
|
||||
this.setData(instance.config);
|
||||
}
|
||||
}
|
||||
|
||||
await this.runHookCode('created');
|
||||
});
|
||||
|
||||
this.once('mounted', async (instance: any) => {
|
||||
this.instance = instance;
|
||||
if (instance) {
|
||||
this.registerMethod(instance);
|
||||
if (instance.config) {
|
||||
this.setData(instance.config);
|
||||
}
|
||||
}
|
||||
|
||||
for (let eventConfig = this.eventQueue.shift(); eventConfig; eventConfig = this.eventQueue.shift()) {
|
||||
if (typeof instance[eventConfig.method] === 'function') {
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
import type { Id, MComponent, MContainer, MPage, MPageFragment } from '@tmagic/schema';
|
||||
|
||||
import type App from './App';
|
||||
import App from './App';
|
||||
import IteratorContainer from './IteratorContainer';
|
||||
import type { default as TMagicNode } from './Node';
|
||||
import Node from './Node';
|
||||
@ -53,7 +53,7 @@ class Page extends Node {
|
||||
return;
|
||||
}
|
||||
|
||||
const node = new Node({
|
||||
const node = new ((config.type && App.nodeClassMap.get(config.type)) || Node)({
|
||||
config,
|
||||
parent,
|
||||
page: this,
|
||||
|
@ -18,8 +18,6 @@
|
||||
import { JsEngine } from '@tmagic/schema';
|
||||
import { isNumber } from '@tmagic/utils';
|
||||
|
||||
import type { default as TMagicNode } from './Node';
|
||||
|
||||
export const style2Obj = (style: string) => {
|
||||
if (typeof style !== 'string') {
|
||||
return style;
|
||||
@ -119,47 +117,7 @@ export const transformStyle = (style: Record<string, any> | string, jsEngine: Js
|
||||
export const COMMON_EVENT_PREFIX = 'magic:common:events:';
|
||||
export const COMMON_METHOD_PREFIX = 'magic:common:actions:';
|
||||
|
||||
export const CommonMethod = {
|
||||
SHOW: 'show',
|
||||
HIDE: 'hide',
|
||||
SCROLL_TO_VIEW: 'scrollIntoView',
|
||||
SCROLL_TO_TOP: 'scrollToTop',
|
||||
};
|
||||
|
||||
export const isCommonMethod = (methodName: string) => methodName.startsWith(COMMON_METHOD_PREFIX);
|
||||
|
||||
export const triggerCommonMethod = (methodName: string, node: TMagicNode) => {
|
||||
const { instance } = node;
|
||||
|
||||
if (!instance) return;
|
||||
|
||||
switch (methodName.replace(COMMON_METHOD_PREFIX, '')) {
|
||||
case CommonMethod.SHOW:
|
||||
instance.show();
|
||||
break;
|
||||
|
||||
case CommonMethod.HIDE:
|
||||
instance.hide();
|
||||
break;
|
||||
|
||||
case CommonMethod.SCROLL_TO_VIEW:
|
||||
instance.$el?.scrollIntoView({ behavior: 'smooth' });
|
||||
break;
|
||||
|
||||
case CommonMethod.SCROLL_TO_TOP:
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export interface EventOption {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_EVENTS: EventOption[] = [{ label: '点击', value: `${COMMON_EVENT_PREFIX}click` }];
|
||||
|
||||
export const DEFAULT_METHODS: EventOption[] = [];
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { MApp, NodeType, TMagicIteratorContainer } from '@tmagic/schema';
|
||||
import { MApp, NodeType } from '@tmagic/schema';
|
||||
|
||||
import App from '../src/App';
|
||||
import TMagicIteratorContainer from '../src/IteratorContainer';
|
||||
|
||||
const createAppDsl = (pageLength: number, nodeLength = 0) => {
|
||||
const dsl: MApp = {
|
||||
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||
*
|
||||
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
import pkg from './package.json';
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
cssCodeSplit: false,
|
||||
sourcemap: false,
|
||||
minify: false,
|
||||
target: 'esnext',
|
||||
|
||||
lib: {
|
||||
entry: 'src/index.ts',
|
||||
name: 'TMagicCore',
|
||||
fileName: 'tmagic-core',
|
||||
},
|
||||
|
||||
rollupOptions: {
|
||||
// 确保外部化处理那些你不想打包进库的依赖
|
||||
external(id: string) {
|
||||
return Object.keys({
|
||||
...pkg.dependencies,
|
||||
...pkg.peerDependencies,
|
||||
}).some((k) => new RegExp(`^${k}`).test(id));
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.12",
|
||||
"name": "@tmagic/data-source",
|
||||
"type": "module",
|
||||
"main": "dist/tmagic-data-source.umd.cjs",
|
||||
@ -19,9 +19,6 @@
|
||||
"src"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "vite build --mode=es && vite build --mode=umd"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@ -49,9 +46,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/events": "^3.0.0",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@types/node": "^18.19.0",
|
||||
"tsc-alias": "^1.8.5",
|
||||
"vite": "^6.0.3"
|
||||
"@types/lodash-es": "^4.17.4"
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,16 @@ import { compiledNodeField, compliedConditions, compliedIteratorItem, createIter
|
||||
class DataSourceManager extends EventEmitter {
|
||||
private static dataSourceClassMap = new Map<string, typeof DataSource>();
|
||||
private static ObservedDataClass: ObservedDataClass = SimpleObservedData;
|
||||
private static waitInitSchemaList = new Map<DataSourceManager, Record<string, DataSourceSchema[]>>();
|
||||
|
||||
public static register<T extends typeof DataSource = typeof DataSource>(type: string, dataSource: T) {
|
||||
DataSourceManager.dataSourceClassMap.set(type, dataSource);
|
||||
DataSourceManager.waitInitSchemaList?.forEach((listMap, app) => {
|
||||
const list = listMap[type] || [];
|
||||
for (let config = list.shift(); config; config = list.shift()) {
|
||||
app.addDataSource(config);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static getDataSourceClass(type: string) {
|
||||
@ -55,6 +62,8 @@ class DataSourceManager extends EventEmitter {
|
||||
constructor({ app, useMock, initialData }: DataSourceManagerOptions) {
|
||||
super();
|
||||
|
||||
DataSourceManager.waitInitSchemaList.set(this, {});
|
||||
|
||||
this.app = app;
|
||||
this.useMock = useMock;
|
||||
|
||||
@ -133,7 +142,24 @@ class DataSourceManager extends EventEmitter {
|
||||
public async addDataSource(config?: DataSourceSchema) {
|
||||
if (!config) return;
|
||||
|
||||
const DataSourceClass = DataSourceManager.dataSourceClassMap.get(config.type) || DataSource;
|
||||
const DataSourceClass = DataSourceManager.dataSourceClassMap.get(config.type);
|
||||
|
||||
if (!DataSourceClass) {
|
||||
let listMap = DataSourceManager.waitInitSchemaList.get(this);
|
||||
|
||||
if (!listMap) {
|
||||
listMap = {};
|
||||
DataSourceManager.waitInitSchemaList.set(this, listMap);
|
||||
}
|
||||
|
||||
if (listMap[config.type]) {
|
||||
listMap[config.type].push(config);
|
||||
} else {
|
||||
listMap[config.type] = [config];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const ds = new DataSourceClass({
|
||||
app: this.app,
|
||||
@ -177,7 +203,7 @@ class DataSourceManager extends EventEmitter {
|
||||
|
||||
this.removeDataSource(schema.id);
|
||||
|
||||
this.addDataSource(schema);
|
||||
this.addDataSource(cloneDeep(schema));
|
||||
const newDs = this.get(schema.id);
|
||||
if (newDs) {
|
||||
this.init(newDs);
|
||||
@ -276,6 +302,7 @@ class DataSourceManager extends EventEmitter {
|
||||
ds.destroy();
|
||||
});
|
||||
this.dataSourceMap.clear();
|
||||
DataSourceManager.waitInitSchemaList.delete(this);
|
||||
}
|
||||
|
||||
public onDataChange(id: string, path: string, callback: (newVal: any) => void) {
|
||||
@ -288,5 +315,6 @@ class DataSourceManager extends EventEmitter {
|
||||
}
|
||||
|
||||
DataSourceManager.register('http', HttpDataSource as any);
|
||||
DataSourceManager.register('base', DataSource as any);
|
||||
|
||||
export default DataSourceManager;
|
||||
|
@ -62,13 +62,15 @@ export default class DataSource<T extends DataSourceSchema = DataSourceSchema> e
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const ObservedDataClass = options.ObservedDataClass || SimpleObservedData;
|
||||
if (this.app.platform === 'editor') {
|
||||
const mocks = cloneDeep(options.schema.mocks || []);
|
||||
// 编辑器中有mock使用mock,没有使用默认值
|
||||
this.mockData = options.schema.mocks?.find((mock) => mock.useInEditor)?.data || this.getDefaultData();
|
||||
this.mockData = mocks.find((mock) => mock.useInEditor)?.data || this.getDefaultData();
|
||||
data = cloneDeep(this.mockData);
|
||||
} else if (typeof options.useMock === 'boolean' && options.useMock) {
|
||||
const mocks = cloneDeep(options.schema.mocks || []);
|
||||
// 设置了使用mock就使用mock数据
|
||||
this.mockData = options.schema.mocks?.find((mock) => mock.enable)?.data;
|
||||
data = this.mockData || this.getDefaultData();
|
||||
this.mockData = mocks.find((mock) => mock.enable)?.data;
|
||||
data = cloneDeep(this.mockData) || this.getDefaultData();
|
||||
} else if (!options.initialData) {
|
||||
data = this.getDefaultData();
|
||||
} else {
|
||||
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||
*
|
||||
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
import pkg from './package.json';
|
||||
|
||||
export default defineConfig(({ mode }) => ({
|
||||
resolve: {
|
||||
alias: [{ find: /^@data-source/, replacement: path.join(__dirname, './src') }],
|
||||
},
|
||||
|
||||
build: {
|
||||
cssCodeSplit: false,
|
||||
sourcemap: false,
|
||||
minify: false,
|
||||
target: 'esnext',
|
||||
|
||||
lib: {
|
||||
entry: 'src/index.ts',
|
||||
name: 'TMagicDataSource',
|
||||
fileName: 'tmagic-data-source',
|
||||
},
|
||||
|
||||
rollupOptions: {
|
||||
// 确保外部化处理那些你不想打包进库的依赖
|
||||
external(id: string) {
|
||||
if (mode === 'umd' && id === 'lodash-es') {
|
||||
return false;
|
||||
}
|
||||
return Object.keys({
|
||||
...pkg.dependencies,
|
||||
...pkg.peerDependencies,
|
||||
}).some((k) => new RegExp(`^${k}`).test(id));
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.12",
|
||||
"name": "@tmagic/dep",
|
||||
"type": "module",
|
||||
"main": "dist/tmagic-dep.umd.cjs",
|
||||
@ -19,9 +19,6 @@
|
||||
"src"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@ -30,11 +27,6 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/Tencent/tmagic-editor.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.19.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"vite": "^6.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tmagic/schema": "workspace:*",
|
||||
"@tmagic/utils": "workspace:*",
|
||||
|
@ -103,9 +103,9 @@ export default class Watcher {
|
||||
* 删除所有target
|
||||
*/
|
||||
public clearTargets() {
|
||||
Object.keys(this.targetsList).forEach((key) => {
|
||||
for (const key of Object.keys(this.targetsList)) {
|
||||
delete this.targetsList[key];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,9 +137,9 @@ export default class Watcher {
|
||||
if (!type && !target.isCollectByDefault) {
|
||||
return;
|
||||
}
|
||||
nodes.forEach((node) => {
|
||||
for (const node of nodes) {
|
||||
cb({ node, target });
|
||||
});
|
||||
}
|
||||
},
|
||||
type,
|
||||
);
|
||||
@ -161,7 +161,7 @@ export default class Watcher {
|
||||
const clearedItemsNodeIds: (string | number)[] = [];
|
||||
traverseTarget(targetsList, (target) => {
|
||||
if (nodes) {
|
||||
nodes.forEach((node) => {
|
||||
for (const node of nodes) {
|
||||
target.removeDep(node[this.idProp]);
|
||||
|
||||
if (
|
||||
@ -172,7 +172,7 @@ export default class Watcher {
|
||||
clearedItemsNodeIds.push(node[this.idProp]);
|
||||
this.clear(node[this.childrenProp]);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
target.removeDep();
|
||||
}
|
||||
@ -202,26 +202,28 @@ export default class Watcher {
|
||||
key: fullKey,
|
||||
});
|
||||
} else if (!keyIsItems && Array.isArray(value)) {
|
||||
value.forEach((item, index) => {
|
||||
for (let i = 0, l = value.length; i < l; i++) {
|
||||
const item = value[i];
|
||||
if (isObject(item)) {
|
||||
collectTarget(item, `${fullKey}[${index}]`);
|
||||
collectTarget(item, `${fullKey}[${i}]`);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (isObject(value)) {
|
||||
collectTarget(value, fullKey);
|
||||
}
|
||||
|
||||
if (keyIsItems && deep && Array.isArray(value)) {
|
||||
value.forEach((child) => {
|
||||
for (const child of value) {
|
||||
this.collectItem(child, target, depExtendedData, deep);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Object.entries(config).forEach(([key, value]) => {
|
||||
if (typeof value === 'undefined' || value === '') return;
|
||||
for (const [key, value] of Object.entries(config)) {
|
||||
if (typeof value === 'undefined' || value === '') continue;
|
||||
|
||||
doCollect(key, value);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
collectTarget(node);
|
||||
@ -230,9 +232,9 @@ export default class Watcher {
|
||||
public removeTargetDep(target: Target, node: TargetNode, key?: string | number) {
|
||||
target.removeDep(node[this.idProp], key);
|
||||
if (typeof key === 'undefined' && Array.isArray(node[this.childrenProp]) && node[this.childrenProp].length) {
|
||||
node[this.childrenProp].forEach((item: TargetNode) => {
|
||||
for (const item of node[this.childrenProp] as TargetNode[]) {
|
||||
this.removeTargetDep(target, item, key);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,6 +185,10 @@ export const isDataSourceTarget = (
|
||||
value: any,
|
||||
hasArray = false,
|
||||
) => {
|
||||
if (!value || !['string', 'object'].includes(typeof value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (`${key}`.startsWith(NODE_CONDS_KEY)) {
|
||||
return false;
|
||||
}
|
||||
@ -259,20 +263,20 @@ export const createDataSourceCondTarget = (ds: Pick<DataSourceSchema, 'id' | 'fi
|
||||
isTarget: (key: string | number, value: any) => isDataSourceCondTarget(ds, key, value),
|
||||
});
|
||||
|
||||
export const createDataSourceMethodTarget = (ds: Pick<DataSourceSchema, 'id' | 'fields'>, initialDeps: DepData = {}) =>
|
||||
export const createDataSourceMethodTarget = (ds: Pick<DataSourceSchema, 'id' | 'methods'>, initialDeps: DepData = {}) =>
|
||||
new Target({
|
||||
type: DepTargetType.DATA_SOURCE_METHOD,
|
||||
id: ds.id,
|
||||
initialDeps,
|
||||
isTarget: (_key: string | number, value: any) => {
|
||||
// 使用data-source-method-select 可以配置出来
|
||||
if (!Array.isArray(value) || !ds) {
|
||||
if (!Array.isArray(value) || !ds?.methods) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [dsId, ...keys] = value;
|
||||
const [dsId, methodName] = value;
|
||||
|
||||
if (dsId !== ds.id || ds.fields?.find((field) => field.name === keys[0])) {
|
||||
if (!methodName || dsId !== ds.id || !ds.methods.find((field) => field.name === methodName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -285,12 +289,12 @@ export const traverseTarget = (
|
||||
cb: (target: Target) => void,
|
||||
type?: DepTargetType | string,
|
||||
) => {
|
||||
Object.values(targetsList).forEach((targets) => {
|
||||
Object.values(targets).forEach((target) => {
|
||||
for (const targets of Object.values(targetsList)) {
|
||||
for (const target of Object.values(targets)) {
|
||||
if (type && target.type !== type) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
cb(target);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||
*
|
||||
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
import pkg from './package.json';
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
sourcemap: false,
|
||||
minify: false,
|
||||
target: 'esnext',
|
||||
|
||||
lib: {
|
||||
entry: 'src/index.ts',
|
||||
name: 'TMagicDep',
|
||||
fileName: 'tmagic-dep',
|
||||
},
|
||||
|
||||
rollupOptions: {
|
||||
// 确保外部化处理那些你不想打包进库的依赖
|
||||
external(id: string) {
|
||||
return Object.keys(pkg.peerDependencies).some((k) => new RegExp(`^${k}`).test(id));
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.12",
|
||||
"name": "@tmagic/design",
|
||||
"type": "module",
|
||||
"sideEffects": [
|
||||
@ -23,9 +23,6 @@
|
||||
"src"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@ -44,13 +41,6 @@
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.19.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vue/compiler-sfc": "^3.5.12",
|
||||
"rimraf": "^3.0.2",
|
||||
"vite": "^6.0.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": ">=3.5.0",
|
||||
"typescript": "*"
|
||||
|
@ -42,7 +42,7 @@ const ui = getDesignConfig('components')?.autocomplete;
|
||||
|
||||
const uiComponent = ui?.component || 'el-autocomplete';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<AutocompleteProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'select', 'update:modelValue']);
|
||||
|
||||
|
@ -19,5 +19,5 @@ const props = defineProps<BadgeProps>();
|
||||
const ui = getDesignConfig('components')?.badge;
|
||||
const uiComponent = ui?.component || 'el-badge';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<BadgeProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -22,7 +22,7 @@ const ui = getDesignConfig('components')?.button;
|
||||
|
||||
const uiComponent = ui?.component || 'el-button';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<ButtonProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['click']);
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<component class="tmagic-design-card" :is="uiComponent" v-bind="uiProps">
|
||||
<template #header>
|
||||
<template #header v-if="$slots.header">
|
||||
<slot name="header" class="header"></slot>
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
<template #default v-if="$slots.default">
|
||||
<slot name="default"></slot>
|
||||
</template>
|
||||
</component>
|
||||
@ -26,5 +26,5 @@ const ui = getDesignConfig('components')?.card;
|
||||
|
||||
const uiComponent = ui?.component || 'el-card';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<CardProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -25,7 +25,7 @@ const ui = getDesignConfig('components')?.cascader;
|
||||
|
||||
const uiComponent = ui?.component || 'el-cascader';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<CascaderProps>(() => ui?.props(props) || props);
|
||||
|
||||
const cascader = ref<any>();
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
@update:modelValue="updateModelValue"
|
||||
@change="changeHandler"
|
||||
>
|
||||
<template #default>
|
||||
<template #default v-if="$slots.default">
|
||||
<slot></slot>
|
||||
</template>
|
||||
</component>
|
||||
@ -31,7 +31,7 @@ const ui = getDesignConfig('components')?.checkbox;
|
||||
|
||||
const uiComponent = ui?.component || 'el-checkbox';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<CheckboxProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -26,7 +26,7 @@ const ui = getDesignConfig('components')?.checkboxGroup;
|
||||
|
||||
const uiComponent = ui?.component || 'el-checkbox-group';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<CheckboxGroupProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.col;
|
||||
|
||||
const uiComponent = ui?.component || 'el-col';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<ColProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -26,7 +26,7 @@ const ui = getDesignConfig('components')?.collapse;
|
||||
|
||||
const uiComponent = ui?.component || 'el-collapse';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<CollapseProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -32,7 +32,7 @@ const ui = getDesignConfig('components')?.collapseItem;
|
||||
|
||||
const uiComponent = ui?.component || 'el-collapse-item';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<CollapseItemProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -28,7 +28,7 @@ const ui = getDesignConfig('components')?.colorPicker;
|
||||
|
||||
const uiComponent = ui?.component || 'el-color-picker';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<ColorPickerProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -27,7 +27,7 @@ const ui = getDesignConfig('components')?.datePicker;
|
||||
|
||||
const uiComponent = ui?.component || 'el-date-picker';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<DatePickerProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -32,7 +32,7 @@ const ui = getDesignConfig('components')?.dialog;
|
||||
|
||||
const uiComponent = ui?.component || 'el-dialog';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<DialogProps>(() => ui?.props(props) || props);
|
||||
|
||||
const closeHandler = (...args: any[]) => {
|
||||
emit('close', ...args);
|
||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.divider;
|
||||
|
||||
const uiComponent = ui?.component || 'el-divider';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<DividerProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -40,7 +40,7 @@ const ui = getDesignConfig('components')?.drawer;
|
||||
|
||||
const uiComponent = ui?.component || 'el-drawer';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<DrawerProps>(() => ui?.props(props) || props);
|
||||
|
||||
const drawer = ref<any>();
|
||||
|
||||
|
@ -24,7 +24,7 @@ const ui = getDesignConfig('components')?.dropdown;
|
||||
|
||||
const uiComponent = ui?.component || 'el-dropdown';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<DropdownProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['command']);
|
||||
|
||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.dropdownItem;
|
||||
|
||||
const uiComponent = ui?.component || 'el-dropdown-item';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<DropdownItemProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -26,7 +26,7 @@ const ui = getDesignConfig('components')?.form;
|
||||
|
||||
const uiComponent = ui?.component || 'el-form';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<FormProps>(() => ui?.props(props) || props);
|
||||
|
||||
const form = ref<any>();
|
||||
|
||||
|
@ -23,5 +23,5 @@ const ui = getDesignConfig('components')?.formItem;
|
||||
|
||||
const uiComponent = ui?.component || 'el-form-item';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<FormItemProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -17,5 +17,5 @@ defineOptions({
|
||||
const ui = getDesignConfig('components')?.icon;
|
||||
const uiComponent = ui?.component || 'el-icon';
|
||||
const props = defineProps<IconProps>();
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<IconProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -39,7 +39,7 @@ const ui = getDesignConfig('components')?.input;
|
||||
|
||||
const uiComponent = ui?.component || 'el-input';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<InputProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'input', 'update:modelValue']);
|
||||
|
||||
|
@ -25,7 +25,7 @@ const ui = getDesignConfig('components')?.inputNumber;
|
||||
|
||||
const uiComponent = ui?.component || 'el-input-number';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<InputNumberProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'input', 'update:modelValue']);
|
||||
|
||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.option;
|
||||
|
||||
const uiComponent = ui?.component || 'el-option';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<OptionProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -20,7 +20,7 @@ const ui = getDesignConfig('components')?.optionGroup;
|
||||
|
||||
const uiComponent = ui?.component || 'el-option-group';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<OptionGroupProps>(() => ui?.props(props) || props);
|
||||
|
||||
const optionGroup = ref<any>();
|
||||
</script>
|
||||
|
@ -27,7 +27,7 @@ const ui = getDesignConfig('components')?.pagination;
|
||||
|
||||
const uiComponent = ui?.component || 'el-pagination';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<PaginationProps>(() => ui?.props(props) || props);
|
||||
|
||||
const handleSizeChange = (...args: any[]) => {
|
||||
emit('size-change', ...args);
|
||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.radio;
|
||||
|
||||
const uiComponent = ui?.component || 'el-radio';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<RadioProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.radioButton;
|
||||
|
||||
const uiComponent = ui?.component || 'el-radio-button';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<RadioButtonProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -26,7 +26,7 @@ const ui = getDesignConfig('components')?.radioGroup;
|
||||
|
||||
const uiComponent = ui?.component || 'el-radio-group';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<RadioGroupProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -31,7 +31,7 @@ const ui = getDesignConfig('components')?.select;
|
||||
|
||||
const uiComponent = ui?.component || 'el-select';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<SelectProps>(() => ui?.props(props) || props);
|
||||
|
||||
const select = ref<any>();
|
||||
|
||||
|
@ -26,5 +26,5 @@ const ui = getDesignConfig('components')?.step;
|
||||
|
||||
const uiComponent = ui?.component || 'el-step';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<StepProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.steps;
|
||||
|
||||
const uiComponent = ui?.component || 'el-steps';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<StepsProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -28,7 +28,7 @@ const ui = getDesignConfig('components')?.switch;
|
||||
|
||||
const uiComponent = ui?.component || 'el-switch';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<SwitchProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -26,5 +26,5 @@ const ui = getDesignConfig('components')?.tabPane;
|
||||
|
||||
const uiComponent = ui?.component || 'el-tab-pane';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<TabPaneProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -33,7 +33,7 @@ const ui = getDesignConfig('components')?.table;
|
||||
|
||||
const uiComponent = ui?.component || 'el-table';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<TableProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['select', 'sort-change', 'expand-change', 'cell-click']);
|
||||
|
||||
|
@ -23,5 +23,5 @@ const ui = getDesignConfig('components')?.tableColumn;
|
||||
|
||||
const uiComponent = ui?.component || 'el-table-column';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<TableColumnProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -30,7 +30,7 @@ const ui = getDesignConfig('components')?.tabs;
|
||||
|
||||
const uiComponent = ui?.component || 'el-tabs';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<TabsProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['tab-click', 'tab-add', 'tab-remove', 'update:model-value']);
|
||||
|
||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.tag;
|
||||
|
||||
const uiComponent = ui?.component || 'el-tag';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<TagProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -25,7 +25,7 @@ const ui = getDesignConfig('components')?.timePicker;
|
||||
|
||||
const uiComponent = ui?.component || 'el-time-picker';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<TimePickerProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits(['change', 'update:modelValue']);
|
||||
|
||||
|
@ -23,5 +23,5 @@ const ui = getDesignConfig('components')?.tooltip;
|
||||
|
||||
const uiComponent = ui?.component || 'el-tooltip';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<TooltipProps>(() => ui?.props(props) || props);
|
||||
</script>
|
||||
|
@ -35,7 +35,7 @@ const ui = getDesignConfig('components')?.tree;
|
||||
|
||||
const uiComponent = ui?.component || 'el-tree';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<TreeProps>(() => ui?.props(props) || props);
|
||||
|
||||
const emit = defineEmits([
|
||||
'node-click',
|
||||
|
@ -29,7 +29,7 @@ const ui = getDesignConfig('components')?.upload;
|
||||
|
||||
const uiComponent = ui?.component || 'el-upload';
|
||||
|
||||
const uiProps = computed(() => ui?.props(props) || props);
|
||||
const uiProps = computed<UploadProps>(() => ui?.props(props) || props);
|
||||
|
||||
const upload = ref<any>();
|
||||
|
||||
|
@ -125,7 +125,7 @@ export default {
|
||||
tMagicMessageBox.close = options.messageBox?.close;
|
||||
}
|
||||
|
||||
if (options.loading) {
|
||||
if (options.loading && !app.directive('loading')) {
|
||||
app.directive('loading', options.loading);
|
||||
}
|
||||
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||
*
|
||||
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
|
||||
import pkg from './package.json';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
|
||||
build: {
|
||||
cssCodeSplit: false,
|
||||
sourcemap: false,
|
||||
minify: false,
|
||||
target: 'esnext',
|
||||
|
||||
lib: {
|
||||
entry: 'src/index.ts',
|
||||
name: 'TMagicDesign',
|
||||
fileName: 'tmagic-design',
|
||||
cssFileName: 'style',
|
||||
},
|
||||
|
||||
rollupOptions: {
|
||||
// 确保外部化处理那些你不想打包进库的依赖
|
||||
external(id: string) {
|
||||
return Object.keys(pkg.peerDependencies).some((k) => new RegExp(`^${k}`).test(id));
|
||||
},
|
||||
|
||||
output: {
|
||||
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
|
||||
globals: {
|
||||
vue: 'Vue',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.12",
|
||||
"name": "@tmagic/editor",
|
||||
"type": "module",
|
||||
"sideEffects": [
|
||||
@ -28,9 +28,6 @@
|
||||
"src"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "vite build"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@ -70,17 +67,10 @@
|
||||
"devDependencies": {
|
||||
"@types/events": "^3.0.0",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@types/node": "^18.19.0",
|
||||
"@types/serialize-javascript": "^5.0.1",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vue/compiler-sfc": "^3.5.12",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"rimraf": "^3.0.2",
|
||||
"sass": "^1.83.0",
|
||||
"tsc-alias": "^1.8.5",
|
||||
"type-fest": "^4.10.3",
|
||||
"vite": "^6.0.3"
|
||||
"type-fest": "^4.10.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tmagic/core": "workspace:*",
|
||||
|
@ -74,9 +74,9 @@ import {
|
||||
import FloatingBox from '@editor/components/FloatingBox.vue';
|
||||
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
|
||||
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import { useWindowRect } from '@editor/hooks/use-window-rect';
|
||||
import CodeEditor from '@editor/layouts/CodeEditor.vue';
|
||||
import type { Services } from '@editor/type';
|
||||
import { getEditorConfig } from '@editor/utils/config';
|
||||
|
||||
defineOptions({
|
||||
@ -97,21 +97,21 @@ const emit = defineEmits<{
|
||||
submit: [values: CodeBlockContent, eventData: ContainerChangeEventData];
|
||||
}>();
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const { codeBlockService, uiService } = useServices();
|
||||
|
||||
const { height: codeBlockEditorHeight } = useEditorContentHeight();
|
||||
|
||||
const difVisible = ref(false);
|
||||
const { rect: windowRect } = useWindowRect();
|
||||
|
||||
const magicVsEditor = useTemplateRef<InstanceType<typeof CodeEditor>>('magicVsEditor');
|
||||
const magicVsEditorRef = useTemplateRef<InstanceType<typeof CodeEditor>>('magicVsEditor');
|
||||
|
||||
const diffChange = () => {
|
||||
if (!magicVsEditor.value || !formBox.value?.form) {
|
||||
if (!magicVsEditorRef.value || !formBox.value?.form) {
|
||||
return;
|
||||
}
|
||||
|
||||
formBox.value.form.values.content = magicVsEditor.value.getEditorValue();
|
||||
formBox.value.form.values.content = magicVsEditorRef.value.getEditorValue();
|
||||
|
||||
difVisible.value = false;
|
||||
};
|
||||
@ -192,7 +192,7 @@ const functionConfig = computed<FormConfig>(() => [
|
||||
label: '描述',
|
||||
name: 'extra',
|
||||
},
|
||||
services?.codeBlockService.getParamsColConfig() || defaultParamColConfig,
|
||||
codeBlockService.getParamsColConfig() || defaultParamColConfig,
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -259,7 +259,7 @@ const closedHandler = () => {
|
||||
};
|
||||
|
||||
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
||||
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
|
||||
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
|
||||
|
||||
defineExpose({
|
||||
async show() {
|
||||
|
@ -32,7 +32,7 @@ const props = defineProps<{
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const form = useTemplateRef<InstanceType<typeof MForm>>('form');
|
||||
const formRef = useTemplateRef<InstanceType<typeof MForm>>('form');
|
||||
|
||||
const getFormConfig = (items: FormConfig = []) => [
|
||||
{
|
||||
@ -61,7 +61,7 @@ const codeParamsConfig = computed(() =>
|
||||
*/
|
||||
const onParamsChangeHandler = async (v: FormValue, eventData: ContainerChangeEventData) => {
|
||||
try {
|
||||
const value = await form.value?.submitForm(true);
|
||||
const value = await formRef.value?.submitForm(true);
|
||||
emit('change', value, eventData);
|
||||
} catch (e) {
|
||||
error(e);
|
||||
|
@ -37,7 +37,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef } from 'vue';
|
||||
import { computed, nextTick, onBeforeUnmount, onMounted, type Ref, ref, useTemplateRef } from 'vue';
|
||||
|
||||
import { useZIndex } from '@tmagic/design';
|
||||
|
||||
@ -69,11 +69,11 @@ const emit = defineEmits<{
|
||||
mouseenter: [];
|
||||
}>();
|
||||
|
||||
const menu = useTemplateRef<HTMLDivElement>('menu');
|
||||
const buttons = useTemplateRef<InstanceType<typeof ToolButton>[]>('buttons');
|
||||
const subMenu = useTemplateRef<any>('subMenu');
|
||||
const menuEl = useTemplateRef<HTMLDivElement>('menu');
|
||||
const buttonRefs = useTemplateRef<InstanceType<typeof ToolButton>[]>('buttons');
|
||||
const subMenuRef = useTemplateRef<any>('subMenu');
|
||||
const visible = ref(false);
|
||||
const subMenuData = ref<(MenuButton | MenuComponent)[]>([]);
|
||||
const subMenuData: Ref<(MenuButton | MenuComponent)[]> = ref<(MenuButton | MenuComponent)[]>([]);
|
||||
const zIndex = useZIndex();
|
||||
const curZIndex = ref<number>(0);
|
||||
|
||||
@ -88,13 +88,13 @@ const menuStyle = computed(() => ({
|
||||
zIndex: curZIndex.value,
|
||||
}));
|
||||
|
||||
const contains = (el: HTMLElement) => menu.value?.contains(el) || subMenu.value?.contains(el);
|
||||
const contains = (el: HTMLElement) => menuEl.value?.contains(el) || subMenuRef.value?.contains(el);
|
||||
|
||||
const hide = () => {
|
||||
if (!visible.value) return;
|
||||
|
||||
visible.value = false;
|
||||
subMenu.value?.hide();
|
||||
subMenuRef.value?.hide();
|
||||
|
||||
emit('hide');
|
||||
};
|
||||
@ -121,7 +121,7 @@ const outsideClickHideHandler = (e: MouseEvent) => {
|
||||
};
|
||||
|
||||
const setPosition = (e: { clientY: number; clientX: number }) => {
|
||||
const menuHeight = menu.value?.clientHeight || 0;
|
||||
const menuHeight = menuEl.value?.clientHeight || 0;
|
||||
|
||||
let top = e.clientY;
|
||||
if (menuHeight + e.clientY > document.body.clientHeight) {
|
||||
@ -158,15 +158,15 @@ const showSubMenu = (item: MenuButton | MenuComponent, index: number) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (menu.value) {
|
||||
if (menuEl.value) {
|
||||
// 将子菜单放置在按钮右侧,与按钮齐平
|
||||
let y = menu.value.offsetTop;
|
||||
if (buttons.value?.[index].$el) {
|
||||
const rect = buttons.value?.[index].$el.getBoundingClientRect();
|
||||
let y = menuEl.value.offsetTop;
|
||||
if (buttonRefs.value?.[index].$el) {
|
||||
const rect = buttonRefs.value?.[index].$el.getBoundingClientRect();
|
||||
y = rect.top;
|
||||
}
|
||||
subMenu.value?.show({
|
||||
clientX: menu.value.offsetLeft + menu.value.clientWidth - 2,
|
||||
subMenuRef.value?.show({
|
||||
clientX: menuEl.value.offsetLeft + menuEl.value.clientWidth - 2,
|
||||
clientY: y,
|
||||
});
|
||||
}
|
||||
@ -190,7 +190,7 @@ onBeforeUnmount(() => {
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
menu,
|
||||
menu: menuEl,
|
||||
menuPosition,
|
||||
hide,
|
||||
show,
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<Teleport to="body" v-if="visible">
|
||||
<div ref="target" class="m-editor-float-box" :style="{ ...style, zIndex: curZIndex }" @mousedown="nextZIndex">
|
||||
<div ref="titleEl" class="m-editor-float-box-title">
|
||||
<div ref="title" class="m-editor-float-box-title">
|
||||
<slot name="title">
|
||||
<span>{{ title }}</span>
|
||||
</slot>
|
||||
@ -17,14 +17,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, inject, nextTick, onBeforeUnmount, provide, ref, useTemplateRef, watch } from 'vue';
|
||||
import { computed, nextTick, onBeforeUnmount, provide, ref, useTemplateRef, watch } from 'vue';
|
||||
import { Close } from '@element-plus/icons-vue';
|
||||
import VanillaMoveable from 'moveable';
|
||||
|
||||
import { TMagicButton, useZIndex } from '@tmagic/design';
|
||||
|
||||
import MIcon from '@editor/components/Icon.vue';
|
||||
import type { Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
|
||||
interface Position {
|
||||
left: number;
|
||||
@ -47,8 +47,8 @@ const props = withDefaults(
|
||||
},
|
||||
);
|
||||
|
||||
const target = useTemplateRef<HTMLDivElement>('target');
|
||||
const titleEl = useTemplateRef<HTMLDivElement>('titleEl');
|
||||
const targetEl = useTemplateRef<HTMLDivElement>('target');
|
||||
const titleEl = useTemplateRef<HTMLDivElement>('title');
|
||||
|
||||
const zIndex = useZIndex();
|
||||
const curZIndex = ref<number>(0);
|
||||
@ -59,15 +59,15 @@ const bodyHeight = computed(() => {
|
||||
return height.value - titleHeight.value;
|
||||
}
|
||||
|
||||
if (target.value) {
|
||||
return target.value.clientHeight - titleHeight.value;
|
||||
if (targetEl.value) {
|
||||
return targetEl.value.clientHeight - titleHeight.value;
|
||||
}
|
||||
|
||||
return 'auto';
|
||||
});
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const frameworkWidth = computed(() => services?.uiService.get('frameworkRect').width || 0);
|
||||
const { uiService } = useServices();
|
||||
const frameworkWidth = computed(() => uiService.get('frameworkRect').width || 0);
|
||||
const style = computed(() => {
|
||||
let { left } = props.position;
|
||||
if (width.value) {
|
||||
@ -87,7 +87,7 @@ let moveable: VanillaMoveable | null = null;
|
||||
const initMoveable = () => {
|
||||
moveable = new VanillaMoveable(globalThis.document.body, {
|
||||
className: 'm-editor-floating-box-moveable',
|
||||
target: target.value,
|
||||
target: targetEl.value,
|
||||
draggable: true,
|
||||
resizable: true,
|
||||
edge: true,
|
||||
@ -126,7 +126,7 @@ watch(
|
||||
await nextTick();
|
||||
curZIndex.value = zIndex.nextZIndex();
|
||||
|
||||
const targetRect = target.value?.getBoundingClientRect();
|
||||
const targetRect = targetEl.value?.getBoundingClientRect();
|
||||
if (targetRect) {
|
||||
width.value = targetRect.width;
|
||||
height.value = targetRect.height;
|
||||
@ -168,11 +168,11 @@ const nextZIndex = () => {
|
||||
curZIndex.value = zIndex.nextZIndex();
|
||||
};
|
||||
|
||||
provide('parentFloating', target);
|
||||
provide('parentFloating', targetEl);
|
||||
|
||||
defineExpose({
|
||||
bodyHeight,
|
||||
target,
|
||||
target: targetEl,
|
||||
titleEl,
|
||||
});
|
||||
</script>
|
||||
|
@ -18,6 +18,6 @@ const emit = defineEmits<{
|
||||
change: [e: OnDrag];
|
||||
}>();
|
||||
|
||||
const target = useTemplateRef<HTMLSpanElement>('target');
|
||||
const { isDragging } = useGetSo(target, emit);
|
||||
const targetEl = useTemplateRef<HTMLSpanElement>('target');
|
||||
const { isDragging } = useGetSo(targetEl, emit);
|
||||
</script>
|
||||
|
@ -21,8 +21,8 @@ const props = defineProps<{
|
||||
|
||||
const emit = defineEmits(['scroll']);
|
||||
|
||||
const bar = useTemplateRef<HTMLDivElement>('bar');
|
||||
const thumb = useTemplateRef<HTMLDivElement>('thumb');
|
||||
const barEl = useTemplateRef<HTMLDivElement>('bar');
|
||||
const thumbEl = useTemplateRef<HTMLDivElement>('thumb');
|
||||
|
||||
const thumbSize = computed(() => props.size * (props.size / props.scrollSize));
|
||||
const thumbPos = computed(() => (props.pos / props.scrollSize) * props.size);
|
||||
@ -35,9 +35,8 @@ const thumbStyle = computed(() => ({
|
||||
let gesto: Gesto;
|
||||
|
||||
onMounted(() => {
|
||||
if (!thumb.value) return;
|
||||
const thumbEl = thumb.value;
|
||||
gesto = new Gesto(thumbEl, {
|
||||
if (!thumbEl.value) return;
|
||||
gesto = new Gesto(thumbEl.value, {
|
||||
container: window,
|
||||
});
|
||||
|
||||
@ -50,12 +49,12 @@ onMounted(() => {
|
||||
scrollBy(getDelta(e));
|
||||
});
|
||||
|
||||
bar.value?.addEventListener('wheel', wheelHandler, false);
|
||||
barEl.value?.addEventListener('wheel', wheelHandler, false);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (gesto) gesto.off();
|
||||
bar.value?.removeEventListener('wheel', wheelHandler, false);
|
||||
barEl.value?.removeEventListener('wheel', wheelHandler, false);
|
||||
});
|
||||
|
||||
const wheelHandler = (e: WheelEvent) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="m-editor-scroll-viewer-container" ref="container">
|
||||
<div ref="el" :style="style">
|
||||
<div ref="target" :style="style">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
@ -63,8 +63,8 @@ const props = withDefaults(
|
||||
},
|
||||
);
|
||||
|
||||
const container = useTemplateRef<HTMLDivElement>('container');
|
||||
const el = useTemplateRef<HTMLDivElement>('el');
|
||||
const containerEl = useTemplateRef<HTMLDivElement>('container');
|
||||
const el = useTemplateRef<HTMLDivElement>('target');
|
||||
const style = computed(
|
||||
() => `
|
||||
width: ${isNumber(`${props.width}`) ? `${props.width}px` : props.width};
|
||||
@ -80,9 +80,9 @@ const scrollHeight = ref(0);
|
||||
let scrollViewer: ScrollViewer;
|
||||
|
||||
onMounted(() => {
|
||||
if (!container.value || !el.value) return;
|
||||
if (!containerEl.value || !el.value) return;
|
||||
scrollViewer = new ScrollViewer({
|
||||
container: container.value,
|
||||
container: containerEl.value,
|
||||
target: el.value,
|
||||
zoom: props.zoom,
|
||||
correctionScrollSize: props.correctionScrollSize,
|
||||
@ -123,6 +123,6 @@ const hScrollHandler = (delta: number) => {
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
container,
|
||||
container: containerEl,
|
||||
});
|
||||
</script>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div ref="el" class="m-editor-layout" :style="`min-width: ${props.minCenter + props.minLeft + props.minRight}px`">
|
||||
<div ref="target" class="m-editor-layout" :style="`min-width: ${props.minCenter + props.minLeft + props.minRight}px`">
|
||||
<template v-if="hasLeft && $slots.left">
|
||||
<div class="m-editor-layout-left" :class="leftClass" :style="`width: ${left}px`">
|
||||
<slot name="left"></slot>
|
||||
@ -45,13 +45,13 @@ const props = withDefaults(
|
||||
centerClass?: string;
|
||||
}>(),
|
||||
{
|
||||
minLeft: 46,
|
||||
minLeft: 1,
|
||||
minRight: 1,
|
||||
minCenter: 5,
|
||||
},
|
||||
);
|
||||
|
||||
const el = useTemplateRef<HTMLElement>('el');
|
||||
const el = useTemplateRef<HTMLElement>('target');
|
||||
|
||||
const hasLeft = computed(() => typeof props.left !== 'undefined');
|
||||
const hasRight = computed(() => typeof props.right !== 'undefined');
|
||||
@ -65,12 +65,21 @@ const getCenterWidth = (l = 0, r = 0) => {
|
||||
let center = clientWidth - left - right;
|
||||
|
||||
if (center < props.minCenter) {
|
||||
const diff = props.minCenter - center;
|
||||
|
||||
center = props.minCenter;
|
||||
if (right > center + props.minRight) {
|
||||
right = clientWidth - left - center;
|
||||
} else {
|
||||
|
||||
if (right - diff < props.minRight) {
|
||||
right = props.minRight;
|
||||
left = clientWidth - right - center;
|
||||
} else {
|
||||
right -= diff;
|
||||
}
|
||||
|
||||
left = clientWidth - right - center;
|
||||
|
||||
if (left < props.minLeft) {
|
||||
left -= diff / 2;
|
||||
right -= diff / 2;
|
||||
}
|
||||
}
|
||||
return {
|
||||
@ -86,8 +95,8 @@ const widthChange = (width: number) => {
|
||||
}
|
||||
|
||||
clientWidth = width;
|
||||
let left = props.left || 0;
|
||||
let right = props.right || 0;
|
||||
let left = props.left || props.minLeft || 0;
|
||||
let right = props.right || props.minRight || 0;
|
||||
|
||||
if (left > clientWidth) {
|
||||
left = clientWidth / 3;
|
||||
|
@ -49,7 +49,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { ArrowDown } from '@element-plus/icons-vue';
|
||||
|
||||
import {
|
||||
@ -62,8 +62,10 @@ import {
|
||||
TMagicTooltip,
|
||||
} from '@tmagic/design';
|
||||
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
|
||||
import MIcon from '../components/Icon.vue';
|
||||
import type { MenuButton, MenuComponent, Services } from '../type';
|
||||
import type { MenuButton, MenuComponent } from '../type';
|
||||
|
||||
defineOptions({
|
||||
name: 'MEditorToolButton',
|
||||
@ -82,7 +84,7 @@ const props = withDefaults(
|
||||
eventType: 'click',
|
||||
},
|
||||
);
|
||||
const services = inject<Services>('services');
|
||||
const services = useServices();
|
||||
|
||||
const disabled = computed(() => {
|
||||
if (typeof props.data === 'string') return false;
|
||||
@ -104,7 +106,7 @@ const display = computed(() => {
|
||||
|
||||
const buttonHandler = (item: MenuButton | MenuComponent, event: MouseEvent) => {
|
||||
if (disabled.value) return;
|
||||
if (typeof (item as MenuButton).handler === 'function' && services) {
|
||||
if (typeof (item as MenuButton).handler === 'function') {
|
||||
(item as MenuButton).handler?.(services, event);
|
||||
}
|
||||
};
|
||||
|
@ -15,7 +15,7 @@
|
||||
class="tree-node"
|
||||
:class="{ selected, expanded }"
|
||||
:style="`padding-left: ${indent}px`"
|
||||
@contextmenu="nodeContentmenuHandler"
|
||||
@contextmenu="nodeContextmenuHandler"
|
||||
@mouseenter="mouseenterHandler"
|
||||
>
|
||||
<MIcon
|
||||
@ -139,7 +139,7 @@ const handleDragEnd = (event: DragEvent) => {
|
||||
treeEmit?.('node-dragend', event, props.data);
|
||||
};
|
||||
|
||||
const nodeContentmenuHandler = (event: MouseEvent) => {
|
||||
const nodeContextmenuHandler = (event: MouseEvent) => {
|
||||
treeEmit?.('node-contextmenu', event, props.data);
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, watch } from 'vue';
|
||||
import { computed, watch } from 'vue';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
|
||||
import { HookCodeType, HookType } from '@tmagic/core';
|
||||
@ -24,7 +24,7 @@ import { TMagicCard } from '@tmagic/design';
|
||||
import type { ContainerChangeEventData, FieldProps, FormItem, GroupListConfig } from '@tmagic/form';
|
||||
import { MContainer } from '@tmagic/form';
|
||||
|
||||
import type { Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
|
||||
defineOptions({
|
||||
name: 'MFieldsCodeSelect',
|
||||
@ -34,7 +34,7 @@ const emit = defineEmits<{
|
||||
change: [v: any, eventData: ContainerChangeEventData];
|
||||
}>();
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const { dataSourceService, codeBlockService } = useServices();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<
|
||||
@ -59,7 +59,7 @@ const codeConfig = computed<GroupListConfig>(() => ({
|
||||
return index;
|
||||
}
|
||||
|
||||
const ds = services?.dataSourceService.getDataSourceById(model.codeId[0]);
|
||||
const ds = dataSourceService.getDataSourceById(model.codeId[0]);
|
||||
return `${ds?.title} / ${model.codeId[1]}`;
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ const codeConfig = computed<GroupListConfig>(() => ({
|
||||
span: 18,
|
||||
labelWidth: 0,
|
||||
display: (mForm, { model }) => model.codeType !== HookCodeType.DATA_SOURCE_METHOD,
|
||||
notEditable: () => !services?.codeBlockService.getEditStatus(),
|
||||
notEditable: () => !codeBlockService.getEditStatus(),
|
||||
},
|
||||
{
|
||||
type: 'data-source-method-select',
|
||||
@ -106,7 +106,7 @@ const codeConfig = computed<GroupListConfig>(() => ({
|
||||
span: 18,
|
||||
labelWidth: 0,
|
||||
display: (mForm, { model }) => model.codeType === HookCodeType.DATA_SOURCE_METHOD,
|
||||
notEditable: () => !services?.dataSourceService.get('editable'),
|
||||
notEditable: () => !dataSourceService.get('editable'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -52,7 +52,8 @@ import {
|
||||
|
||||
import CodeParams from '@editor/components/CodeParams.vue';
|
||||
import MIcon from '@editor/components/Icon.vue';
|
||||
import type { CodeParamStatement, CodeSelectColConfig, EventBus, Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import type { CodeParamStatement, CodeSelectColConfig, EventBus } from '@editor/type';
|
||||
import { SideItemKey } from '@editor/type';
|
||||
|
||||
defineOptions({
|
||||
@ -60,7 +61,7 @@ defineOptions({
|
||||
});
|
||||
|
||||
const mForm = inject<FormState | undefined>('mForm');
|
||||
const services = inject<Services>('services');
|
||||
const { codeBlockService, uiService } = useServices();
|
||||
const eventBus = inject<EventBus>('eventBus');
|
||||
const emit = defineEmits<{
|
||||
change: [v: any, eventData: ContainerChangeEventData];
|
||||
@ -73,7 +74,7 @@ const props = withDefaults(defineProps<FieldProps<CodeSelectColConfig>>(), {
|
||||
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
|
||||
|
||||
const hasCodeBlockSidePanel = computed(() =>
|
||||
(services?.uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.CODE_BLOCK),
|
||||
(uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.CODE_BLOCK),
|
||||
);
|
||||
|
||||
/**
|
||||
@ -94,7 +95,7 @@ const getParamItemsConfig = (codeId?: Id): CodeParamStatement[] => {
|
||||
}));
|
||||
};
|
||||
|
||||
const codeDsl = computed(() => services?.codeBlockService.getCodeDsl());
|
||||
const codeDsl = computed(() => codeBlockService.getCodeDsl());
|
||||
const paramsConfig = ref<CodeParamStatement[]>(getParamItemsConfig(props.model[props.name]));
|
||||
|
||||
watch(
|
||||
|
@ -27,12 +27,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, inject } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { getDesignConfig, TMagicSelect } from '@tmagic/design';
|
||||
import type { FieldProps } from '@tmagic/form';
|
||||
|
||||
import type { CondOpSelectConfig, Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import type { CondOpSelectConfig } from '@editor/type';
|
||||
import { arrayOptions, eqOptions, numberOptions } from '@editor/utils';
|
||||
|
||||
defineOptions({
|
||||
@ -43,7 +44,7 @@ const emit = defineEmits<{
|
||||
change: [value: string];
|
||||
}>();
|
||||
|
||||
const { dataSourceService } = inject<Services>('services') || {};
|
||||
const { dataSourceService } = useServices();
|
||||
|
||||
const props = defineProps<FieldProps<CondOpSelectConfig>>();
|
||||
|
||||
@ -52,7 +53,7 @@ const optionComponent = getDesignConfig('components')?.option;
|
||||
const options = computed(() => {
|
||||
const [id, ...fieldNames] = [...(props.config.parentFields || []), ...props.model.field];
|
||||
|
||||
const ds = dataSourceService?.getDataSourceById(id);
|
||||
const ds = dataSourceService.getDataSourceById(id);
|
||||
|
||||
let fields = ds?.fields || [];
|
||||
let type = '';
|
||||
|
@ -69,13 +69,14 @@
|
||||
import { computed, inject, ref, watch } from 'vue';
|
||||
import { Edit, View } from '@element-plus/icons-vue';
|
||||
|
||||
import { DataSourceFieldType } from '@tmagic/core';
|
||||
import type { DataSourceFieldType } from '@tmagic/core';
|
||||
import { getDesignConfig, TMagicButton, TMagicCascader, TMagicSelect, TMagicTooltip } from '@tmagic/design';
|
||||
import { type FilterFunction, filterFunction, type FormState, type SelectOption } from '@tmagic/form';
|
||||
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
||||
|
||||
import MIcon from '@editor/components/Icon.vue';
|
||||
import { type EventBus, type Services, SideItemKey } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import { type EventBus, SideItemKey } from '@editor/type';
|
||||
import { getCascaderOptionsFromFields, removeDataSourceFieldPrefix } from '@editor/utils';
|
||||
|
||||
const props = defineProps<{
|
||||
@ -101,11 +102,11 @@ const modelValue = defineModel<string[] | any>('modelValue', { default: [] });
|
||||
|
||||
const optionComponent = getDesignConfig('components')?.option;
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const { dataSourceService, uiService } = useServices();
|
||||
const mForm = inject<FormState | undefined>('mForm');
|
||||
const eventBus = inject<EventBus>('eventBus');
|
||||
|
||||
const dataSources = computed(() => services?.dataSourceService.get('dataSources') || []);
|
||||
const dataSources = computed(() => dataSourceService.get('dataSources') || []);
|
||||
|
||||
const valueIsKey = computed(() => props.value === 'key');
|
||||
const notEditable = computed(() => filterFunction(mForm, props.notEditable, props));
|
||||
@ -172,7 +173,7 @@ const onChangeHandler = (v: string[] = []) => {
|
||||
};
|
||||
|
||||
const hasDataSourceSidePanel = computed(() =>
|
||||
(services?.uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.DATA_SOURCE),
|
||||
uiService.get('sideBarItems').find((item) => item.$key === SideItemKey.DATA_SOURCE),
|
||||
);
|
||||
|
||||
const editHandler = (id: string) => {
|
||||
|
@ -48,7 +48,8 @@ import type { ContainerChangeEventData, FieldProps, FormState } from '@tmagic/fo
|
||||
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
||||
|
||||
import MIcon from '@editor/components/Icon.vue';
|
||||
import type { DataSourceFieldSelectConfig, Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import type { DataSourceFieldSelectConfig } from '@editor/type';
|
||||
import { removeDataSourceFieldPrefix } from '@editor/utils';
|
||||
|
||||
import FieldSelect from './FieldSelect.vue';
|
||||
@ -83,10 +84,10 @@ watch(
|
||||
},
|
||||
);
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const { dataSourceService } = useServices();
|
||||
const mForm = inject<FormState | undefined>('mForm');
|
||||
|
||||
const dataSources = computed(() => services?.dataSourceService.get('dataSources') || []);
|
||||
const dataSources = computed(() => dataSourceService.get('dataSources') || []);
|
||||
|
||||
const type = computed((): string => {
|
||||
let type = props.config.fieldConfig?.type;
|
||||
|
@ -64,7 +64,7 @@ import { getDefaultValueFromFields } from '@tmagic/utils';
|
||||
import FloatingBox from '@editor/components/FloatingBox.vue';
|
||||
import { useEditorContentHeight } from '@editor/hooks';
|
||||
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
|
||||
import type { Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
|
||||
defineOptions({
|
||||
name: 'MFieldsDataSourceFields',
|
||||
@ -85,7 +85,7 @@ const emit = defineEmits<{
|
||||
change: [v: any, eventData?: ContainerChangeEventData];
|
||||
}>();
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const { uiService } = useServices();
|
||||
|
||||
const fieldValues = ref<Record<string, any>>({});
|
||||
const fieldTitle = ref('');
|
||||
@ -344,5 +344,5 @@ const addFromJsonDialogVisible = defineModel<boolean>('visible1', { default: fal
|
||||
const { height: editorHeight } = useEditorContentHeight();
|
||||
|
||||
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
||||
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
|
||||
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
|
||||
</script>
|
||||
|
@ -48,7 +48,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, inject, nextTick, ref, useTemplateRef, watch } from 'vue';
|
||||
import { computed, nextTick, ref, useTemplateRef, watch } from 'vue';
|
||||
import { Coin } from '@element-plus/icons-vue';
|
||||
|
||||
import type { DataSchema, DataSourceSchema } from '@tmagic/core';
|
||||
@ -57,7 +57,7 @@ import type { FieldProps, FormItem } from '@tmagic/form';
|
||||
import { getKeysArray, isNumber } from '@tmagic/utils';
|
||||
|
||||
import Icon from '@editor/components/Icon.vue';
|
||||
import type { Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import { getDisplayField } from '@editor/utils/data-source';
|
||||
|
||||
defineOptions({
|
||||
@ -81,15 +81,15 @@ const emit = defineEmits<{
|
||||
change: [value: string];
|
||||
}>();
|
||||
|
||||
const { dataSourceService } = inject<Services>('services') || {};
|
||||
const { dataSourceService } = useServices();
|
||||
|
||||
const autocomplete = useTemplateRef<InstanceType<typeof TMagicAutocomplete>>('autocomplete');
|
||||
const autocompleteRef = useTemplateRef<InstanceType<typeof TMagicAutocomplete>>('autocomplete');
|
||||
const isFocused = ref(false);
|
||||
const state = ref('');
|
||||
const displayState = ref<{ value: string; type: 'var' | 'text' }[]>([]);
|
||||
|
||||
const input = computed<HTMLInputElement>(() => autocomplete.value?.inputRef?.input);
|
||||
const dataSources = computed(() => dataSourceService?.get('dataSources') || []);
|
||||
const input = computed<HTMLInputElement>(() => autocompleteRef.value?.inputRef?.input);
|
||||
const dataSources = computed(() => dataSourceService.get('dataSources'));
|
||||
|
||||
const setDisplayState = () => {
|
||||
displayState.value = getDisplayField(dataSources.value, state.value);
|
||||
@ -112,7 +112,7 @@ const mouseupHandler = async () => {
|
||||
|
||||
isFocused.value = true;
|
||||
await nextTick();
|
||||
autocomplete.value?.focus();
|
||||
autocompleteRef.value?.focus();
|
||||
|
||||
if (focusOffset && input.value) {
|
||||
input.value.setSelectionRange(anchorOffset, focusOffset);
|
||||
|
@ -41,37 +41,36 @@ import { createValues, type FieldProps, filterFunction, type FormState, MContain
|
||||
|
||||
import CodeParams from '@editor/components/CodeParams.vue';
|
||||
import MIcon from '@editor/components/Icon.vue';
|
||||
import type { CodeParamStatement, DataSourceMethodSelectConfig, EventBus, Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import type { CodeParamStatement, DataSourceMethodSelectConfig, EventBus } from '@editor/type';
|
||||
import { SideItemKey } from '@editor/type';
|
||||
|
||||
defineOptions({
|
||||
name: 'MFieldsDataSourceMethodSelect',
|
||||
});
|
||||
|
||||
const { dataSourceService, uiService } = useServices();
|
||||
const mForm = inject<FormState | undefined>('mForm');
|
||||
const services = inject<Services>('services');
|
||||
const eventBus = inject<EventBus>('eventBus');
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const dataSourceService = services?.dataSourceService;
|
||||
|
||||
const props = withDefaults(defineProps<FieldProps<DataSourceMethodSelectConfig>>(), {
|
||||
disabled: false,
|
||||
});
|
||||
|
||||
const hasDataSourceSidePanel = computed(() =>
|
||||
(services?.uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.DATA_SOURCE),
|
||||
(uiService.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.DATA_SOURCE),
|
||||
);
|
||||
|
||||
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
|
||||
|
||||
const dataSources = computed(() => dataSourceService?.get('dataSources'));
|
||||
const dataSources = computed(() => dataSourceService.get('dataSources'));
|
||||
|
||||
const isCustomMethod = computed(() => {
|
||||
const [id, name] = props.model[props.name];
|
||||
|
||||
const dataSource = dataSourceService?.getDataSourceById(id);
|
||||
const dataSource = dataSourceService.getDataSourceById(id);
|
||||
|
||||
return Boolean(dataSource?.methods.find((method) => method.name === name));
|
||||
});
|
||||
@ -107,7 +106,7 @@ const setParamsConfig = (dataSourceMethod: [Id, string], formState: any = {}) =>
|
||||
const methodsOptions = computed(
|
||||
() =>
|
||||
dataSources.value
|
||||
?.filter((ds) => ds.methods?.length || dataSourceService?.getFormMethod(ds.type).length)
|
||||
?.filter((ds) => ds.methods?.length || dataSourceService.getFormMethod(ds.type).length)
|
||||
?.map((ds) => ({
|
||||
label: ds.title || ds.id,
|
||||
value: ds.id,
|
||||
@ -144,7 +143,7 @@ const onChangeHandler = (value: any) => {
|
||||
const editCodeHandler = () => {
|
||||
const [id] = props.model[props.name];
|
||||
|
||||
const dataSource = dataSourceService?.getDataSourceById(id);
|
||||
const dataSource = dataSourceService.getDataSourceById(id);
|
||||
|
||||
if (!dataSource) return;
|
||||
|
||||
|
@ -51,7 +51,7 @@ const props = withDefaults(
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const codeConfig = ref<CodeBlockContent>();
|
||||
const codeBlockEditor = useTemplateRef<InstanceType<typeof CodeBlockEditor>>('codeBlockEditor');
|
||||
const codeBlockEditorRef = useTemplateRef<InstanceType<typeof CodeBlockEditor>>('codeBlockEditor');
|
||||
|
||||
let editIndex = -1;
|
||||
|
||||
@ -94,7 +94,7 @@ const methodColumns: ColumnConfig[] = [
|
||||
editIndex = index;
|
||||
|
||||
nextTick(() => {
|
||||
codeBlockEditor.value?.show();
|
||||
codeBlockEditorRef.value?.show();
|
||||
});
|
||||
},
|
||||
},
|
||||
@ -121,7 +121,7 @@ const createCodeHandler = () => {
|
||||
editIndex = -1;
|
||||
|
||||
nextTick(() => {
|
||||
codeBlockEditor.value?.show();
|
||||
codeBlockEditorRef.value?.show();
|
||||
});
|
||||
};
|
||||
|
||||
@ -157,6 +157,6 @@ const submitCodeHandler = (value: CodeBlockContent, data: ContainerChangeEventDa
|
||||
editIndex = -1;
|
||||
codeConfig.value = void 0;
|
||||
|
||||
codeBlockEditor.value?.hide();
|
||||
codeBlockEditorRef.value?.hide();
|
||||
};
|
||||
</script>
|
||||
|
@ -38,8 +38,8 @@ import { getDefaultValueFromFields } from '@tmagic/utils';
|
||||
|
||||
import FloatingBox from '@editor/components/FloatingBox.vue';
|
||||
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import CodeEditor from '@editor/layouts/CodeEditor.vue';
|
||||
import { Services } from '@editor/type';
|
||||
|
||||
import { useEditorContentHeight } from '..';
|
||||
|
||||
@ -60,7 +60,7 @@ const props = withDefaults(
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const { uiService } = useServices();
|
||||
const width = defineModel<number>('width', { default: 670 });
|
||||
|
||||
const drawerTitle = ref('');
|
||||
@ -250,5 +250,5 @@ const toggleValue = (row: MockSchema, key: 'enable' | 'useInEditor', value: bool
|
||||
const addDialogVisible = defineModel<boolean>('visible', { default: false });
|
||||
const { height: editorHeight } = useEditorContentHeight();
|
||||
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
||||
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
|
||||
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
|
||||
</script>
|
||||
|
@ -27,7 +27,8 @@ import { TMagicButton, TMagicTooltip } from '@tmagic/design';
|
||||
import { type FieldProps, filterFunction, type FormState, MSelect, type SelectConfig } from '@tmagic/form';
|
||||
|
||||
import MIcon from '@editor/components/Icon.vue';
|
||||
import type { DataSourceSelect, EventBus, Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import type { DataSourceSelect, EventBus } from '@editor/type';
|
||||
import { SideItemKey } from '@editor/type';
|
||||
|
||||
defineOptions({
|
||||
@ -41,15 +42,15 @@ const props = withDefaults(defineProps<FieldProps<DataSourceSelect>>(), {
|
||||
});
|
||||
|
||||
const mForm = inject<FormState | undefined>('mForm');
|
||||
const { dataSourceService, uiService } = inject<Services>('services') || {};
|
||||
const { dataSourceService, uiService } = useServices();
|
||||
const eventBus = inject<EventBus>('eventBus');
|
||||
|
||||
const dataSources = computed(() => dataSourceService?.get('dataSources') || []);
|
||||
const dataSources = computed(() => dataSourceService.get('dataSources'));
|
||||
|
||||
const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
|
||||
|
||||
const hasDataSourceSidePanel = computed(() =>
|
||||
(uiService?.get('sideBarItems') || []).find((item) => item.$key === SideItemKey.DATA_SOURCE),
|
||||
uiService.get('sideBarItems').find((item) => item.$key === SideItemKey.DATA_SOURCE),
|
||||
);
|
||||
|
||||
const selectConfig = computed<SelectConfig>(() => {
|
||||
@ -87,7 +88,7 @@ const editHandler = () => {
|
||||
|
||||
const id = typeof value === 'string' ? value : value.dataSourceId;
|
||||
|
||||
const dataSource = dataSourceService?.getDataSourceById(id);
|
||||
const dataSource = dataSourceService.getDataSourceById(id);
|
||||
|
||||
if (!dataSource) return;
|
||||
|
||||
|
@ -26,7 +26,7 @@ import {
|
||||
MGroupList,
|
||||
} from '@tmagic/form';
|
||||
|
||||
import type { Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import { getCascaderOptionsFromFields } from '@editor/utils';
|
||||
|
||||
defineOptions({
|
||||
@ -49,7 +49,7 @@ const props = withDefaults(
|
||||
},
|
||||
);
|
||||
|
||||
const { dataSourceService } = inject<Services>('services') || {};
|
||||
const { dataSourceService } = useServices();
|
||||
const mForm = inject<FormState | undefined>('mForm');
|
||||
|
||||
const parentFields = computed(() => filterFunction<string[]>(mForm, props.config.parentFields, props) || []);
|
||||
@ -71,7 +71,7 @@ const config = computed<GroupListConfig>(() => ({
|
||||
type: 'cascader',
|
||||
options: () => {
|
||||
const [dsId, ...keys] = parentFields.value;
|
||||
const ds = dataSourceService?.getDataSourceById(dsId);
|
||||
const ds = dataSourceService.getDataSourceById(dsId);
|
||||
if (!ds) {
|
||||
return [];
|
||||
}
|
||||
@ -113,7 +113,7 @@ const config = computed<GroupListConfig>(() => ({
|
||||
type: (mForm, { model }) => {
|
||||
const [id, ...fieldNames] = [...parentFields.value, ...model.field];
|
||||
|
||||
const ds = dataSourceService?.getDataSourceById(id);
|
||||
const ds = dataSourceService.getDataSourceById(id);
|
||||
|
||||
let fields = ds?.fields || [];
|
||||
let type = '';
|
||||
|
@ -50,7 +50,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { Delete } from '@element-plus/icons-vue';
|
||||
import { has } from 'lodash-es';
|
||||
|
||||
@ -68,7 +68,8 @@ import type {
|
||||
import { MContainer as MFormContainer, MPanel } from '@tmagic/form';
|
||||
import { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, traverseNode } from '@tmagic/utils';
|
||||
|
||||
import type { CodeSelectColConfig, DataSourceMethodSelectConfig, EventSelectConfig, Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import type { CodeSelectColConfig, DataSourceMethodSelectConfig, EventSelectConfig } from '@editor/type';
|
||||
import { getCascaderOptionsFromFields } from '@editor/utils';
|
||||
|
||||
defineOptions({
|
||||
@ -81,12 +82,7 @@ const emit = defineEmits<{
|
||||
change: [v: any, eventData?: ContainerChangeEventData];
|
||||
}>();
|
||||
|
||||
const services = inject<Services>('services');
|
||||
|
||||
const editorService = services?.editorService;
|
||||
const dataSourceService = services?.dataSourceService;
|
||||
const eventsService = services?.eventsService;
|
||||
const codeBlockService = services?.codeBlockService;
|
||||
const { editorService, dataSourceService, eventsService, codeBlockService } = useServices();
|
||||
|
||||
// 事件名称下拉框表单配置
|
||||
const eventNameConfig = computed(() => {
|
||||
@ -108,13 +104,11 @@ const eventNameConfig = computed(() => {
|
||||
options: (mForm: FormState, { formValue }: any) => {
|
||||
let events: EventOption[] | CascaderOption[] = [];
|
||||
|
||||
if (!eventsService || !dataSourceService) return events;
|
||||
|
||||
if (props.config.src === 'component') {
|
||||
events = eventsService.getEvent(formValue.type);
|
||||
|
||||
if (formValue.type === 'page-fragment-container' && formValue.pageFragmentId) {
|
||||
const pageFragment = editorService?.get('root')?.items?.find((page) => page.id === formValue.pageFragmentId);
|
||||
const pageFragment = editorService.get('root')?.items?.find((page) => page.id === formValue.pageFragmentId);
|
||||
if (pageFragment) {
|
||||
events = [
|
||||
{
|
||||
@ -185,7 +179,7 @@ const actionTypeConfig = computed(() => {
|
||||
{
|
||||
text: '代码',
|
||||
label: '代码',
|
||||
disabled: !Object.keys(codeBlockService?.getCodeDsl() || {}).length,
|
||||
disabled: !Object.keys(codeBlockService.getCodeDsl() || {}).length,
|
||||
value: ActionType.CODE,
|
||||
},
|
||||
{
|
||||
@ -193,7 +187,7 @@ const actionTypeConfig = computed(() => {
|
||||
label: '数据源',
|
||||
disabled: !dataSourceService
|
||||
?.get('dataSources')
|
||||
?.filter((ds) => ds.methods?.length || dataSourceService?.getFormMethod(ds.type).length).length,
|
||||
?.filter((ds) => ds.methods?.length || dataSourceService.getFormMethod(ds.type).length).length,
|
||||
value: ActionType.DATA_SOURCE,
|
||||
},
|
||||
],
|
||||
@ -222,7 +216,7 @@ const compActionConfig = computed(() => {
|
||||
name: 'method',
|
||||
text: '动作',
|
||||
type: (mForm, { model }: any) => {
|
||||
const to = editorService?.getNodeById(model.to);
|
||||
const to = editorService.getNodeById(model.to);
|
||||
|
||||
if (to && to.type === 'page-fragment-container' && to.pageFragmentId) {
|
||||
return 'cascader';
|
||||
@ -233,20 +227,20 @@ const compActionConfig = computed(() => {
|
||||
checkStrictly: () => props.config.src !== 'component',
|
||||
display: (mForm, { model }: any) => model.actionType === ActionType.COMP,
|
||||
options: (mForm: FormState, { model }: any) => {
|
||||
const node = editorService?.getNodeById(model.to);
|
||||
const node = editorService.getNodeById(model.to);
|
||||
if (!node?.type) return [];
|
||||
|
||||
let methods: EventOption[] | CascaderOption[] = [];
|
||||
|
||||
methods = eventsService?.getMethod(node.type) || [];
|
||||
methods = eventsService.getMethod(node.type);
|
||||
|
||||
if (node.type === 'page-fragment-container' && node.pageFragmentId) {
|
||||
const pageFragment = editorService?.get('root')?.items?.find((page) => page.id === node.pageFragmentId);
|
||||
const pageFragment = editorService.get('root')?.items?.find((page) => page.id === node.pageFragmentId);
|
||||
if (pageFragment) {
|
||||
methods = [];
|
||||
pageFragment.items.forEach((node: MComponent | MContainer) => {
|
||||
traverseNode<MComponent | MContainer>(node, (node) => {
|
||||
const nodeMethods = (node.type && eventsService?.getMethod(node.type)) || [];
|
||||
const nodeMethods = (node.type && eventsService.getMethod(node.type)) || [];
|
||||
|
||||
if (nodeMethods.length) {
|
||||
methods.push({
|
||||
@ -277,7 +271,7 @@ const codeActionConfig = computed(() => {
|
||||
type: 'code-select-col',
|
||||
text: '代码块',
|
||||
name: 'codeId',
|
||||
notEditable: () => !codeBlockService?.getEditStatus(),
|
||||
notEditable: () => !codeBlockService.getEditStatus(),
|
||||
display: (mForm, { model }) => model.actionType === ActionType.CODE,
|
||||
};
|
||||
return { ...defaultCodeActionConfig, ...props.config.codeActionConfig };
|
||||
@ -289,7 +283,7 @@ const dataSourceActionConfig = computed(() => {
|
||||
type: 'data-source-method-select',
|
||||
text: '数据源方法',
|
||||
name: 'dataSourceMethod',
|
||||
notEditable: () => !services?.dataSourceService.get('editable'),
|
||||
notEditable: () => !dataSourceService.get('editable'),
|
||||
display: (mForm, { model }) => model.actionType === ActionType.DATA_SOURCE,
|
||||
};
|
||||
return { ...defaultDataSourceActionConfig, ...props.config.dataSourceActionConfig };
|
||||
@ -305,7 +299,7 @@ const tableConfig = computed(() => ({
|
||||
label: '事件名',
|
||||
type: eventNameConfig.value.type,
|
||||
options: (mForm: FormState, { formValue }: any) =>
|
||||
eventsService?.getEvent(formValue.type).map((option: any) => ({
|
||||
eventsService.getEvent(formValue.type).map((option: any) => ({
|
||||
text: option.label,
|
||||
value: option.value,
|
||||
})),
|
||||
@ -320,10 +314,10 @@ const tableConfig = computed(() => ({
|
||||
label: '动作',
|
||||
type: compActionConfig.value.type,
|
||||
options: (mForm: FormState, { model }: any) => {
|
||||
const node = editorService?.getNodeById(model.to);
|
||||
const node = editorService.getNodeById(model.to);
|
||||
if (!node?.type) return [];
|
||||
|
||||
return eventsService?.getMethod(node.type).map((option: any) => ({
|
||||
return eventsService.getMethod(node.type).map((option: any) => ({
|
||||
text: option.label,
|
||||
value: option.value,
|
||||
}));
|
||||
|
@ -16,27 +16,28 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { Edit } from '@element-plus/icons-vue';
|
||||
|
||||
import { Id, NodeType } from '@tmagic/core';
|
||||
import { FieldProps } from '@tmagic/form';
|
||||
|
||||
import Icon from '@editor/components/Icon.vue';
|
||||
import type { PageFragmentSelectConfig, Services } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import type { PageFragmentSelectConfig } from '@editor/type';
|
||||
|
||||
defineOptions({
|
||||
name: 'MFieldsPageFragmentSelect',
|
||||
});
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const { editorService } = useServices();
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const props = withDefaults(defineProps<FieldProps<PageFragmentSelectConfig>>(), {
|
||||
disabled: false,
|
||||
});
|
||||
const pageList = computed(() =>
|
||||
services?.editorService.get('root')?.items.filter((item) => item.type === NodeType.PAGE_FRAGMENT),
|
||||
editorService.get('root')?.items.filter((item) => item.type === NodeType.PAGE_FRAGMENT),
|
||||
);
|
||||
|
||||
const selectConfig = {
|
||||
@ -58,6 +59,6 @@ const changeHandler = async () => {
|
||||
};
|
||||
|
||||
const editPageFragment = (id: Id) => {
|
||||
services?.editorService.select(id);
|
||||
editorService.select(id);
|
||||
};
|
||||
</script>
|
||||
|
@ -27,7 +27,7 @@ defineOptions({
|
||||
name: 'MFieldsStyleSetter',
|
||||
});
|
||||
|
||||
defineProps<FieldProps<StyleSchema>>();
|
||||
const props = defineProps<FieldProps<StyleSchema>>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
change: [v: any, eventData: ContainerChangeEventData];
|
||||
@ -64,6 +64,9 @@ const collapseValue = shallowRef(
|
||||
);
|
||||
|
||||
const change = (v: any, eventData: ContainerChangeEventData) => {
|
||||
eventData.changeRecords?.forEach((record) => {
|
||||
record.propPath = `${props.name}.${record.propPath}`;
|
||||
});
|
||||
emit('change', v, eventData);
|
||||
};
|
||||
</script>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<MContainer :config="config" :model="values" @change="change"></MContainer>
|
||||
<Box :model="values" @change="change"></Box>
|
||||
<Box v-show="!['fixed', 'absolute'].includes(values.position)" :model="values" @change="change"></Box>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -125,7 +125,7 @@ const config = {
|
||||
},
|
||||
{
|
||||
name: 'height',
|
||||
text: '宽度',
|
||||
text: '高度',
|
||||
labelWidth: '68px',
|
||||
type: 'data-source-field-select',
|
||||
fieldConfig: {
|
||||
@ -135,25 +135,41 @@ const config = {
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'data-source-field-select',
|
||||
text: 'overflow',
|
||||
name: 'overflow',
|
||||
checkStrictly: false,
|
||||
dataSourceFieldType: ['string'],
|
||||
fieldConfig: {
|
||||
type: 'select',
|
||||
clearable: true,
|
||||
allowCreate: true,
|
||||
options: [
|
||||
{ text: 'visible', value: 'visible' },
|
||||
{ text: 'hidden', value: 'hidden' },
|
||||
{ text: 'clip', value: 'clip' },
|
||||
{ text: 'scroll', value: 'scroll' },
|
||||
{ text: 'auto', value: 'auto' },
|
||||
{ text: 'overlay', value: 'overlay' },
|
||||
{ text: 'initial', value: 'initial' },
|
||||
],
|
||||
},
|
||||
type: 'row',
|
||||
items: [
|
||||
{
|
||||
type: 'data-source-field-select',
|
||||
text: 'overflow',
|
||||
name: 'overflow',
|
||||
labelWidth: '68px',
|
||||
checkStrictly: false,
|
||||
dataSourceFieldType: ['string'],
|
||||
fieldConfig: {
|
||||
type: 'select',
|
||||
clearable: true,
|
||||
allowCreate: true,
|
||||
options: [
|
||||
{ text: 'visible', value: 'visible' },
|
||||
{ text: 'hidden', value: 'hidden' },
|
||||
{ text: 'clip', value: 'clip' },
|
||||
{ text: 'scroll', value: 'scroll' },
|
||||
{ text: 'auto', value: 'auto' },
|
||||
{ text: 'overlay', value: 'overlay' },
|
||||
{ text: 'initial', value: 'initial' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'data-source-field-select',
|
||||
text: '透明度',
|
||||
name: 'opacity',
|
||||
labelWidth: '68px',
|
||||
dataSourceFieldType: ['string', 'number'],
|
||||
fieldConfig: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -1,15 +1,12 @@
|
||||
<template>
|
||||
<MContainer :config="config" :model="values" @change="change"></MContainer>
|
||||
<Position v-show="values['position'] !== 'static'" :model="values" @change="change"></Position>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ContainerChangeEventData, MContainer } from '@tmagic/form';
|
||||
import type { StyleSchema } from '@tmagic/schema';
|
||||
|
||||
import Position from '../components/Position.vue';
|
||||
|
||||
defineProps<{ values: Partial<StyleSchema> }>();
|
||||
const props = defineProps<{ values: Partial<StyleSchema> }>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
change: [v: string | StyleSchema, eventData: ContainerChangeEventData];
|
||||
@ -30,6 +27,52 @@ const config = {
|
||||
})),
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'row',
|
||||
labelWidth: '68px',
|
||||
display: () => props.values.position !== 'static',
|
||||
items: [
|
||||
{
|
||||
name: 'left',
|
||||
type: 'data-source-field-select',
|
||||
text: 'left',
|
||||
fieldConfig: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'top',
|
||||
type: 'data-source-field-select',
|
||||
text: 'top',
|
||||
fieldConfig: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'row',
|
||||
labelWidth: '68px',
|
||||
display: () => props.values.position !== 'static',
|
||||
items: [
|
||||
{
|
||||
name: 'right',
|
||||
type: 'data-source-field-select',
|
||||
text: 'right',
|
||||
fieldConfig: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'bottom',
|
||||
type: 'data-source-field-select',
|
||||
text: 'bottom',
|
||||
fieldConfig: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
labelWidth: '68px',
|
||||
name: 'zIndex',
|
||||
|
@ -50,7 +50,8 @@ import { TMagicButton, TMagicTooltip } from '@tmagic/design';
|
||||
import type { FieldProps, FormItem, FormState } from '@tmagic/form';
|
||||
import { getIdFromEl } from '@tmagic/utils';
|
||||
|
||||
import { type Services, UI_SELECT_MODE_EVENT_NAME } from '@editor/type';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
import { UI_SELECT_MODE_EVENT_NAME } from '@editor/utils/const';
|
||||
|
||||
defineOptions({
|
||||
name: 'MFieldsUISelect',
|
||||
@ -60,14 +61,14 @@ const props = defineProps<FieldProps<{ type: 'ui-select' } & FormItem>>();
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const services = inject<Services>('services');
|
||||
const { editorService, uiService, stageOverlayService } = useServices();
|
||||
const mForm = inject<FormState>('mForm');
|
||||
|
||||
const val = computed(() => props.model[props.name]);
|
||||
const uiSelectMode = ref(false);
|
||||
|
||||
const cancelHandler = () => {
|
||||
if (!services?.uiService) return;
|
||||
services.uiService.set('uiSelectMode', false);
|
||||
uiService.set('uiSelectMode', false);
|
||||
uiSelectMode.value = false;
|
||||
globalThis.document.removeEventListener(UI_SELECT_MODE_EVENT_NAME, clickHandler as EventListener);
|
||||
};
|
||||
@ -89,13 +90,12 @@ const clickHandler = ({ detail }: Event & { detail: HTMLElement | MNode }) => {
|
||||
};
|
||||
|
||||
const toName = computed(() => {
|
||||
const config = services?.editorService.getNodeById(val.value);
|
||||
const config = editorService.getNodeById(val.value);
|
||||
return config?.name || '';
|
||||
});
|
||||
|
||||
const startSelect = () => {
|
||||
if (!services?.uiService) return;
|
||||
services.uiService.set('uiSelectMode', true);
|
||||
uiService.set('uiSelectMode', true);
|
||||
uiSelectMode.value = true;
|
||||
globalThis.document.addEventListener(UI_SELECT_MODE_EVENT_NAME, clickHandler as EventListener);
|
||||
};
|
||||
@ -109,24 +109,21 @@ const deleteHandler = () => {
|
||||
};
|
||||
|
||||
const selectNode = async (id: Id) => {
|
||||
if (!services) return;
|
||||
await services.editorService.select(id);
|
||||
services.editorService.get('stage')?.select(id);
|
||||
services.stageOverlayService.get('stage')?.select(id);
|
||||
await editorService.select(id);
|
||||
editorService.get('stage')?.select(id);
|
||||
stageOverlayService.get('stage')?.select(id);
|
||||
};
|
||||
|
||||
const highlight = throttle((id: Id) => {
|
||||
if (!services) return;
|
||||
services.editorService.highlight(id);
|
||||
services.editorService.get('stage')?.highlight(id);
|
||||
services.stageOverlayService.get('stage')?.highlight(id);
|
||||
editorService.highlight(id);
|
||||
editorService.get('stage')?.highlight(id);
|
||||
stageOverlayService.get('stage')?.highlight(id);
|
||||
}, 150);
|
||||
|
||||
const unhighlight = () => {
|
||||
if (!services) return;
|
||||
services.editorService.set('highlightNode', null);
|
||||
services.editorService.get('stage')?.clearHighlight();
|
||||
services.stageOverlayService.get('stage')?.clearHighlight();
|
||||
editorService.set('highlightNode', null);
|
||||
editorService.get('stage')?.clearHighlight();
|
||||
stageOverlayService.get('stage')?.clearHighlight();
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -28,3 +28,4 @@ export * from './use-next-float-box-position';
|
||||
export * from './use-node-status';
|
||||
export * from './use-stage';
|
||||
export * from './use-window-rect';
|
||||
export * from './use-services';
|
||||
|
@ -5,20 +5,15 @@ import type { CodeBlockContent } from '@tmagic/core';
|
||||
import { tMagicMessage } from '@tmagic/design';
|
||||
|
||||
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
||||
import type { CodeBlockService } from '@editor/services/codeBlock';
|
||||
import type { Services } from '@editor/type';
|
||||
|
||||
export const useCodeBlockEdit = (codeBlockService?: CodeBlockService) => {
|
||||
export const useCodeBlockEdit = (codeBlockService: Services['codeBlockService']) => {
|
||||
const codeConfig = ref<CodeBlockContent>();
|
||||
const codeId = ref<string>();
|
||||
const codeBlockEditor = useTemplateRef<InstanceType<typeof CodeBlockEditor>>('codeBlockEditor');
|
||||
const codeBlockEditorRef = useTemplateRef<InstanceType<typeof CodeBlockEditor>>('codeBlockEditor');
|
||||
|
||||
// 新增代码块
|
||||
const createCodeBlock = async () => {
|
||||
if (!codeBlockService) {
|
||||
tMagicMessage.error('新增代码块失败');
|
||||
return;
|
||||
}
|
||||
|
||||
codeConfig.value = {
|
||||
name: '',
|
||||
content: `({app, params, flowState}) => {\n // place your code here\n}`,
|
||||
@ -29,12 +24,12 @@ export const useCodeBlockEdit = (codeBlockService?: CodeBlockService) => {
|
||||
|
||||
await nextTick();
|
||||
|
||||
codeBlockEditor.value?.show();
|
||||
codeBlockEditorRef.value?.show();
|
||||
};
|
||||
|
||||
// 编辑代码块
|
||||
const editCode = async (id: string) => {
|
||||
const codeBlock = await codeBlockService?.getCodeContentById(id);
|
||||
const codeBlock = await codeBlockService.getCodeContentById(id);
|
||||
|
||||
if (!codeBlock) {
|
||||
tMagicMessage.error('获取代码块内容失败');
|
||||
@ -54,26 +49,26 @@ export const useCodeBlockEdit = (codeBlockService?: CodeBlockService) => {
|
||||
codeId.value = id;
|
||||
|
||||
await nextTick();
|
||||
codeBlockEditor.value?.show();
|
||||
codeBlockEditorRef.value?.show();
|
||||
};
|
||||
|
||||
// 删除代码块
|
||||
const deleteCode = async (key: string) => {
|
||||
codeBlockService?.deleteCodeDslByIds([key]);
|
||||
codeBlockService.deleteCodeDslByIds([key]);
|
||||
};
|
||||
|
||||
const submitCodeBlockHandler = async (values: CodeBlockContent) => {
|
||||
if (!codeId.value) return;
|
||||
|
||||
await codeBlockService?.setCodeDslById(codeId.value, values);
|
||||
await codeBlockService.setCodeDslById(codeId.value, values);
|
||||
|
||||
codeBlockEditor.value?.hide();
|
||||
codeBlockEditorRef.value?.hide();
|
||||
};
|
||||
|
||||
return {
|
||||
codeId,
|
||||
codeConfig,
|
||||
codeBlockEditor,
|
||||
codeBlockEditor: codeBlockEditorRef,
|
||||
|
||||
createCodeBlock,
|
||||
editCode,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user