mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-04-26 03:26:53 +08:00
Compare commits
66 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7eded0e44a | ||
|
cdfb3adfa9 | ||
|
ba05ecbf60 | ||
|
9d8ee4b2d3 | ||
|
e774c9ff5f | ||
|
604ae1eb52 | ||
|
105de9d2c6 | ||
|
0987901a46 | ||
|
de52ff4fe1 | ||
|
0e911337b8 | ||
|
fd7e737e8c | ||
|
e7e9197ae3 | ||
|
5e0e776d40 | ||
|
31515c4046 | ||
|
42adb962fd | ||
|
0bcd7d0755 | ||
|
54e00f2852 | ||
|
f91eb415db | ||
|
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 |
@ -1,14 +0,0 @@
|
|||||||
dist
|
|
||||||
coverage
|
|
||||||
node_modules
|
|
||||||
dest
|
|
||||||
types
|
|
||||||
public/entry
|
|
||||||
public/runtime
|
|
||||||
|
|
||||||
comp-entry.ts
|
|
||||||
config-entry.ts
|
|
||||||
value-entry.ts
|
|
||||||
|
|
||||||
magic-admin/web/public/runtime
|
|
||||||
magic-admin/server/static
|
|
@ -1,71 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
env: {
|
|
||||||
node: true,
|
|
||||||
browser: true,
|
|
||||||
es2021: true,
|
|
||||||
},
|
|
||||||
globals: {
|
|
||||||
describe: true,
|
|
||||||
it: true,
|
|
||||||
expect: true,
|
|
||||||
beforeEach: true,
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
'eslint-config-tencent',
|
|
||||||
'eslint-config-tencent/ts',
|
|
||||||
'plugin:vue/vue3-essential',
|
|
||||||
'./prettier.cjs',
|
|
||||||
],
|
|
||||||
parser: 'vue-eslint-parser',
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 12,
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
extraFileExtensions: ['.vue'],
|
|
||||||
sourceType: 'module',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
'vue',
|
|
||||||
'@typescript-eslint',
|
|
||||||
'simple-import-sort'
|
|
||||||
],
|
|
||||||
ignorePatterns: ['.eslintrc.cjs'],
|
|
||||||
rules: {
|
|
||||||
'vue/no-mutating-props': 'off',
|
|
||||||
'vue/multi-word-component-names': 'off',
|
|
||||||
'no-param-reassign': 'off',
|
|
||||||
'@typescript-eslint/naming-convention': 'off',
|
|
||||||
'@typescript-eslint/no-require-imports': 'off',
|
|
||||||
"@typescript-eslint/no-misused-promises": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"checksVoidReturn": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'simple-import-sort/imports': [
|
|
||||||
"error", {
|
|
||||||
groups: [
|
|
||||||
['./polyfills'],
|
|
||||||
// Node.js builtins. You could also generate this regex if you use a `.js` config.
|
|
||||||
// For example: `^(${require("module").builtinModules.join("|")})(/|$)`
|
|
||||||
[
|
|
||||||
"^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)",
|
|
||||||
],
|
|
||||||
["^(node)(:.*|$)"],
|
|
||||||
// Packages. `react|vue` related packages come first.
|
|
||||||
["^(react|vue|vite)", "^@?\\w"],
|
|
||||||
["^(@tmagic)(/.*|$)"],
|
|
||||||
// Internal packages.
|
|
||||||
["^(@|@editor|@data-source)(/.*|$)"],
|
|
||||||
// Side effect imports.
|
|
||||||
["^\\u0000"],
|
|
||||||
// Parent imports. Put `..` last.
|
|
||||||
["^\\.\\.(?!/?$)", "^\\.\\./?$"],
|
|
||||||
// Other relative imports. Put same-folder imports and `.` last.
|
|
||||||
["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
|
|
||||||
// Style imports.
|
|
||||||
["^.+\\.s?css$"],
|
|
||||||
],
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
};
|
|
6
.github/workflows/pages.yml
vendored
6
.github/workflows/pages.yml
vendored
@ -10,16 +10,16 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: dev
|
ref: dev
|
||||||
|
|
||||||
- name: Install pnpm
|
- name: Install pnpm
|
||||||
uses: pnpm/action-setup@v2
|
uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
- name: Set node version to 18
|
- name: Set node version to 18
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 18
|
||||||
cache: 'pnpm'
|
cache: 'pnpm'
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -31,3 +31,5 @@ coverage
|
|||||||
auto-imports.d.ts
|
auto-imports.d.ts
|
||||||
components.d.ts
|
components.d.ts
|
||||||
docs/.vitepress/cache
|
docs/.vitepress/cache
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
128
CHANGELOG.md
128
CHANGELOG.md
@ -1,3 +1,131 @@
|
|||||||
|
## [1.5.15](https://github.com/Tencent/tmagic-editor/compare/v1.5.14...v1.5.15) (2025-04-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **editor:** getTMagicApp返回类型错误 ([ba05ecb](https://github.com/Tencent/tmagic-editor/commit/ba05ecbf608785d97c60adbdd6b7381597e6cb6f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.5.14](https://github.com/Tencent/tmagic-editor/compare/v1.5.13...v1.5.14) (2025-04-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **dep:** 配置了数据源内部方法无法收集到依赖 ([0e91133](https://github.com/Tencent/tmagic-editor/commit/0e911337b8f88e5e88fecf072395c38d2de1bc08))
|
||||||
|
* **editor:** 编辑数据源/代码块时,列表高亮 ([de52ff4](https://github.com/Tencent/tmagic-editor/commit/de52ff4fe100cb11b73865703b03a0cbcc4e92e7))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **form:** onChange添加setModel参数,用于修改model并添加至修改记录中 ([5e0e776](https://github.com/Tencent/tmagic-editor/commit/5e0e776d4004c9a4ad2ae53d7146353dc088a478))
|
||||||
|
* **utils:** 添加设置删除获取url参数的方法 ([105de9d](https://github.com/Tencent/tmagic-editor/commit/105de9d2c6ba69eb9e7ca9777f16441e5aa4c1f0))
|
||||||
|
* **vue-runtime-help:** app不存在时抛异常,保证app一定存在,避免多余的可选链 ([fd7e737](https://github.com/Tencent/tmagic-editor/commit/fd7e737e8c4f4958c8d59d5f844f40cf1509724f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.5.13](https://github.com/Tencent/tmagic-editor/compare/v1.5.12...v1.5.13) (2025-04-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **data-source:** 数据源初始化时机比注册早回出现死循环 ([840c2c3](https://github.com/Tencent/tmagic-editor/commit/840c2c3c7d267f999e229f7720cbbdc1bf5e2436))
|
||||||
|
* 修复表格拖拽排序与表单选字操作冲突的问题 ([f91eb41](https://github.com/Tencent/tmagic-editor/commit/f91eb415dbdf23c8f05bc21617de67aef7bd524c))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **core:** 支持传入env ([0bcd7d0](https://github.com/Tencent/tmagic-editor/commit/0bcd7d075518523809b639e8128583c87b90aa89))
|
||||||
|
* **core:** 支持自定义Node类 ([18524d8](https://github.com/Tencent/tmagic-editor/commit/18524d89fb8086a34307ed17e54da520db92add2))
|
||||||
|
* **editor:** 编辑代码块/数据源时高亮列表中对应的项 ([54e00f2](https://github.com/Tencent/tmagic-editor/commit/54e00f28524e546cecd0691d19fbcb0bee4af35e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [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.7](https://github.com/Tencent/tmagic-editor/compare/v1.5.6...v1.5.7) (2025-02-11)
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,11 +17,7 @@
|
|||||||
<slot name="highlight"></slot>
|
<slot name="highlight"></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="demo-block-control" ref="control" @click="isExpanded = !isExpanded">
|
||||||
class="demo-block-control"
|
|
||||||
ref="control"
|
|
||||||
@click="isExpanded = !isExpanded"
|
|
||||||
>
|
|
||||||
<transition name="arrow-slide">
|
<transition name="arrow-slide">
|
||||||
<i :class="[iconClass, hovering]"></i>
|
<i :class="[iconClass, hovering]"></i>
|
||||||
</transition>
|
</transition>
|
||||||
@ -30,23 +26,14 @@
|
|||||||
</transition>
|
</transition>
|
||||||
<el-tooltip effect="dark" :content="'前往 codepen.io 运行此示例'" placement="right">
|
<el-tooltip effect="dark" :content="'前往 codepen.io 运行此示例'" placement="right">
|
||||||
<transition name="text-slide">
|
<transition name="text-slide">
|
||||||
<el-button
|
<el-button size="small" type="primary" text class="control-button" @click.stop="goCodepen">
|
||||||
size="small"
|
{{ type === 'form' ? '查看结果' : '在线运行' }}
|
||||||
type="primary"
|
|
||||||
text
|
|
||||||
class="control-button"
|
|
||||||
@click.stop="goCodepen"
|
|
||||||
>
|
|
||||||
{{type === 'form' ? '查看结果' : '在线运行'}}
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</transition>
|
</transition>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog v-model="resultVisible" title="result">
|
||||||
v-model="resultVisible"
|
|
||||||
title="result"
|
|
||||||
>
|
|
||||||
<pre><code class="language-javascript hljs" v-html="result"></code></pre>
|
<pre><code class="language-javascript hljs" v-html="result"></code></pre>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
@ -60,7 +47,9 @@
|
|||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
|
|
||||||
&.hover {
|
&.hover {
|
||||||
box-shadow: 0 0 8px 0 rgba(232, 237, 250, 0.6), 0 2px 4px 0 rgba(232, 237, 250, 0.5);
|
box-shadow:
|
||||||
|
0 0 8px 0 rgba(232, 237, 250, 0.6),
|
||||||
|
0 2px 4px 0 rgba(232, 237, 250, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
@ -219,9 +208,7 @@ export function stripTemplate(content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: [
|
props: ['type', 'config'],
|
||||||
'type', 'config'
|
|
||||||
],
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -293,12 +280,15 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
text() {
|
text() {
|
||||||
return this.isStringConfig ?
|
return this.isStringConfig
|
||||||
hljs.highlight('js', this.config).value :
|
? hljs.highlight('js', this.config).value
|
||||||
hljs.highlight('js', serialize(this.config, {
|
: hljs.highlight(
|
||||||
|
'js',
|
||||||
|
serialize(this.config, {
|
||||||
space: 2,
|
space: 2,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}).replace(/"(\w+)":\s/g, '$1: ')).value;
|
}).replace(/"(\w+)":\s/g, '$1: '),
|
||||||
|
).value;
|
||||||
},
|
},
|
||||||
|
|
||||||
formConfig() {
|
formConfig() {
|
||||||
@ -307,7 +297,7 @@ export default {
|
|||||||
|
|
||||||
isStringConfig() {
|
isStringConfig() {
|
||||||
return typeof this.config === 'string';
|
return typeof this.config === 'string';
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
@ -356,7 +346,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeUnmount() {
|
||||||
this.removeScrollHandler();
|
this.removeScrollHandler();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
566
eslint-config/flat/base.mjs
Normal file
566
eslint-config/flat/base.mjs
Normal file
@ -0,0 +1,566 @@
|
|||||||
|
export default {
|
||||||
|
rules: {
|
||||||
|
/**
|
||||||
|
* 不要在中括号中添加空格
|
||||||
|
*/
|
||||||
|
'array-bracket-spacing': ['error', 'never'],
|
||||||
|
/**
|
||||||
|
* 数组的方法除了 forEach 之外,回调函数必须有返回值
|
||||||
|
*/
|
||||||
|
'array-callback-return': 'warn',
|
||||||
|
/**
|
||||||
|
* 要求箭头函数体使用大括号
|
||||||
|
*/
|
||||||
|
'arrow-body-style': ['warn', 'as-needed'],
|
||||||
|
/**
|
||||||
|
* 要求箭头函数的参数使用圆括号
|
||||||
|
*/
|
||||||
|
'arrow-parens': [
|
||||||
|
'warn',
|
||||||
|
'as-needed',
|
||||||
|
{
|
||||||
|
requireForBlockBody: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 强制箭头函数的箭头前后使用一致的空格
|
||||||
|
*/
|
||||||
|
'arrow-spacing': 'warn',
|
||||||
|
/**
|
||||||
|
* 要求打开的块标志和同一行上的标志拥有一致的间距。此规则还会在同一行关闭的块标记和前边的标记强制实施一致的间距。
|
||||||
|
*/
|
||||||
|
'block-spacing': 'error',
|
||||||
|
/**
|
||||||
|
* 强制在代码块中使用一致的大括号风格
|
||||||
|
*/
|
||||||
|
'brace-style': 'error',
|
||||||
|
/**
|
||||||
|
* 使用驼峰命名法(camelCase)命名对象、函数和实例。
|
||||||
|
*/
|
||||||
|
camelcase: [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
ignoreDestructuring: true,
|
||||||
|
properties: 'never',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 添加尾随逗号
|
||||||
|
*/
|
||||||
|
'comma-dangle': ['warn', 'always-multiline'],
|
||||||
|
/**
|
||||||
|
* 强制在逗号前后使用一致的空格
|
||||||
|
*/
|
||||||
|
'comma-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
before: false,
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 强制使用一致的逗号风格
|
||||||
|
*/
|
||||||
|
'comma-style': ['error', 'last'],
|
||||||
|
/**
|
||||||
|
* 强制在计算的属性的方括号中使用一致的空格
|
||||||
|
*/
|
||||||
|
'computed-property-spacing': ['warn', 'never'],
|
||||||
|
/**
|
||||||
|
* 禁止使用 foo['bar'],必须写成 foo.bar
|
||||||
|
*/
|
||||||
|
'dot-notation': 'warn',
|
||||||
|
/**
|
||||||
|
* 要求或禁止文件末尾存在空行
|
||||||
|
*/
|
||||||
|
'eol-last': ['error', 'always'],
|
||||||
|
/**
|
||||||
|
* 必须使用 === 或 !==,禁止使用 == 或 !=
|
||||||
|
*/
|
||||||
|
eqeqeq: ['warn', 'always'],
|
||||||
|
/**
|
||||||
|
* 要求或禁止在函数标识符和其调用之间有空格
|
||||||
|
*/
|
||||||
|
'func-call-spacing': ['error', 'never'],
|
||||||
|
/**
|
||||||
|
* 必须只使用函数声明或只使用函数表达式
|
||||||
|
*/
|
||||||
|
'func-style': ['off', 'expression'],
|
||||||
|
/**
|
||||||
|
* 强制在函数括号内使用一致的换行
|
||||||
|
*/
|
||||||
|
'function-paren-newline': ['warn', 'multiline'],
|
||||||
|
/**
|
||||||
|
* 强制 generator 函数中 * 号周围使用一致的空格
|
||||||
|
*/
|
||||||
|
'generator-star-spacing': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
before: false,
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 限制变量名长度
|
||||||
|
*/
|
||||||
|
'id-length': 'off',
|
||||||
|
/**
|
||||||
|
* 强制隐式返回的箭头函数体的位置
|
||||||
|
*/
|
||||||
|
'implicit-arrow-linebreak': ['warn', 'beside'],
|
||||||
|
/**
|
||||||
|
* 使用 2 个空格缩进
|
||||||
|
*/
|
||||||
|
indent: [
|
||||||
|
'warn',
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
SwitchCase: 1,
|
||||||
|
VariableDeclarator: 1,
|
||||||
|
outerIIFEBody: 1,
|
||||||
|
FunctionDeclaration: {
|
||||||
|
parameters: 1,
|
||||||
|
body: 1,
|
||||||
|
},
|
||||||
|
FunctionExpression: {
|
||||||
|
parameters: 1,
|
||||||
|
body: 1,
|
||||||
|
},
|
||||||
|
CallExpression: {
|
||||||
|
arguments: 1,
|
||||||
|
},
|
||||||
|
ArrayExpression: 1,
|
||||||
|
ObjectExpression: 1,
|
||||||
|
ImportDeclaration: 1,
|
||||||
|
flatTernaryExpressions: false,
|
||||||
|
ignoredNodes: [
|
||||||
|
'JSXElement',
|
||||||
|
'JSXElement > *',
|
||||||
|
'JSXAttribute',
|
||||||
|
'JSXIdentifier',
|
||||||
|
'JSXNamespacedName',
|
||||||
|
'JSXMemberExpression',
|
||||||
|
'JSXSpreadAttribute',
|
||||||
|
'JSXExpressionContainer',
|
||||||
|
'JSXOpeningElement',
|
||||||
|
'JSXClosingElement',
|
||||||
|
'JSXFragment',
|
||||||
|
'JSXOpeningFragment',
|
||||||
|
'JSXClosingFragment',
|
||||||
|
'JSXText',
|
||||||
|
'JSXEmptyExpression',
|
||||||
|
'JSXSpreadChild',
|
||||||
|
],
|
||||||
|
ignoreComments: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 强制在对象字面量的属性中键和值之间使用一致的间距
|
||||||
|
*/
|
||||||
|
'key-spacing': 'error',
|
||||||
|
/**
|
||||||
|
* 强制在关键字前后使用一致的空格
|
||||||
|
*/
|
||||||
|
'keyword-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
overrides: {
|
||||||
|
if: {
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
for: {
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
while: {
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
else: {
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 只允许使用 unix 的 LF 作为换行符,Windows 的 CRLF 不可以使用
|
||||||
|
*/
|
||||||
|
'linebreak-style': ['warn', 'unix'],
|
||||||
|
/**
|
||||||
|
* 强制一行的最大长度,限制单行不能超过100个字符,字符串和正则表达式除外。
|
||||||
|
*/
|
||||||
|
'max-len': [
|
||||||
|
'off',
|
||||||
|
{
|
||||||
|
code: 120,
|
||||||
|
ignoreStrings: true,
|
||||||
|
ignoreUrls: true,
|
||||||
|
ignoreRegExpLiterals: true,
|
||||||
|
ignoreTemplateLiterals: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 只有在命名构造器或者类的时候,才用帕斯卡拼命名法(PascalCase),即首字母大写。
|
||||||
|
*/
|
||||||
|
'new-cap': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
newIsCap: true,
|
||||||
|
newIsCapExceptions: [],
|
||||||
|
capIsNew: false,
|
||||||
|
capIsNewExceptions: ['Immutable.Map', 'Immutable.Set', 'Immutable.List'],
|
||||||
|
properties: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 在编写多个方法链式调用(超过两个方法链式调用)时。 使用前导点,强调这行是一个方法调用,而不是一个语句。
|
||||||
|
*/
|
||||||
|
'newline-per-chained-call': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
ignoreChainWithDepth: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 使用字面量语法创建数组。
|
||||||
|
*/
|
||||||
|
'no-array-constructor': ['error'],
|
||||||
|
/**
|
||||||
|
* 在 case 和 default 的子句中,如果存在声明 (例如. let, const, function, 和 class),使用大括号来创建块级作用域。
|
||||||
|
*/
|
||||||
|
'no-case-declarations': 'error',
|
||||||
|
/**
|
||||||
|
* 避免搞混箭头函数符号 (=>) 和比较运算符 (<=, >=)。
|
||||||
|
*/
|
||||||
|
'no-confusing-arrow': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁止对使用 const 定义的常量重新赋值
|
||||||
|
*/
|
||||||
|
'no-const-assign': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止重复定义类的成员
|
||||||
|
*/
|
||||||
|
'no-dupe-class-members': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止在 else 内使用 return,必须改为提前结束
|
||||||
|
*/
|
||||||
|
'no-else-return': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
allowElseIf: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止使用 eval
|
||||||
|
*/
|
||||||
|
'no-eval': 'error',
|
||||||
|
/**
|
||||||
|
* 不要使用迭代器。
|
||||||
|
* @reason 推荐使用 JavaScript 的高阶函数代替 for-in。
|
||||||
|
*/
|
||||||
|
'no-iterator': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁止在循环内的函数内部出现循环体条件语句中定义的变量
|
||||||
|
*/
|
||||||
|
'no-loop-func': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止混合使用不同的操作符:
|
||||||
|
* - 禁止 `%`, `**` 之间混用
|
||||||
|
* - 禁止 `%` 与其它运算符之间混用
|
||||||
|
* - 禁止乘除运算符之间混用
|
||||||
|
* - 禁止位运算符之间的任何混用
|
||||||
|
* - 禁止比较运算符之间混用
|
||||||
|
* - 禁止 `&&`, `||` 之间混用
|
||||||
|
*/
|
||||||
|
'no-mixed-operators': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
groups: [
|
||||||
|
['%', '**'],
|
||||||
|
['%', '+'],
|
||||||
|
['%', '-'],
|
||||||
|
['%', '*'],
|
||||||
|
['%', '/'],
|
||||||
|
['&', '|', '<<', '>>', '>>>'],
|
||||||
|
['==', '!=', '===', '!=='],
|
||||||
|
['&&', '||'],
|
||||||
|
],
|
||||||
|
allowSamePrecedence: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止连续赋值,比如 foo = bar = 1
|
||||||
|
*/
|
||||||
|
'no-multi-assign': 'error',
|
||||||
|
/**
|
||||||
|
* 不要使用多个空行填充代码。
|
||||||
|
*/
|
||||||
|
'no-multiple-empty-lines': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止使用嵌套的三元表达式,比如 a ? b : c ? d : e
|
||||||
|
*/
|
||||||
|
'no-nested-ternary': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁止使用 new Function
|
||||||
|
* @reason 这和 eval 是等价的
|
||||||
|
*/
|
||||||
|
'no-new-func': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止直接 new Object
|
||||||
|
*/
|
||||||
|
'no-new-object': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止使用 new 来生成 String, Number 或 Boolean
|
||||||
|
*/
|
||||||
|
'no-new-wrappers': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁止对函数的参数重新赋值
|
||||||
|
*/
|
||||||
|
'no-param-reassign': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
props: true,
|
||||||
|
ignorePropertyModificationsFor: [
|
||||||
|
'acc',
|
||||||
|
'accumulator',
|
||||||
|
'e',
|
||||||
|
'ctx',
|
||||||
|
'req',
|
||||||
|
'request',
|
||||||
|
'res',
|
||||||
|
'response',
|
||||||
|
'$scope',
|
||||||
|
'staticContext',
|
||||||
|
'state',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止使用 ++ 或 --
|
||||||
|
*/
|
||||||
|
'no-plusplus': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowForLoopAfterthoughts: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止使用 hasOwnProperty, isPrototypeOf 或 propertyIsEnumerable
|
||||||
|
*/
|
||||||
|
'no-prototype-builtins': 'error',
|
||||||
|
/**
|
||||||
|
* 计算指数时,可以使用 ** 运算符。
|
||||||
|
*/
|
||||||
|
'no-restricted-properties': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
object: 'Math',
|
||||||
|
property: 'pow',
|
||||||
|
message: 'Please use ** instand',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 推荐使用 JavaScript 的高阶函数代替 for-in
|
||||||
|
*/
|
||||||
|
'no-restricted-syntax': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
selector: 'ForInStatement',
|
||||||
|
message:
|
||||||
|
'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: 'LabeledStatement',
|
||||||
|
message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: 'WithStatement',
|
||||||
|
message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 避免在行尾添加空格。
|
||||||
|
*/
|
||||||
|
'no-trailing-spaces': 'error',
|
||||||
|
/**
|
||||||
|
* 变量应先声明再使用,禁止引用任何未声明的变量,除非你明确知道引用的变量存在于当前作用域链上。
|
||||||
|
*/
|
||||||
|
'no-undef': ['error'],
|
||||||
|
/**
|
||||||
|
* 禁止变量名出现下划线
|
||||||
|
*/
|
||||||
|
'no-underscore-dangle': 'warn',
|
||||||
|
/**
|
||||||
|
* 必须使用 !a 替代 a ? false : true
|
||||||
|
*/
|
||||||
|
'no-unneeded-ternary': 'warn',
|
||||||
|
/**
|
||||||
|
* 已定义的变量必须使用
|
||||||
|
* 但不检查最后一个使用的参数之前的参数
|
||||||
|
* 也不检查 rest 属性的兄弟属性
|
||||||
|
*/
|
||||||
|
'no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
args: 'after-used',
|
||||||
|
ignoreRestSiblings: true,
|
||||||
|
argsIgnorePattern: '^_.+',
|
||||||
|
varsIgnorePattern: '^_.+',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止出现没必要的 constructor
|
||||||
|
*/
|
||||||
|
'no-useless-constructor': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁止出现没必要的转义
|
||||||
|
*/
|
||||||
|
'no-useless-escape': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止使用 var
|
||||||
|
*/
|
||||||
|
'no-var': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止属性前有空白
|
||||||
|
*/
|
||||||
|
'no-whitespace-before-property': 'warn',
|
||||||
|
/**
|
||||||
|
* 强制单个语句的位置
|
||||||
|
*/
|
||||||
|
'nonblock-statement-body-position': ['error', 'beside'],
|
||||||
|
/**
|
||||||
|
* 强制在大括号中使用一致的空格
|
||||||
|
*/
|
||||||
|
'object-curly-spacing': ['warn', 'always'],
|
||||||
|
/**
|
||||||
|
* 将对象方法、属性简写,且间歇属性放在前面。
|
||||||
|
*/
|
||||||
|
'object-shorthand': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁止变量申明时用逗号一次申明多个
|
||||||
|
*/
|
||||||
|
'one-var': ['warn', 'never'],
|
||||||
|
/**
|
||||||
|
* 避免在赋值语句 = 前后换行。如果你的代码单行长度超过了 max-len 定义的长度而不得不换行,那么使用括号包裹。
|
||||||
|
*/
|
||||||
|
'operator-linebreak': [
|
||||||
|
'error',
|
||||||
|
'before',
|
||||||
|
{
|
||||||
|
overrides: {
|
||||||
|
'=': 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 要求或禁止块内填充
|
||||||
|
*/
|
||||||
|
'padded-blocks': ['error', 'never'],
|
||||||
|
/**
|
||||||
|
* 要求回调函数使用箭头函数
|
||||||
|
*/
|
||||||
|
'prefer-arrow-callback': 'warn',
|
||||||
|
/**
|
||||||
|
* 申明后不再被修改的变量必须使用 const 来申明
|
||||||
|
*/
|
||||||
|
'prefer-const': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
destructuring: 'any',
|
||||||
|
ignoreReadBeforeAssign: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 优先使用解构赋值
|
||||||
|
*/
|
||||||
|
'prefer-destructuring': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
VariableDeclarator: {
|
||||||
|
array: false,
|
||||||
|
object: true,
|
||||||
|
},
|
||||||
|
AssignmentExpression: {
|
||||||
|
array: true,
|
||||||
|
object: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enforceForRenamedProperties: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 必须使用 ...args 而不是 arguments
|
||||||
|
*/
|
||||||
|
'prefer-rest-params': 'warn',
|
||||||
|
/**
|
||||||
|
* 必须使用 ... 而不是 apply,比如 foo(...args)
|
||||||
|
*/
|
||||||
|
'prefer-spread': 'warn',
|
||||||
|
/**
|
||||||
|
* 必须使用模版字符串而不是字符串连接
|
||||||
|
*/
|
||||||
|
'prefer-template': 'error',
|
||||||
|
/**
|
||||||
|
* 要求对象字面量属性名称用引号括起来
|
||||||
|
*/
|
||||||
|
'quote-props': [
|
||||||
|
'error',
|
||||||
|
'as-needed',
|
||||||
|
{
|
||||||
|
keywords: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 使用单引号 '' 定义字符串
|
||||||
|
*/
|
||||||
|
quotes: [
|
||||||
|
'warn',
|
||||||
|
'single',
|
||||||
|
{
|
||||||
|
allowTemplateLiterals: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* parseInt 必须传入第二个参数
|
||||||
|
*/
|
||||||
|
radix: 'warn',
|
||||||
|
/**
|
||||||
|
* 要加分号
|
||||||
|
*/
|
||||||
|
semi: ['error', 'always'],
|
||||||
|
/**
|
||||||
|
* 强制在块之前使用一致的空格
|
||||||
|
*/
|
||||||
|
'space-before-blocks': 'error',
|
||||||
|
/**
|
||||||
|
* 强制在 function 的左括号之前使用一致的空格
|
||||||
|
*/
|
||||||
|
'space-before-function-paren': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
anonymous: 'always',
|
||||||
|
named: 'never',
|
||||||
|
asyncArrow: 'always',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 强制在圆括号内使用一致的空格
|
||||||
|
*/
|
||||||
|
'space-in-parens': ['error', 'never'],
|
||||||
|
/**
|
||||||
|
* 要求操作符周围有空格
|
||||||
|
*/
|
||||||
|
'space-infix-ops': 'error',
|
||||||
|
/**
|
||||||
|
* 注释的斜线或 * 后必须有空格
|
||||||
|
*/
|
||||||
|
'spaced-comment': ['error', 'always'],
|
||||||
|
/**
|
||||||
|
* 要求或禁止模板字符串中的嵌入表达式周围空格的使用
|
||||||
|
*/
|
||||||
|
'template-curly-spacing': ['error', 'never'],
|
||||||
|
/**
|
||||||
|
* 要求立即执行的函数使用括号括起来
|
||||||
|
*/
|
||||||
|
'wrap-iife': ['error', 'outside'],
|
||||||
|
},
|
||||||
|
};
|
38
eslint-config/flat/import-sort.mjs
Normal file
38
eslint-config/flat/import-sort.mjs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import simpleImportSort from 'eslint-plugin-simple-import-sort';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
files: ['**/*.{js,mjs,cjs,ts,vue}'],
|
||||||
|
plugins: {
|
||||||
|
'simple-import-sort': simpleImportSort,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'simple-import-sort/imports': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
groups: [
|
||||||
|
['./polyfills'],
|
||||||
|
['^(node)(:.*|$)'],
|
||||||
|
// Node.js builtins. You could also generate this regex if you use a `.js` config.
|
||||||
|
// For example: `^(${require("module").builtinModules.join("|")})(/|$)`
|
||||||
|
[
|
||||||
|
'^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)',
|
||||||
|
],
|
||||||
|
// Packages. `react|vue` related packages come first.
|
||||||
|
['^(react|vue|vite|vitest)', '^@?\\w'],
|
||||||
|
['^(@tencent)(/.*|$)'],
|
||||||
|
['^(@tmagic)(/.*|$)'],
|
||||||
|
// Internal packages.
|
||||||
|
['^(@|@editor|@data-source)(/.*|$)'],
|
||||||
|
// Side effect imports.
|
||||||
|
['^\\u0000'],
|
||||||
|
// Parent imports. Put `..` last.
|
||||||
|
['^\\.\\.(?!/?$)', '^\\.\\./?$'],
|
||||||
|
// Other relative imports. Put same-folder imports and `.` last.
|
||||||
|
['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
|
||||||
|
// Style imports.
|
||||||
|
['^.+\\.s?css$'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
37
eslint-config/flat/import.mjs
Normal file
37
eslint-config/flat/import.mjs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { rules } from 'eslint-plugin-import';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
import: {
|
||||||
|
meta: { name: 'eslint-plugin-import' },
|
||||||
|
rules,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2018,
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
/**
|
||||||
|
* 导入语句前不允许有任何非导入语句
|
||||||
|
*/
|
||||||
|
'import/first': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止重复导入模块
|
||||||
|
*/
|
||||||
|
'import/no-duplicates': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止使用 let 导出
|
||||||
|
*/
|
||||||
|
'import/no-mutable-exports': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁用导入的模块时使用 webpack 特有的语法(感叹号)
|
||||||
|
*/
|
||||||
|
'import/no-webpack-loader-syntax': 'warn',
|
||||||
|
/**
|
||||||
|
* 当只有一个导出时,必须使用 export default 来导出
|
||||||
|
*/
|
||||||
|
'import/prefer-default-export': 'off',
|
||||||
|
},
|
||||||
|
};
|
@ -1,5 +1,4 @@
|
|||||||
module.exports = {
|
export default {
|
||||||
plugins: ['prettier'],
|
|
||||||
rules: {
|
rules: {
|
||||||
'wrap-iife': 'off',
|
'wrap-iife': 'off',
|
||||||
'template-curly-spacing': 'off',
|
'template-curly-spacing': 'off',
|
376
eslint-config/flat/ts.mjs
Normal file
376
eslint-config/flat/ts.mjs
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
export default {
|
||||||
|
files: ['**/*.ts', '**/*.tsx'],
|
||||||
|
rules: {
|
||||||
|
'brace-style': 'off',
|
||||||
|
'no-empty-function': 'off',
|
||||||
|
// https://github.com/typescript-eslint/typescript-eslint/issues/491
|
||||||
|
'no-invalid-this': 'off',
|
||||||
|
'no-magic-numbers': 'off',
|
||||||
|
'react/sort-comp': 'off',
|
||||||
|
'func-call-spacing': 'off',
|
||||||
|
'comma-spacing': 'off',
|
||||||
|
'dot-notation': 'off',
|
||||||
|
indent: 'off',
|
||||||
|
'keyword-spacing': 'off',
|
||||||
|
camelcase: 'off',
|
||||||
|
'no-underscore-dangle': 'off',
|
||||||
|
'no-array-constructor': 'off',
|
||||||
|
'no-dupe-class-members': 'off',
|
||||||
|
'no-undef': 'off',
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'no-useless-constructor': 'off',
|
||||||
|
quotes: 'off',
|
||||||
|
semi: 'off',
|
||||||
|
'space-before-function-paren': 'off',
|
||||||
|
// https://github.com/typescript-eslint/typescript-eslint/issues/600
|
||||||
|
'spaced-comment': ['error', 'always', { markers: ['/'] }],
|
||||||
|
/**
|
||||||
|
* 重载的函数必须写在一起
|
||||||
|
* @reason 增加可读性
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/adjacent-overload-signatures': 'error',
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@stylistic/ts/brace-style': 'error',
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@stylistic/comma-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
before: false,
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 类型断言必须使用 as Type,禁止使用 <Type>,禁止对对象字面量进行类型断言(断言成 any 是允许的)
|
||||||
|
* @reason <Type> 容易被理解为 jsx
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/consistent-type-assertions': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
assertionStyle: 'as',
|
||||||
|
objectLiteralTypeAssertions: 'never',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 优先使用 interface 而不是 type
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/consistent-type-definitions': 'off',
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@typescript-eslint/dot-notation': 'warn',
|
||||||
|
/**
|
||||||
|
* 必须设置类的成员的可访问性
|
||||||
|
* @reason 将不需要公开的成员设为私有的,可以增强代码的可理解性,对文档输出也很友好
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/explicit-member-accessibility': 'off',
|
||||||
|
/**
|
||||||
|
* 要求或禁止在函数标识符和其调用之间有空格
|
||||||
|
*/
|
||||||
|
'@stylistic/ts/func-call-spacing': ['error', 'never'],
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@stylistic/ts/indent': [
|
||||||
|
'warn',
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
SwitchCase: 1,
|
||||||
|
VariableDeclarator: 1,
|
||||||
|
outerIIFEBody: 1,
|
||||||
|
FunctionDeclaration: {
|
||||||
|
parameters: 1,
|
||||||
|
body: 1,
|
||||||
|
},
|
||||||
|
FunctionExpression: {
|
||||||
|
parameters: 1,
|
||||||
|
body: 1,
|
||||||
|
},
|
||||||
|
CallExpression: {
|
||||||
|
arguments: 1,
|
||||||
|
},
|
||||||
|
ArrayExpression: 1,
|
||||||
|
ObjectExpression: 1,
|
||||||
|
ImportDeclaration: 1,
|
||||||
|
flatTernaryExpressions: false,
|
||||||
|
ignoredNodes: [
|
||||||
|
'JSXElement',
|
||||||
|
'JSXElement > *',
|
||||||
|
'JSXAttribute',
|
||||||
|
'JSXIdentifier',
|
||||||
|
'JSXNamespacedName',
|
||||||
|
'JSXMemberExpression',
|
||||||
|
'JSXSpreadAttribute',
|
||||||
|
'JSXExpressionContainer',
|
||||||
|
'JSXOpeningElement',
|
||||||
|
'JSXClosingElement',
|
||||||
|
'JSXFragment',
|
||||||
|
'JSXOpeningFragment',
|
||||||
|
'JSXClosingFragment',
|
||||||
|
'JSXText',
|
||||||
|
'JSXEmptyExpression',
|
||||||
|
'JSXSpreadChild',
|
||||||
|
],
|
||||||
|
ignoreComments: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@stylistic/ts/keyword-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
overrides: {
|
||||||
|
if: {
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
for: {
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
while: {
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
else: {
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
before: true,
|
||||||
|
after: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 指定类成员的排序规则
|
||||||
|
* @reason 优先级:
|
||||||
|
* 1. static > instance
|
||||||
|
* 2. field > constructor > method
|
||||||
|
* 3. public > protected > private
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/member-ordering': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
default: [
|
||||||
|
'public-static-field',
|
||||||
|
'protected-static-field',
|
||||||
|
'private-static-field',
|
||||||
|
'static-field',
|
||||||
|
'public-static-method',
|
||||||
|
'protected-static-method',
|
||||||
|
'private-static-method',
|
||||||
|
'static-method',
|
||||||
|
'public-instance-field',
|
||||||
|
'protected-instance-field',
|
||||||
|
'private-instance-field',
|
||||||
|
'public-field',
|
||||||
|
'protected-field',
|
||||||
|
'private-field',
|
||||||
|
'instance-field',
|
||||||
|
'field',
|
||||||
|
'constructor',
|
||||||
|
'public-instance-method',
|
||||||
|
'protected-instance-method',
|
||||||
|
'private-instance-method',
|
||||||
|
'public-method',
|
||||||
|
'protected-method',
|
||||||
|
'private-method',
|
||||||
|
'instance-method',
|
||||||
|
'method',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 接口中的方法必须用属性的方式定义
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/method-signature-style': 'off',
|
||||||
|
/** 代替 JS 规则 camelCase 的 TS 规则 */
|
||||||
|
'@typescript-eslint/naming-convention': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
selector: 'function',
|
||||||
|
format: ['camelCase', 'PascalCase'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: 'variable',
|
||||||
|
format: ['camelCase', 'UPPER_CASE'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: 'variable',
|
||||||
|
modifiers: ['global'],
|
||||||
|
format: ['camelCase', 'PascalCase', 'UPPER_CASE'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: 'variable',
|
||||||
|
format: ['camelCase', 'PascalCase'],
|
||||||
|
types: ['function'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: 'variable',
|
||||||
|
modifiers: ['exported'],
|
||||||
|
format: ['UPPER_CASE'],
|
||||||
|
types: ['boolean', 'string', 'number', 'array'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: 'variable',
|
||||||
|
modifiers: ['exported'],
|
||||||
|
format: ['camelCase', 'PascalCase'],
|
||||||
|
types: ['function'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: ['class', 'typeLike'],
|
||||||
|
format: ['PascalCase'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
selector: ['classMethod', 'classProperty'],
|
||||||
|
leadingUnderscore: 'forbid',
|
||||||
|
trailingUnderscore: 'forbid',
|
||||||
|
format: ['camelCase'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@typescript-eslint/no-array-constructor': 'error',
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@typescript-eslint/no-dupe-class-members': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止定义空的接口
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-empty-interface': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止给一个初始化时直接赋值为 number, string 的变量显式的声明类型
|
||||||
|
* @reason 可以简化代码
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-inferrable-types': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁止对 promise 的误用,详见示例
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-misused-promises': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
checksConditionals: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止使用 namespace 来定义命名空间
|
||||||
|
* @reason 使用 es6 引入模块,才是更标准的方式。
|
||||||
|
* 但是允许使用 declare namespace ... {} 来定义外部命名空间
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-namespace': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowDeclarations: true,
|
||||||
|
allowDefinitionFiles: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止在 optional chaining 之后使用 non-null 断言(感叹号)
|
||||||
|
* @reason optional chaining 后面的属性一定是非空的
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止给类的构造函数的参数添加修饰符
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-parameter-properties': 'off',
|
||||||
|
/**
|
||||||
|
* 禁止使用 require
|
||||||
|
* @reason 统一使用 import 来引入模块,特殊情况使用单行注释允许 require 引入
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-require-imports': 'error',
|
||||||
|
/**
|
||||||
|
* 禁止将 this 赋值给其他变量,除非是解构赋值
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-this-alias': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowDestructuring: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止无用的表达式
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-unused-expressions': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowShortCircuit: true,
|
||||||
|
allowTernary: true,
|
||||||
|
allowTaggedTemplates: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
args: 'after-used',
|
||||||
|
ignoreRestSiblings: true,
|
||||||
|
argsIgnorePattern: '^_.+',
|
||||||
|
varsIgnorePattern: '^_.+',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止出现没必要的 constructor
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/no-useless-constructor': 'warn',
|
||||||
|
/**
|
||||||
|
* 使用 for 循环遍历数组时,如果索引仅用于获取成员,则必须使用 for of 循环替代 for 循环
|
||||||
|
* @reason for of 循环更加易读
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/prefer-for-of': 'warn',
|
||||||
|
/**
|
||||||
|
* 使用函数类型别名替代包含函数调用声明的接口
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/prefer-function-type': 'warn',
|
||||||
|
/**
|
||||||
|
* 禁止使用 module 来定义命名空间
|
||||||
|
* @reason module 已成为 js 的关键字
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/prefer-namespace-keyword': 'error',
|
||||||
|
/**
|
||||||
|
* 使用 optional chaining 替代 &&
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/prefer-optional-chain': 'error',
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@stylistic/ts/quotes': [
|
||||||
|
'warn',
|
||||||
|
'single',
|
||||||
|
{
|
||||||
|
allowTemplateLiterals: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@stylistic/ts/semi': ['error', 'always'],
|
||||||
|
/** 同 JS 规则的 TS 版本 */
|
||||||
|
'@stylistic/ts/space-before-function-paren': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
anonymous: 'always',
|
||||||
|
named: 'never',
|
||||||
|
asyncArrow: 'always',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 禁止使用三斜杠导入文件
|
||||||
|
* @reason 三斜杠是已废弃的语法,但在类型声明文件中还是可以使用的
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/triple-slash-reference': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
path: 'never',
|
||||||
|
types: 'always',
|
||||||
|
lib: 'always',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 在类型注释周围需要一致的间距
|
||||||
|
*/
|
||||||
|
'@stylistic/ts/type-annotation-spacing': 'error',
|
||||||
|
/**
|
||||||
|
* interface 和 type 定义时必须声明成员的类型
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/typedef': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
arrayDestructuring: false,
|
||||||
|
arrowParameter: false,
|
||||||
|
memberVariableDeclaration: false,
|
||||||
|
objectDestructuring: false,
|
||||||
|
parameter: false,
|
||||||
|
propertyDeclaration: true,
|
||||||
|
variableDeclaration: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/**
|
||||||
|
* 函数重载时,若能通过联合类型将两个函数的类型声明合为一个,则使用联合类型而不是两个函数声明
|
||||||
|
*/
|
||||||
|
'@typescript-eslint/unified-signatures': 'error',
|
||||||
|
},
|
||||||
|
};
|
39
eslint-config/index.mjs
Normal file
39
eslint-config/index.mjs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import js from '@eslint/js';
|
||||||
|
import stylistic from '@stylistic/eslint-plugin';
|
||||||
|
import stylisticTs from '@stylistic/eslint-plugin-ts';
|
||||||
|
import parserTs from '@typescript-eslint/parser';
|
||||||
|
import { defineConfig } from 'eslint/config';
|
||||||
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
||||||
|
import pluginVue from 'eslint-plugin-vue';
|
||||||
|
import globals from 'globals';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
|
||||||
|
import tencentEslintBaseConfig from './flat/base.mjs';
|
||||||
|
import tencentEslintImportexport from './flat/import.mjs';
|
||||||
|
import ImportSortConfig from './flat/import-sort.mjs';
|
||||||
|
import tencentEslintPrettierConfig from './flat/prettier.mjs';
|
||||||
|
import tencentEslintTsConfig from './flat/ts.mjs';
|
||||||
|
|
||||||
|
export default (tsconfigRootDir) =>
|
||||||
|
defineConfig([
|
||||||
|
{ files: ['**/*.{js,mjs,cjs}'], plugins: { js }, extends: ['js/recommended'] },
|
||||||
|
{ files: ['**/*.{js,mjs,cjs,ts,vue}'], languageOptions: { globals: { ...globals.browser, ...globals.node } } },
|
||||||
|
...tseslint.config(tencentEslintBaseConfig, tencentEslintImportexport, tseslint.configs.base, {
|
||||||
|
plugins: {
|
||||||
|
'@stylistic': stylistic,
|
||||||
|
'@stylistic/ts': stylisticTs,
|
||||||
|
},
|
||||||
|
languageOptions: {
|
||||||
|
parser: parserTs,
|
||||||
|
parserOptions: {
|
||||||
|
project: tsconfigRootDir,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...tencentEslintTsConfig,
|
||||||
|
}),
|
||||||
|
pluginVue.configs['flat/essential'],
|
||||||
|
{ files: ['**/*.vue'], languageOptions: { parserOptions: { parser: tseslint.parser } } },
|
||||||
|
eslintPluginPrettierRecommended,
|
||||||
|
tencentEslintPrettierConfig,
|
||||||
|
ImportSortConfig,
|
||||||
|
]);
|
29
eslint-config/package.json
Normal file
29
eslint-config/package.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"name": "@tmagic/eslint-config",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"main": "index.mjs",
|
||||||
|
"type": "module",
|
||||||
|
"repository": {
|
||||||
|
"directory": "eslint-config",
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Tencent/tmagic-editor.git"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@eslint/js": "^9.24.0",
|
||||||
|
"@typescript-eslint/parser": "^8.30.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.30.1",
|
||||||
|
"@stylistic/eslint-plugin": "^4.2.0",
|
||||||
|
"@stylistic/eslint-plugin-ts": "^4.2.0",
|
||||||
|
"eslint-config-prettier": "^10.1.2",
|
||||||
|
"eslint-plugin-import": "^2.31.0",
|
||||||
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||||
|
"eslint-plugin-vue": "^10.0.0",
|
||||||
|
"eslint-plugin-prettier": "^5.2.6",
|
||||||
|
"globals": "^16.0.0",
|
||||||
|
"typescript-eslint": "^8.30.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": ">=9.24.0",
|
||||||
|
"prettier": ">=3.5.3"
|
||||||
|
}
|
||||||
|
}
|
41
eslint.config.js
Normal file
41
eslint.config.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
import { defineConfig, globalIgnores } from 'eslint/config';
|
||||||
|
|
||||||
|
import eslintConfig from '@tmagic/eslint-config';
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores([
|
||||||
|
'./docs/**/*',
|
||||||
|
'./packages/cli/lib/**/*',
|
||||||
|
'*/**/auto-imports.d.ts',
|
||||||
|
'*/**/components.d.ts',
|
||||||
|
'*/**/dist/**/*',
|
||||||
|
'*/**/.tmagic/**/*',
|
||||||
|
'*/**/public/**/*',
|
||||||
|
'*/**/types/**/*',
|
||||||
|
'*/**/*.config.ts',
|
||||||
|
'vite-env.d.ts',
|
||||||
|
]),
|
||||||
|
...eslintConfig(path.join(path.dirname(fileURLToPath(import.meta.url)), 'tsconfig.json')),
|
||||||
|
{
|
||||||
|
files: ['**/*.vue'],
|
||||||
|
rules: {
|
||||||
|
'vue/no-mutating-props': 'off',
|
||||||
|
'vue/multi-word-component-names': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.{js,mjs,cjs,ts,vue}'],
|
||||||
|
rules: {
|
||||||
|
'no-param-reassign': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.tsx'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/naming-convention': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
44
package.json
44
package.json
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.5.7",
|
"version": "1.5.15",
|
||||||
"name": "tmagic",
|
"name": "tmagic",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -9,8 +9,8 @@
|
|||||||
"clean:top": "rimraf */**/dist */**/types */dist coverage dwt* temp packages/cli/lib",
|
"clean:top": "rimraf */**/dist */**/types */dist coverage dwt* temp packages/cli/lib",
|
||||||
"clean:modules": "rimraf node_modules **/node_modules **/**/node_modules",
|
"clean:modules": "rimraf node_modules **/node_modules **/**/node_modules",
|
||||||
"clean:all": "pnpm clean:top && pnpm clean:modules",
|
"clean:all": "pnpm clean:top && pnpm clean:modules",
|
||||||
"lint": "eslint . --ext .js,.vue,.ts,.tsx",
|
"lint": "eslint --cache .",
|
||||||
"lint-fix": "eslint . --fix --ext .vue,.js,.ts,.tsx",
|
"lint-fix": "eslint --fix --cache .",
|
||||||
"playground": "pnpm --filter \"runtime-vue3\" build:libs && pnpm --filter \"runtime-vue3\" --filter \"tmagic-playground\" dev",
|
"playground": "pnpm --filter \"runtime-vue3\" build:libs && pnpm --filter \"runtime-vue3\" --filter \"tmagic-playground\" dev",
|
||||||
"pg": "pnpm playground",
|
"pg": "pnpm playground",
|
||||||
"playground:vue2": "pnpm --filter \"runtime-vue2\" build:libs && pnpm --filter \"runtime-vue2\" --filter \"tmagic-playground\" dev:vue2",
|
"playground:vue2": "pnpm --filter \"runtime-vue2\" build:libs && pnpm --filter \"runtime-vue2\" --filter \"tmagic-playground\" dev:vue2",
|
||||||
@ -46,25 +46,19 @@
|
|||||||
"@commitlint/cli": "^18.6.1",
|
"@commitlint/cli": "^18.6.1",
|
||||||
"@commitlint/config-conventional": "^18.6.3",
|
"@commitlint/config-conventional": "^18.6.3",
|
||||||
"@rollup/plugin-alias": "^5.1.1",
|
"@rollup/plugin-alias": "^5.1.1",
|
||||||
|
"@tmagic/eslint-config": "workspace: ^*",
|
||||||
"@types/node": "18.19.61",
|
"@types/node": "18.19.61",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
"@vitest/coverage-v8": "^2.1.9",
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
|
||||||
"@vitest/coverage-v8": "^2.1.8",
|
|
||||||
"@vue/compiler-sfc": "^3.5.13",
|
"@vue/compiler-sfc": "^3.5.13",
|
||||||
"c8": "^7.14.0",
|
"c8": "^7.14.0",
|
||||||
"commitizen": "^4.3.1",
|
"commitizen": "^4.3.1",
|
||||||
"conventional-changelog-cli": "^4.1.0",
|
"conventional-changelog-cli": "^4.1.0",
|
||||||
"cosmiconfig": "^8.3.6",
|
"cosmiconfig": "^8.3.6",
|
||||||
"cz-conventional-changelog": "^3.3.0",
|
"cz-conventional-changelog": "^3.3.0",
|
||||||
"element-plus": "^2.9.3",
|
"element-plus": "^2.9.7",
|
||||||
"enquirer": "^2.4.1",
|
"enquirer": "^2.4.1",
|
||||||
"eslint": "^8.57.1",
|
"eslint": "^9.25.0",
|
||||||
"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.32.0",
|
|
||||||
"execa": "^4.1.0",
|
"execa": "^4.1.0",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"husky": "^7.0.4",
|
"husky": "^7.0.4",
|
||||||
@ -72,20 +66,20 @@
|
|||||||
"lint-staged": "^11.2.6",
|
"lint-staged": "^11.2.6",
|
||||||
"minimist": "^1.2.8",
|
"minimist": "^1.2.8",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^3.5.3",
|
||||||
"recast": "^0.20.5",
|
"recast": "^0.23.11",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rollup": "^4.31.0",
|
"rollup": "^4.38.0",
|
||||||
"rollup-plugin-dts": "^6.1.1",
|
"rollup-plugin-dts": "^6.2.1",
|
||||||
"semver": "^7.6.3",
|
"semver": "^7.7.1",
|
||||||
"serialize-javascript": "^6.0.2",
|
"serialize-javascript": "^6.0.2",
|
||||||
"shx": "^0.3.4",
|
"shx": "^0.3.4",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "^5.8.2",
|
||||||
"vite": "^6.0.10",
|
"vite": "^6.2.4",
|
||||||
"vitepress": "^1.6.1",
|
"vitepress": "^1.6.3",
|
||||||
"vitest": "^3.0.2",
|
"vitest": "^3.1.1",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-tsc": "^2.2.0"
|
"vue-tsc": "^2.2.8"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"commitizen": {
|
"commitizen": {
|
||||||
@ -93,7 +87,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,ts,vue}": "eslint --fix",
|
"*.{js,ts,vue}": "eslint --fix --cache",
|
||||||
"*.scss": "prettier --write"
|
"*.scss": "prettier --write"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.5.7",
|
"version": "1.5.15",
|
||||||
"name": "@tmagic/cli",
|
"name": "@tmagic/cli",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
@ -31,7 +31,7 @@
|
|||||||
"esbuild": "^0.21.5",
|
"esbuild": "^0.21.5",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
"recast": "^0.23.9",
|
"recast": "^0.23.11",
|
||||||
"tslib": "^2.8.0"
|
"tslib": "^2.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
|
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
|
|
||||||
@ -6,16 +6,20 @@ import { ModuleMainFilePath, UserConfig } from './types';
|
|||||||
import { prepareEntryFile, resolveAppPackages } from './utils';
|
import { prepareEntryFile, resolveAppPackages } from './utils';
|
||||||
|
|
||||||
export default class Core {
|
export default class Core {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
public version = require('../package.json').version;
|
public version = require('../package.json').version;
|
||||||
|
|
||||||
public options: UserConfig;
|
public options: UserConfig;
|
||||||
|
|
||||||
public moduleMainFilePath: ModuleMainFilePath = {
|
public moduleMainFilePath: ModuleMainFilePath = {
|
||||||
|
componentPackage: {},
|
||||||
componentMap: {},
|
componentMap: {},
|
||||||
|
pluginPakcage: {},
|
||||||
pluginMap: {},
|
pluginMap: {},
|
||||||
configMap: {},
|
configMap: {},
|
||||||
valueMap: {},
|
valueMap: {},
|
||||||
eventMap: {},
|
eventMap: {},
|
||||||
|
datasourcePackage: {},
|
||||||
datasourceMap: {},
|
datasourceMap: {},
|
||||||
dsConfigMap: {},
|
dsConfigMap: {},
|
||||||
dsValueMap: {},
|
dsValueMap: {},
|
||||||
|
@ -29,6 +29,7 @@ export const cli = (defaultAppConfig: UserConfig): void => {
|
|||||||
const program = cac('tmagic');
|
const program = cac('tmagic');
|
||||||
|
|
||||||
// display core version and cli version
|
// display core version and cli version
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const versionCli = require('../package.json').version;
|
const versionCli = require('../package.json').version;
|
||||||
program.version(`tmagic/cli@${versionCli}`);
|
program.version(`tmagic/cli@${versionCli}`);
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
|
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
|
|
||||||
|
@ -54,11 +54,14 @@ export interface NpmConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ModuleMainFilePath {
|
export interface ModuleMainFilePath {
|
||||||
|
componentPackage: Record<string, string>;
|
||||||
componentMap: Record<string, string>;
|
componentMap: Record<string, string>;
|
||||||
|
pluginPakcage: Record<string, string>;
|
||||||
pluginMap: Record<string, string>;
|
pluginMap: Record<string, string>;
|
||||||
configMap: Record<string, string>;
|
configMap: Record<string, string>;
|
||||||
valueMap: Record<string, string>;
|
valueMap: Record<string, string>;
|
||||||
eventMap: Record<string, string>;
|
eventMap: Record<string, string>;
|
||||||
|
datasourcePackage: Record<string, string>;
|
||||||
datasourceMap: Record<string, string>;
|
datasourceMap: Record<string, string>;
|
||||||
dsConfigMap: Record<string, string>;
|
dsConfigMap: Record<string, string>;
|
||||||
dsValueMap: Record<string, string>;
|
dsValueMap: Record<string, string>;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import fs from 'fs';
|
import fs from 'node:fs';
|
||||||
import path from 'path';
|
import path from 'node:path';
|
||||||
|
|
||||||
export const backupFile = (runtimeSource: string, file: string) => {
|
export const backupFile = (runtimeSource: string, file: string) => {
|
||||||
const filePath = path.join(runtimeSource, file);
|
const filePath = path.join(runtimeSource, file);
|
||||||
|
@ -10,6 +10,7 @@ export const hasExportDefault = <T = any>(mod: unknown): mod is { default: T } =
|
|||||||
isPlainObject(mod) && !!mod.__esModule && Object.prototype.hasOwnProperty.call(mod, 'default');
|
isPlainObject(mod) && !!mod.__esModule && Object.prototype.hasOwnProperty.call(mod, 'default');
|
||||||
|
|
||||||
export const loadUserConfigCjs: UserConfigLoader = async (userConfigPath) => {
|
export const loadUserConfigCjs: UserConfigLoader = async (userConfigPath) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const required = require(userConfigPath);
|
const required = require(userConfigPath);
|
||||||
return hasExportDefault(required) ? required.default : required;
|
return hasExportDefault(required) ? required.default : required;
|
||||||
};
|
};
|
||||||
|
@ -5,33 +5,84 @@ import { EntryType } from '../types';
|
|||||||
|
|
||||||
export const prepareEntryFile = async (app: App) => {
|
export const prepareEntryFile = async (app: App) => {
|
||||||
const { moduleMainFilePath, options } = app;
|
const { moduleMainFilePath, options } = app;
|
||||||
const { componentFileAffix, dynamicImport, hooks, useTs = true } = options;
|
const { dynamicImport, hooks, useTs = true } = options;
|
||||||
|
|
||||||
let contentMap: Record<string, string> = {
|
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(
|
'async-comp-entry': generateContent(
|
||||||
useTs,
|
useTs,
|
||||||
EntryType.COMPONENT,
|
EntryType.COMPONENT,
|
||||||
|
moduleMainFilePath.componentPackage,
|
||||||
moduleMainFilePath.componentMap,
|
moduleMainFilePath.componentMap,
|
||||||
componentFileAffix,
|
|
||||||
dynamicImport,
|
dynamicImport,
|
||||||
),
|
),
|
||||||
'plugin-entry': generateContent(useTs, EntryType.PLUGIN, moduleMainFilePath.pluginMap),
|
'plugin-entry': generateContent(
|
||||||
'async-plugin-entry': generateContent(useTs, EntryType.PLUGIN, moduleMainFilePath.pluginMap, '', dynamicImport),
|
useTs,
|
||||||
'config-entry': generateContent(useTs, EntryType.CONFIG, moduleMainFilePath.configMap),
|
EntryType.PLUGIN,
|
||||||
'value-entry': generateContent(useTs, EntryType.VALUE, moduleMainFilePath.valueMap),
|
moduleMainFilePath.pluginPakcage,
|
||||||
'event-entry': generateContent(useTs, EntryType.EVENT, moduleMainFilePath.eventMap),
|
moduleMainFilePath.pluginMap,
|
||||||
'datasource-entry': generateContent(useTs, EntryType.DATASOURCE, moduleMainFilePath.datasourceMap),
|
),
|
||||||
|
'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(
|
'async-datasource-entry': generateContent(
|
||||||
useTs,
|
useTs,
|
||||||
EntryType.DATASOURCE,
|
EntryType.DATASOURCE,
|
||||||
|
moduleMainFilePath.datasourcePackage,
|
||||||
moduleMainFilePath.datasourceMap,
|
moduleMainFilePath.datasourceMap,
|
||||||
'',
|
|
||||||
dynamicImport,
|
dynamicImport,
|
||||||
),
|
),
|
||||||
'ds-config-entry': generateContent(useTs, EntryType.DS_CONFIG, moduleMainFilePath.dsConfigMap),
|
'ds-config-entry': generateContent(
|
||||||
'ds-value-entry': generateContent(useTs, EntryType.DS_VALUE, moduleMainFilePath.dsValueMap),
|
useTs,
|
||||||
'ds-event-entry': generateContent(useTs, EntryType.DS_EVENT, moduleMainFilePath.dsEventMap),
|
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') {
|
if (typeof hooks?.beforeWriteEntry === 'function') {
|
||||||
@ -44,7 +95,7 @@ export const prepareEntryFile = async (app: App) => {
|
|||||||
app.writeTemp(fileName, content);
|
app.writeTemp(fileName, content);
|
||||||
} else {
|
} else {
|
||||||
fileName = `${file}.js`;
|
fileName = `${file}.js`;
|
||||||
app.writeTemp(`${file}.d.ts`, `const type: Record<string, any>;\n\nexport default type;`);
|
app.writeTemp(`${file}.d.ts`, 'const type: Record<string, any>;\n\nexport default type;');
|
||||||
}
|
}
|
||||||
app.writeTemp(fileName, content);
|
app.writeTemp(fileName, content);
|
||||||
});
|
});
|
||||||
@ -53,8 +104,8 @@ export const prepareEntryFile = async (app: App) => {
|
|||||||
export const generateContent = (
|
export const generateContent = (
|
||||||
useTs: boolean,
|
useTs: boolean,
|
||||||
type: EntryType,
|
type: EntryType,
|
||||||
|
packageMap: Record<string, string> = {},
|
||||||
map: Record<string, string> = {},
|
map: Record<string, string> = {},
|
||||||
componentFileAffix = '',
|
|
||||||
dynamicImport = false,
|
dynamicImport = false,
|
||||||
) => {
|
) => {
|
||||||
const list: string[] = [];
|
const list: string[] = [];
|
||||||
@ -62,14 +113,14 @@ export const generateContent = (
|
|||||||
|
|
||||||
Object.entries(map).forEach(([key, packagePath]) => {
|
Object.entries(map).forEach(([key, packagePath]) => {
|
||||||
const name = makeCamelCase(key);
|
const name = makeCamelCase(key);
|
||||||
if (dynamicImport) {
|
|
||||||
list.push(
|
if ([EntryType.CONFIG, EntryType.EVENT, EntryType.VALUE].includes(type) && packagePath === packageMap[key]) {
|
||||||
`'${key}': () => import('${packagePath}${packagePath.endsWith(componentFileAffix) ? '' : componentFileAffix}')`,
|
importDeclarations.push(`import { ${type} as ${name} } from '${packageMap[key]}'`);
|
||||||
);
|
list.push(`'${key}': ${name}`);
|
||||||
|
} else if (dynamicImport) {
|
||||||
|
list.push(`'${key}': () => import('${packagePath}')`);
|
||||||
} else {
|
} else {
|
||||||
importDeclarations.push(
|
importDeclarations.push(`import ${name} from '${packagePath}'`);
|
||||||
`import ${name} from '${packagePath}${packagePath.endsWith(componentFileAffix) ? '' : componentFileAffix}'`,
|
|
||||||
);
|
|
||||||
list.push(`'${key}': ${name}`);
|
list.push(`'${key}': ${name}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -85,6 +136,7 @@ export const generateContent = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const prettyCode = (code: string) =>
|
export const prettyCode = (code: string) =>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
recast.prettyPrint(recast.parse(code.replace(/\\/g, '/'), { parser: require('recast/parsers/typescript') }), {
|
recast.prettyPrint(recast.parse(code.replace(/\\/g, '/'), { parser: require('recast/parsers/typescript') }), {
|
||||||
tabWidth: 2,
|
tabWidth: 2,
|
||||||
trailingComma: true,
|
trailingComma: true,
|
||||||
|
@ -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 = {}) {
|
const npmInstall = function (dependencies: Record<string, string>, cwd: string, npmConfig: NpmConfig = {}) {
|
||||||
try {
|
try {
|
||||||
const { client = 'npm', registry, installArgs = '' } = npmConfig;
|
const { client = 'npm', registry, installArgs = '', keepPackageJsonClean } = npmConfig;
|
||||||
const install = {
|
const install = {
|
||||||
npm: 'install',
|
npm: 'install',
|
||||||
yarn: 'add',
|
yarn: 'add',
|
||||||
pnpm: 'add',
|
pnpm: 'add',
|
||||||
}[client];
|
}[client];
|
||||||
|
|
||||||
const packages = Object.entries(dependencies)
|
let packages = Object.entries(dependencies);
|
||||||
.map(([name, version]) => (version ? `${name}@${version}` : name))
|
|
||||||
.join(' ');
|
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 installArgsString = `${installArgs ? ` ${installArgs}` : ''}`;
|
||||||
const registryString = `${registry ? ` --registry ${registry}` : ''}`;
|
const registryString = `${registry ? ` --registry ${registry}` : ''}`;
|
||||||
const command = `${client} ${install}${installArgsString} ${packages}${registryString}`;
|
const command = `${client} ${install}${installArgsString} ${packageNames}${registryString}`;
|
||||||
|
|
||||||
execInfo(cwd);
|
execInfo(cwd);
|
||||||
execInfo(command);
|
execInfo(command);
|
||||||
@ -110,6 +127,7 @@ const typeAssertion = function ({
|
|||||||
|
|
||||||
if (isFile(defaultFile)) {
|
if (isFile(defaultFile)) {
|
||||||
const defaultCode = fs.readFileSync(defaultFile, { encoding: 'utf-8', flag: 'r' });
|
const defaultCode = fs.readFileSync(defaultFile, { encoding: 'utf-8', flag: 'r' });
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const ast = recast.parse(defaultCode, { parser: require('recast/parsers/typescript') });
|
const ast = recast.parse(defaultCode, { parser: require('recast/parsers/typescript') });
|
||||||
if (
|
if (
|
||||||
isDatasource(
|
isDatasource(
|
||||||
@ -318,25 +336,30 @@ const parseEntry = function ({ ast, package: module, indexPath }: ParseEntryOpti
|
|||||||
const tokens = getASTTokenByTraverse({ ast, indexPath });
|
const tokens = getASTTokenByTraverse({ ast, indexPath });
|
||||||
let { config, value, event, component } = tokens;
|
let { config, value, event, component } = tokens;
|
||||||
|
|
||||||
if (!config) {
|
if (typeof config === 'undefined') {
|
||||||
info(`${module} 表单配置文件声明缺失`);
|
info(`${module} 表单配置文件声明缺失`);
|
||||||
}
|
}
|
||||||
if (!value) {
|
if (typeof value === 'undefined') {
|
||||||
info(`${module} 初始化数据文件声明缺失`);
|
info(`${module} 初始化数据文件声明缺失`);
|
||||||
}
|
}
|
||||||
if (!event) {
|
if (typeof event === 'undefined') {
|
||||||
info(`${module} 事件声明文件声明缺失`);
|
info(`${module} 事件声明文件声明缺失`);
|
||||||
}
|
}
|
||||||
if (!component) {
|
|
||||||
info(`${module} 组件或数据源文件声明不合法`);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const reg = /^.*[/\\]node_modules[/\\](.*)/;
|
const reg = /^.*[/\\]node_modules[/\\](.*)/;
|
||||||
|
|
||||||
|
if (config) {
|
||||||
[, config] = config.match(reg) || [, config];
|
[, config] = config.match(reg) || [, config];
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
[, value] = value.match(reg) || [, value];
|
[, value] = value.match(reg) || [, value];
|
||||||
|
}
|
||||||
|
if (component) {
|
||||||
[, component] = component.match(reg) || [, component];
|
[, component] = component.match(reg) || [, component];
|
||||||
|
}
|
||||||
|
if (event) {
|
||||||
[, event] = event.match(reg) || [, event];
|
[, event] = event.match(reg) || [, event];
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
config,
|
config,
|
||||||
@ -347,10 +370,10 @@ const parseEntry = function ({ ast, package: module, indexPath }: ParseEntryOpti
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string }) => {
|
const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string }) => {
|
||||||
let config = '';
|
let config: string | undefined;
|
||||||
let value = '';
|
let value: string | undefined;
|
||||||
let event = '';
|
let event: string | undefined;
|
||||||
let component = '';
|
let component: string | undefined;
|
||||||
const importSpecifiersMap: { [key: string]: string } = {};
|
const importSpecifiersMap: { [key: string]: string } = {};
|
||||||
const exportSpecifiersMap: { [key: string]: string | undefined } = {};
|
const exportSpecifiersMap: { [key: string]: string | undefined } = {};
|
||||||
|
|
||||||
@ -396,7 +419,11 @@ const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string
|
|||||||
visitExportDefaultDeclaration(p) {
|
visitExportDefaultDeclaration(p) {
|
||||||
const { node } = p;
|
const { node } = p;
|
||||||
const { declaration } = node as any;
|
const { declaration } = node as any;
|
||||||
|
|
||||||
|
if (importSpecifiersMap[declaration.name]) {
|
||||||
component = path.resolve(path.dirname(indexPath), importSpecifiersMap[declaration.name]);
|
component = path.resolve(path.dirname(indexPath), importSpecifiersMap[declaration.name]);
|
||||||
|
}
|
||||||
|
|
||||||
this.traverse(p);
|
this.traverse(p);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -405,7 +432,10 @@ const getASTTokenByTraverse = ({ ast, indexPath }: { ast: any; indexPath: string
|
|||||||
const exportValue = exportSpecifiersMap[exportName];
|
const exportValue = exportSpecifiersMap[exportName];
|
||||||
const importValue = importSpecifiersMap[exportName];
|
const importValue = importSpecifiersMap[exportName];
|
||||||
const connectValue = exportValue ? importSpecifiersMap[exportValue] : '';
|
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) {
|
if (exportName === EntryType.VALUE) {
|
||||||
value = filePath;
|
value = filePath;
|
||||||
@ -463,7 +493,7 @@ const getDependencies = (dependencies: Record<string, string>, packagePath: stri
|
|||||||
|
|
||||||
const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string, cwd: string, key?: string) => {
|
const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string, cwd: string, key?: string) => {
|
||||||
const { options } = app;
|
const { options } = app;
|
||||||
const { temp, componentFileAffix, datasoucreSuperClass } = options;
|
const { temp, componentFileAffix = '', datasoucreSuperClass } = options;
|
||||||
|
|
||||||
let { name: moduleName } = splitNameVersion(packagePath);
|
let { name: moduleName } = splitNameVersion(packagePath);
|
||||||
|
|
||||||
@ -489,6 +519,7 @@ const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string
|
|||||||
.replace('\n', '');
|
.replace('\n', '');
|
||||||
|
|
||||||
const indexCode = fs.readFileSync(indexPath, { encoding: 'utf-8', flag: 'r' });
|
const indexCode = fs.readFileSync(indexPath, { encoding: 'utf-8', flag: 'r' });
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
const ast: Ast = recast.parse(indexCode, { parser: require('recast/parsers/typescript') });
|
const ast: Ast = recast.parse(indexCode, { parser: require('recast/parsers/typescript') });
|
||||||
const result = typeAssertion({ ast, indexPath, componentFileAffix, datasoucreSuperClass });
|
const result = typeAssertion({ ast, indexPath, componentFileAffix, datasoucreSuperClass });
|
||||||
|
|
||||||
@ -513,15 +544,45 @@ const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string
|
|||||||
|
|
||||||
if (!key) return;
|
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 });
|
const entry = parseEntry({ ast, package: moduleName, indexPath });
|
||||||
|
|
||||||
if (entry.component) packages.componentMap[key] = getRelativePath(entry.component, temp);
|
if (entry.component) {
|
||||||
if (entry.config) packages.configMap[key] = getRelativePath(entry.config, temp);
|
const packagePath = getRelativePath(entry.component, temp);
|
||||||
if (entry.event) packages.eventMap[key] = getRelativePath(entry.event, temp);
|
packages.componentMap[key] = `${packagePath}${
|
||||||
if (entry.value) packages.valueMap[key] = getRelativePath(entry.value, temp);
|
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) {
|
} else if (result.type === PackageType.DATASOURCE) {
|
||||||
|
packages.datasourcePackage[key] = moduleName;
|
||||||
// 数据源
|
// 数据源
|
||||||
const entry = parseEntry({ ast, package: moduleName, indexPath });
|
const entry = parseEntry({ ast, package: moduleName, indexPath });
|
||||||
|
|
||||||
@ -530,6 +591,7 @@ const setPackages = (packages: ModuleMainFilePath, app: App, packagePath: string
|
|||||||
if (entry.event) packages.dsEventMap[key] = getRelativePath(entry.event, temp);
|
if (entry.event) packages.dsEventMap[key] = getRelativePath(entry.event, temp);
|
||||||
if (entry.value) packages.dsValueMap[key] = getRelativePath(entry.value, temp);
|
if (entry.value) packages.dsValueMap[key] = getRelativePath(entry.value, temp);
|
||||||
} else if (result.type === PackageType.PLUGIN) {
|
} else if (result.type === PackageType.PLUGIN) {
|
||||||
|
packages.pluginPakcage[key] = moduleName;
|
||||||
// 插件
|
// 插件
|
||||||
packages.pluginMap[key] = getRelativePath(moduleName, temp);
|
packages.pluginMap[key] = getRelativePath(moduleName, temp);
|
||||||
}
|
}
|
||||||
@ -573,11 +635,14 @@ export const resolveAppPackages = (app: App): ModuleMainFilePath => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const packagesMap: ModuleMainFilePath = {
|
const packagesMap: ModuleMainFilePath = {
|
||||||
|
componentPackage: {},
|
||||||
componentMap: {},
|
componentMap: {},
|
||||||
configMap: {},
|
configMap: {},
|
||||||
eventMap: {},
|
eventMap: {},
|
||||||
valueMap: {},
|
valueMap: {},
|
||||||
|
pluginPakcage: {},
|
||||||
pluginMap: {},
|
pluginMap: {},
|
||||||
|
datasourcePackage: {},
|
||||||
datasourceMap: {},
|
datasourceMap: {},
|
||||||
dsConfigMap: {},
|
dsConfigMap: {},
|
||||||
dsEventMap: {},
|
dsEventMap: {},
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"outDir": "./lib",
|
"outDir": "./lib",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
|
|
||||||
"types": ["node"],
|
"types": ["node"],
|
||||||
},
|
},
|
||||||
"include": ["./src"],
|
"include": ["./src"],
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.5.7",
|
"version": "1.5.15",
|
||||||
"name": "@tmagic/core",
|
"name": "@tmagic/core",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/tmagic-core.umd.cjs",
|
"main": "dist/tmagic-core.umd.cjs",
|
||||||
|
@ -33,6 +33,7 @@ import { transformStyle as defaultTransformStyle } from './utils';
|
|||||||
|
|
||||||
export interface AppOptionsConfig {
|
export interface AppOptionsConfig {
|
||||||
ua?: string;
|
ua?: string;
|
||||||
|
env?: Env;
|
||||||
config?: MApp;
|
config?: MApp;
|
||||||
platform?: 'editor' | 'mobile' | 'tv' | 'pc';
|
platform?: 'editor' | 'mobile' | 'tv' | 'pc';
|
||||||
jsEngine?: JsEngine;
|
jsEngine?: JsEngine;
|
||||||
@ -49,7 +50,13 @@ export interface AppOptionsConfig {
|
|||||||
|
|
||||||
class App extends EventEmitter {
|
class App extends EventEmitter {
|
||||||
[x: string]: any;
|
[x: string]: any;
|
||||||
public env: Env = new Env();
|
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;
|
||||||
public dsl?: MApp;
|
public dsl?: MApp;
|
||||||
public codeDsl?: CodeBlockDSL;
|
public codeDsl?: CodeBlockDSL;
|
||||||
public dataSourceManager?: DataSourceManager;
|
public dataSourceManager?: DataSourceManager;
|
||||||
@ -69,7 +76,12 @@ class App extends EventEmitter {
|
|||||||
constructor(options: AppOptionsConfig) {
|
constructor(options: AppOptionsConfig) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
if (options.env) {
|
||||||
|
this.setEnv(options.env);
|
||||||
|
} else {
|
||||||
this.setEnv(options.ua);
|
this.setEnv(options.ua);
|
||||||
|
}
|
||||||
|
|
||||||
// 代码块描述内容在dsl codeBlocks字段
|
// 代码块描述内容在dsl codeBlocks字段
|
||||||
this.codeDsl = options.config?.codeBlocks;
|
this.codeDsl = options.config?.codeBlocks;
|
||||||
options.platform && (this.platform = options.platform);
|
options.platform && (this.platform = options.platform);
|
||||||
@ -117,8 +129,12 @@ class App extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setEnv(ua?: string) {
|
public setEnv<T extends Env>(ua?: string | T) {
|
||||||
|
if (!ua || typeof ua === 'string') {
|
||||||
this.env = new Env(ua);
|
this.env = new Env(ua);
|
||||||
|
} else {
|
||||||
|
this.env = ua;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setDesignWidth(width: number) {
|
public setDesignWidth(width: number) {
|
||||||
@ -144,7 +160,12 @@ class App extends EventEmitter {
|
|||||||
this.dataSourceManager = createDataSourceManager(this, this.useMock);
|
this.dataSourceManager = createDataSourceManager(this, this.useMock);
|
||||||
|
|
||||||
this.codeDsl = config.codeBlocks;
|
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) {
|
if (this.dataSourceManager) {
|
||||||
const dataSourceList = Array.from(this.dataSourceManager.dataSourceMap.values());
|
const dataSourceList = Array.from(this.dataSourceManager.dataSourceMap.values());
|
||||||
@ -162,19 +183,22 @@ class App extends EventEmitter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageConfig === this.page?.data) return;
|
if (this.page) {
|
||||||
|
if (pageConfig === this.page.data) return;
|
||||||
this.page?.destroy();
|
this.page.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
this.page = new Page({
|
this.page = new Page({
|
||||||
config: pageConfig,
|
config: pageConfig,
|
||||||
app: this,
|
app: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.eventHelper?.removeNodeEvents();
|
if (this.eventHelper) {
|
||||||
this.page.nodes.forEach((node) => {
|
this.eventHelper.removeNodeEvents();
|
||||||
this.eventHelper?.bindNodeEvents(node);
|
for (const [, node] of this.page.nodes) {
|
||||||
});
|
this.eventHelper.bindNodeEvents(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
super.emit('page-change', this.page);
|
super.emit('page-change', this.page);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,11 @@ class Env {
|
|||||||
isWeb = false;
|
isWeb = false;
|
||||||
isOpenHarmony = 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.isIphone = ua.indexOf('iPhone') >= 0;
|
||||||
|
|
||||||
this.isIpad = /(iPad).*OS\s([\d_]+)/.test(ua);
|
this.isIpad = /(iPad).*OS\s([\d_]+)/.test(ua);
|
||||||
|
@ -32,38 +32,11 @@ import {
|
|||||||
type EventActionItem,
|
type EventActionItem,
|
||||||
type EventConfig,
|
type EventConfig,
|
||||||
} from '@tmagic/schema';
|
} 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 type { default as TMagicApp } from './App';
|
||||||
import FlowState from './FlowState';
|
import FlowState from './FlowState';
|
||||||
import type { default as TMagicNode } from './Node';
|
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 {
|
export default class EventHelper extends EventEmitter {
|
||||||
public app: TMagicApp;
|
public app: TMagicApp;
|
||||||
@ -75,19 +48,11 @@ export default class EventHelper extends EventEmitter {
|
|||||||
super();
|
super();
|
||||||
|
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
|
||||||
if (app.jsEngine === 'browser') {
|
|
||||||
globalThis.document.body.addEventListener('click', this.commonClickEventHandler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
this.removeNodeEvents();
|
this.removeNodeEvents();
|
||||||
this.removeAllListeners();
|
this.removeAllListeners();
|
||||||
|
|
||||||
if (this.app.jsEngine === 'browser') {
|
|
||||||
globalThis.document.body.removeEventListener('click', this.commonClickEventHandler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bindNodeEvents(node: TMagicNode) {
|
public bindNodeEvents(node: TMagicNode) {
|
||||||
@ -243,10 +208,6 @@ export default class EventHelper extends EventEmitter {
|
|||||||
const toNode = this.app.getNode(to);
|
const toNode = this.app.getNode(to);
|
||||||
if (!toNode) throw `ID为${to}的组件不存在`;
|
if (!toNode) throw `ID为${to}的组件不存在`;
|
||||||
|
|
||||||
if (isCommonMethod(methodName)) {
|
|
||||||
return triggerCommonMethod(methodName, toNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toNode.instance) {
|
if (toNode.instance) {
|
||||||
if (typeof toNode.instance[methodName] === 'function') {
|
if (typeof toNode.instance[methodName] === 'function') {
|
||||||
await toNode.instance[methodName](fromCpt, ...args);
|
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[];
|
args: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Methods {
|
||||||
|
[key: string]: (...args: any[]) => any;
|
||||||
|
}
|
||||||
|
|
||||||
export interface NodeOptions {
|
export interface NodeOptions {
|
||||||
config: MNode;
|
config: MNode;
|
||||||
page?: Page;
|
page?: Page;
|
||||||
@ -45,7 +49,7 @@ class Node extends EventEmitter {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
public events: EventConfig[] = [];
|
public events: EventConfig[] = [];
|
||||||
public instance?: any;
|
public instance?: any = {};
|
||||||
public page?: Page;
|
public page?: Page;
|
||||||
public parent?: Node;
|
public parent?: Node;
|
||||||
public app: TMagicApp;
|
public app: TMagicApp;
|
||||||
@ -69,6 +73,7 @@ class Node extends EventEmitter {
|
|||||||
const { events, style } = data;
|
const { events, style } = data;
|
||||||
this.events = events || [];
|
this.events = events || [];
|
||||||
this.style = style || {};
|
this.style = style || {};
|
||||||
|
this.instance.config = data;
|
||||||
this.emit('update-data', data);
|
this.emit('update-data', data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +81,22 @@ class Node extends EventEmitter {
|
|||||||
this.eventQueue.push(event);
|
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>) {
|
public async runHookCode(hook: string, params?: Record<string, any>) {
|
||||||
if (typeof this.data[hook] === 'function') {
|
if (typeof this.data[hook] === 'function') {
|
||||||
// 兼容旧的数据格式
|
// 兼容旧的数据格式
|
||||||
@ -102,8 +123,9 @@ class Node extends EventEmitter {
|
|||||||
const { codeType = HookCodeType.CODE, codeId, params: itemParams = {} } = item;
|
const { codeType = HookCodeType.CODE, codeId, params: itemParams = {} } = item;
|
||||||
|
|
||||||
let functionContent: ((...args: any[]) => any) | string | undefined;
|
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,
|
app: this.app,
|
||||||
|
node: this,
|
||||||
params: params || itemParams,
|
params: params || itemParams,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,7 +148,7 @@ class Node extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private listenLifeSafe() {
|
private listenLifeSafe() {
|
||||||
this.once('created', async (instance: any) => {
|
this.once('created', (instance: any) => {
|
||||||
this.once('destroy', () => {
|
this.once('destroy', () => {
|
||||||
this.instance = null;
|
this.instance = null;
|
||||||
if (typeof this.data.destroy === 'function') {
|
if (typeof this.data.destroy === 'function') {
|
||||||
@ -136,12 +158,24 @@ class Node extends EventEmitter {
|
|||||||
this.listenLifeSafe();
|
this.listenLifeSafe();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.instance = instance;
|
if (instance) {
|
||||||
await this.runHookCode('created');
|
this.registerMethod(instance);
|
||||||
|
if (instance.config) {
|
||||||
|
this.setData(instance.config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.runHookCode('created');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.once('mounted', async (instance: any) => {
|
this.once('mounted', (instance: any) => {
|
||||||
this.instance = instance;
|
const handler = async () => {
|
||||||
|
if (instance) {
|
||||||
|
this.registerMethod(instance);
|
||||||
|
if (instance.config) {
|
||||||
|
this.setData(instance.config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (let eventConfig = this.eventQueue.shift(); eventConfig; eventConfig = this.eventQueue.shift()) {
|
for (let eventConfig = this.eventQueue.shift(); eventConfig; eventConfig = this.eventQueue.shift()) {
|
||||||
if (typeof instance[eventConfig.method] === 'function') {
|
if (typeof instance[eventConfig.method] === 'function') {
|
||||||
@ -149,7 +183,9 @@ class Node extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.runHookCode('mounted');
|
this.runHookCode('mounted');
|
||||||
|
};
|
||||||
|
handler();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
import type { Id, MComponent, MContainer, MPage, MPageFragment } from '@tmagic/schema';
|
import type { Id, MComponent, MContainer, MPage, MPageFragment } from '@tmagic/schema';
|
||||||
|
|
||||||
import type App from './App';
|
import App from './App';
|
||||||
import IteratorContainer from './IteratorContainer';
|
import IteratorContainer from './IteratorContainer';
|
||||||
import type { default as TMagicNode } from './Node';
|
import type { default as TMagicNode } from './Node';
|
||||||
import Node from './Node';
|
import Node from './Node';
|
||||||
@ -53,7 +53,7 @@ class Page extends Node {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const node = new Node({
|
const node = new ((config.type && App.nodeClassMap.get(config.type)) || Node)({
|
||||||
config,
|
config,
|
||||||
parent,
|
parent,
|
||||||
page: this,
|
page: this,
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
import { JsEngine } from '@tmagic/schema';
|
import { JsEngine } from '@tmagic/schema';
|
||||||
import { isNumber } from '@tmagic/utils';
|
import { isNumber } from '@tmagic/utils';
|
||||||
|
|
||||||
import type { default as TMagicNode } from './Node';
|
|
||||||
|
|
||||||
export const style2Obj = (style: string) => {
|
export const style2Obj = (style: string) => {
|
||||||
if (typeof style !== 'string') {
|
if (typeof style !== 'string') {
|
||||||
return style;
|
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_EVENT_PREFIX = 'magic:common:events:';
|
||||||
export const COMMON_METHOD_PREFIX = 'magic:common:actions:';
|
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 {
|
export interface EventOption {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_EVENTS: EventOption[] = [{ label: '点击', value: `${COMMON_EVENT_PREFIX}click` }];
|
|
||||||
|
|
||||||
export const DEFAULT_METHODS: EventOption[] = [];
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.5.7",
|
"version": "1.5.15",
|
||||||
"name": "@tmagic/data-source",
|
"name": "@tmagic/data-source",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/tmagic-data-source.umd.cjs",
|
"main": "dist/tmagic-data-source.umd.cjs",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
/*
|
/*
|
||||||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||||||
*
|
*
|
||||||
@ -32,9 +33,16 @@ import { compiledNodeField, compliedConditions, compliedIteratorItem, createIter
|
|||||||
class DataSourceManager extends EventEmitter {
|
class DataSourceManager extends EventEmitter {
|
||||||
private static dataSourceClassMap = new Map<string, typeof DataSource>();
|
private static dataSourceClassMap = new Map<string, typeof DataSource>();
|
||||||
private static ObservedDataClass: ObservedDataClass = SimpleObservedData;
|
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) {
|
public static register<T extends typeof DataSource = typeof DataSource>(type: string, dataSource: T) {
|
||||||
DataSourceManager.dataSourceClassMap.set(type, dataSource);
|
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) {
|
public static getDataSourceClass(type: string) {
|
||||||
@ -55,6 +63,8 @@ class DataSourceManager extends EventEmitter {
|
|||||||
constructor({ app, useMock, initialData }: DataSourceManagerOptions) {
|
constructor({ app, useMock, initialData }: DataSourceManagerOptions) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
DataSourceManager.waitInitSchemaList.set(this, {});
|
||||||
|
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.useMock = useMock;
|
this.useMock = useMock;
|
||||||
|
|
||||||
@ -133,7 +143,24 @@ class DataSourceManager extends EventEmitter {
|
|||||||
public async addDataSource(config?: DataSourceSchema) {
|
public async addDataSource(config?: DataSourceSchema) {
|
||||||
if (!config) return;
|
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({
|
const ds = new DataSourceClass({
|
||||||
app: this.app,
|
app: this.app,
|
||||||
@ -276,6 +303,7 @@ class DataSourceManager extends EventEmitter {
|
|||||||
ds.destroy();
|
ds.destroy();
|
||||||
});
|
});
|
||||||
this.dataSourceMap.clear();
|
this.dataSourceMap.clear();
|
||||||
|
DataSourceManager.waitInitSchemaList.delete(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onDataChange(id: string, path: string, callback: (newVal: any) => void) {
|
public onDataChange(id: string, path: string, callback: (newVal: any) => void) {
|
||||||
@ -288,5 +316,6 @@ class DataSourceManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataSourceManager.register('http', HttpDataSource as any);
|
DataSourceManager.register('http', HttpDataSource as any);
|
||||||
|
DataSourceManager.register('base', DataSource as any);
|
||||||
|
|
||||||
export default DataSourceManager;
|
export default DataSourceManager;
|
||||||
|
@ -139,6 +139,7 @@ export const compliedDataSourceField = (value: any, data: DataSourceManagerData)
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
return getValueByKeyPath(fields.join('.'), dsData);
|
return getValueByKeyPath(fields.join('.'), dsData);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -151,6 +152,7 @@ export const template = (value: string, data?: DataSourceManagerData) =>
|
|||||||
value.replaceAll(dataSourceTemplateRegExp, (match, $1) => {
|
value.replaceAll(dataSourceTemplateRegExp, (match, $1) => {
|
||||||
try {
|
try {
|
||||||
return getValueByKeyPath($1, data);
|
return getValueByKeyPath($1, data);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.5.7",
|
"version": "1.5.15",
|
||||||
"name": "@tmagic/dep",
|
"name": "@tmagic/dep",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/tmagic-dep.umd.cjs",
|
"main": "dist/tmagic-dep.umd.cjs",
|
||||||
|
@ -222,7 +222,6 @@ export default class Watcher {
|
|||||||
for (const [key, value] of Object.entries(config)) {
|
for (const [key, value] of Object.entries(config)) {
|
||||||
if (typeof value === 'undefined' || value === '') continue;
|
if (typeof value === 'undefined' || value === '') continue;
|
||||||
|
|
||||||
if (key === 'id' || key === 'name') continue;
|
|
||||||
doCollect(key, value);
|
doCollect(key, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -263,20 +263,32 @@ export const createDataSourceCondTarget = (ds: Pick<DataSourceSchema, 'id' | 'fi
|
|||||||
isTarget: (key: string | number, value: any) => isDataSourceCondTarget(ds, key, value),
|
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' | 'fields'>,
|
||||||
|
initialDeps: DepData = {},
|
||||||
|
) =>
|
||||||
new Target({
|
new Target({
|
||||||
type: DepTargetType.DATA_SOURCE_METHOD,
|
type: DepTargetType.DATA_SOURCE_METHOD,
|
||||||
id: ds.id,
|
id: ds.id,
|
||||||
initialDeps,
|
initialDeps,
|
||||||
isTarget: (_key: string | number, value: any) => {
|
isTarget: (_key: string | number, value: any) => {
|
||||||
// 使用data-source-method-select 可以配置出来
|
// 使用data-source-method-select 可以配置出来
|
||||||
if (!Array.isArray(value) || !ds) {
|
if (!Array.isArray(value)) {
|
||||||
return false;
|
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) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ds.methods?.find((method) => method.name === methodName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置的方法名称可能会是数据源类中定义的,并不存在于methods中,所以这里判断如果methodName如果是字段名称,就表示配置的不是方法
|
||||||
|
if (ds.fields?.find((field) => field.name === methodName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ describe('utils', () => {
|
|||||||
test('isUseDataSourceField', () => {
|
test('isUseDataSourceField', () => {
|
||||||
expect(utils.isUseDataSourceField([`${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}dsID`, 'field'], 'dsID')).toBeTruthy();
|
expect(utils.isUseDataSourceField([`${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}dsID`, 'field'], 'dsID')).toBeTruthy();
|
||||||
expect(utils.isUseDataSourceField([`${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}dsID`, 'field'], 'dsID1')).toBeFalsy();
|
expect(utils.isUseDataSourceField([`${DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX}dsID`, 'field'], 'dsID1')).toBeFalsy();
|
||||||
expect(utils.isUseDataSourceField([`abcdsID`, 'field'], 'dsID')).toBeFalsy();
|
expect(utils.isUseDataSourceField(['abcdsID', 'field'], 'dsID')).toBeFalsy();
|
||||||
expect(utils.isUseDataSourceField([123, 'field'], 123)).toBeFalsy();
|
expect(utils.isUseDataSourceField([123, 'field'], 123)).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.5.7",
|
"version": "1.5.15",
|
||||||
"name": "@tmagic/design",
|
"name": "@tmagic/design",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
@ -42,7 +42,7 @@ const ui = getDesignConfig('components')?.autocomplete;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
const emit = defineEmits(['change', 'select', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -19,5 +19,5 @@ const props = defineProps<BadgeProps>();
|
|||||||
const ui = getDesignConfig('components')?.badge;
|
const ui = getDesignConfig('components')?.badge;
|
||||||
const uiComponent = ui?.component || 'el-badge';
|
const uiComponent = ui?.component || 'el-badge';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<BadgeProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -22,7 +22,7 @@ const ui = getDesignConfig('components')?.button;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
const emit = defineEmits(['click']);
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<component class="tmagic-design-card" :is="uiComponent" v-bind="uiProps">
|
<component class="tmagic-design-card" :is="uiComponent" v-bind="uiProps">
|
||||||
<template #header>
|
<template #header v-if="$slots.header">
|
||||||
<slot name="header" class="header"></slot>
|
<slot name="header" class="header"></slot>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #default>
|
<template #default v-if="$slots.default">
|
||||||
<slot name="default"></slot>
|
<slot name="default"></slot>
|
||||||
</template>
|
</template>
|
||||||
</component>
|
</component>
|
||||||
@ -26,5 +26,5 @@ const ui = getDesignConfig('components')?.card;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-card';
|
const uiComponent = ui?.component || 'el-card';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<CardProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -25,7 +25,7 @@ const ui = getDesignConfig('components')?.cascader;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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>();
|
const cascader = ref<any>();
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
@update:modelValue="updateModelValue"
|
@update:modelValue="updateModelValue"
|
||||||
@change="changeHandler"
|
@change="changeHandler"
|
||||||
>
|
>
|
||||||
<template #default>
|
<template #default v-if="$slots.default">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</template>
|
</template>
|
||||||
</component>
|
</component>
|
||||||
@ -31,7 +31,7 @@ const ui = getDesignConfig('components')?.checkbox;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ const ui = getDesignConfig('components')?.checkboxGroup;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-checkbox-group';
|
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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.col;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-col';
|
const uiComponent = ui?.component || 'el-col';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<ColProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -26,7 +26,7 @@ const ui = getDesignConfig('components')?.collapse;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ const ui = getDesignConfig('components')?.collapseItem;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-collapse-item';
|
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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ const ui = getDesignConfig('components')?.colorPicker;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-color-picker';
|
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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ const ui = getDesignConfig('components')?.datePicker;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-date-picker';
|
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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ const ui = getDesignConfig('components')?.dialog;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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[]) => {
|
const closeHandler = (...args: any[]) => {
|
||||||
emit('close', ...args);
|
emit('close', ...args);
|
||||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.divider;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-divider';
|
const uiComponent = ui?.component || 'el-divider';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<DividerProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -40,7 +40,7 @@ const ui = getDesignConfig('components')?.drawer;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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>();
|
const drawer = ref<any>();
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ const ui = getDesignConfig('components')?.dropdown;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
const emit = defineEmits(['command']);
|
||||||
|
|
||||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.dropdownItem;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-dropdown-item';
|
const uiComponent = ui?.component || 'el-dropdown-item';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<DropdownItemProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -26,7 +26,7 @@ const ui = getDesignConfig('components')?.form;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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>();
|
const form = ref<any>();
|
||||||
|
|
||||||
|
@ -23,5 +23,5 @@ const ui = getDesignConfig('components')?.formItem;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-form-item';
|
const uiComponent = ui?.component || 'el-form-item';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<FormItemProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -17,5 +17,5 @@ defineOptions({
|
|||||||
const ui = getDesignConfig('components')?.icon;
|
const ui = getDesignConfig('components')?.icon;
|
||||||
const uiComponent = ui?.component || 'el-icon';
|
const uiComponent = ui?.component || 'el-icon';
|
||||||
const props = defineProps<IconProps>();
|
const props = defineProps<IconProps>();
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<IconProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -39,7 +39,7 @@ const ui = getDesignConfig('components')?.input;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
const emit = defineEmits(['change', 'input', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ const ui = getDesignConfig('components')?.inputNumber;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-input-number';
|
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']);
|
const emit = defineEmits(['change', 'input', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.option;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-option';
|
const uiComponent = ui?.component || 'el-option';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<OptionProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,7 +20,7 @@ const ui = getDesignConfig('components')?.optionGroup;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-option-group';
|
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>();
|
const optionGroup = ref<any>();
|
||||||
</script>
|
</script>
|
||||||
|
@ -27,7 +27,7 @@ const ui = getDesignConfig('components')?.pagination;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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[]) => {
|
const handleSizeChange = (...args: any[]) => {
|
||||||
emit('size-change', ...args);
|
emit('size-change', ...args);
|
||||||
|
@ -27,9 +27,9 @@ import type { PopoverProps } from './types';
|
|||||||
|
|
||||||
defineSlots<{
|
defineSlots<{
|
||||||
/** 触发 Popover 显示的 HTML 元素 */
|
/** 触发 Popover 显示的 HTML 元素 */
|
||||||
reference(props: {}): any;
|
reference(_props: {}): any;
|
||||||
/** Popover 内嵌 HTML 文本 */
|
/** Popover 内嵌 HTML 文本 */
|
||||||
default(props: {}): any;
|
default(_props: {}): any;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -130,7 +130,7 @@ const mouseenterHandler = () => {
|
|||||||
popoverVisible.value = true;
|
popoverVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
let timer: NodeJS.Timeout | null = null;
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||||
const mouseleaveHandler = () => {
|
const mouseleaveHandler = () => {
|
||||||
if (props.disabled) return;
|
if (props.disabled) return;
|
||||||
|
|
||||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.radio;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-radio';
|
const uiComponent = ui?.component || 'el-radio';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<RadioProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.radioButton;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-radio-button';
|
const uiComponent = ui?.component || 'el-radio-button';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<RadioButtonProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -26,7 +26,7 @@ const ui = getDesignConfig('components')?.radioGroup;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-radio-group';
|
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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ const ui = getDesignConfig('components')?.select;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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>();
|
const select = ref<any>();
|
||||||
|
|
||||||
|
@ -26,5 +26,5 @@ const ui = getDesignConfig('components')?.step;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-step';
|
const uiComponent = ui?.component || 'el-step';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<StepProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -20,5 +20,5 @@ const ui = getDesignConfig('components')?.steps;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-steps';
|
const uiComponent = ui?.component || 'el-steps';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<StepsProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -28,7 +28,7 @@ const ui = getDesignConfig('components')?.switch;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -26,5 +26,5 @@ const ui = getDesignConfig('components')?.tabPane;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-tab-pane';
|
const uiComponent = ui?.component || 'el-tab-pane';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<TabPaneProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -33,7 +33,7 @@ const ui = getDesignConfig('components')?.table;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
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 uiComponent = ui?.component || 'el-table-column';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<TableColumnProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -30,7 +30,7 @@ const ui = getDesignConfig('components')?.tabs;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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']);
|
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 uiComponent = ui?.component || 'el-tag';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<TagProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -25,7 +25,7 @@ const ui = getDesignConfig('components')?.timePicker;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-time-picker';
|
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']);
|
const emit = defineEmits(['change', 'update:modelValue']);
|
||||||
|
|
||||||
|
@ -23,5 +23,5 @@ const ui = getDesignConfig('components')?.tooltip;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-tooltip';
|
const uiComponent = ui?.component || 'el-tooltip';
|
||||||
|
|
||||||
const uiProps = computed(() => ui?.props(props) || props);
|
const uiProps = computed<TooltipProps>(() => ui?.props(props) || props);
|
||||||
</script>
|
</script>
|
||||||
|
@ -35,7 +35,7 @@ const ui = getDesignConfig('components')?.tree;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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([
|
const emit = defineEmits([
|
||||||
'node-click',
|
'node-click',
|
||||||
|
@ -29,7 +29,7 @@ const ui = getDesignConfig('components')?.upload;
|
|||||||
|
|
||||||
const uiComponent = ui?.component || 'el-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>();
|
const upload = ref<any>();
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import './theme/index.scss';
|
|||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './config';
|
export * from './config';
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
||||||
export { default as TMagicAutocomplete } from './Autocomplete.vue';
|
export { default as TMagicAutocomplete } from './Autocomplete.vue';
|
||||||
export { default as TMagicBadge } from './Badge.vue';
|
export { default as TMagicBadge } from './Badge.vue';
|
||||||
export { default as TMagicButton } from './Button.vue';
|
export { default as TMagicButton } from './Button.vue';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.5.7",
|
"version": "1.5.15",
|
||||||
"name": "@tmagic/editor",
|
"name": "@tmagic/editor",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
@ -142,7 +142,7 @@ import codeBlockService from './services/codeBlock';
|
|||||||
import componentListService from './services/componentList';
|
import componentListService from './services/componentList';
|
||||||
import dataSourceService from './services/dataSource';
|
import dataSourceService from './services/dataSource';
|
||||||
import depService from './services/dep';
|
import depService from './services/dep';
|
||||||
import editorService, { type EditorService } from './services/editor';
|
import editorService from './services/editor';
|
||||||
import eventsService from './services/events';
|
import eventsService from './services/events';
|
||||||
import historyService from './services/history';
|
import historyService from './services/history';
|
||||||
import keybindingService from './services/keybinding';
|
import keybindingService from './services/keybinding';
|
||||||
@ -153,25 +153,9 @@ import uiService from './services/ui';
|
|||||||
import keybindingConfig from './utils/keybinding-config';
|
import keybindingConfig from './utils/keybinding-config';
|
||||||
import { defaultEditorProps, EditorProps } from './editorProps';
|
import { defaultEditorProps, EditorProps } from './editorProps';
|
||||||
import { initServiceEvents, initServiceState } from './initService';
|
import { initServiceEvents, initServiceState } from './initService';
|
||||||
import type {
|
import type { EditorSlots, EventBus, Services, StageOptions } from './type';
|
||||||
EventBus,
|
|
||||||
FrameworkSlots,
|
|
||||||
PropsPanelSlots,
|
|
||||||
Services,
|
|
||||||
SidebarSlots,
|
|
||||||
StageOptions,
|
|
||||||
WorkspaceSlots,
|
|
||||||
} from './type';
|
|
||||||
|
|
||||||
defineSlots<
|
defineSlots<EditorSlots>();
|
||||||
FrameworkSlots &
|
|
||||||
WorkspaceSlots &
|
|
||||||
SidebarSlots &
|
|
||||||
PropsPanelSlots & {
|
|
||||||
workspace(props: { editorService: EditorService }): any;
|
|
||||||
'workspace-content'(props: { editorService: EditorService }): any;
|
|
||||||
}
|
|
||||||
>();
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MEditor',
|
name: 'MEditor',
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, inject, Ref, ref, useTemplateRef } from 'vue';
|
import { computed, inject, nextTick, Ref, ref, useTemplateRef, watch } from 'vue';
|
||||||
|
|
||||||
import type { CodeBlockContent } from '@tmagic/core';
|
import type { CodeBlockContent } from '@tmagic/core';
|
||||||
import { TMagicButton, TMagicDialog, tMagicMessage, tMagicMessageBox, TMagicTag } from '@tmagic/design';
|
import { TMagicButton, TMagicDialog, tMagicMessage, tMagicMessageBox, TMagicTag } from '@tmagic/design';
|
||||||
@ -74,9 +74,9 @@ import {
|
|||||||
import FloatingBox from '@editor/components/FloatingBox.vue';
|
import FloatingBox from '@editor/components/FloatingBox.vue';
|
||||||
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
|
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
|
||||||
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
|
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 { useWindowRect } from '@editor/hooks/use-window-rect';
|
||||||
import CodeEditor from '@editor/layouts/CodeEditor.vue';
|
import CodeEditor from '@editor/layouts/CodeEditor.vue';
|
||||||
import type { Services } from '@editor/type';
|
|
||||||
import { getEditorConfig } from '@editor/utils/config';
|
import { getEditorConfig } from '@editor/utils/config';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -95,9 +95,11 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
submit: [values: CodeBlockContent, eventData: ContainerChangeEventData];
|
submit: [values: CodeBlockContent, eventData: ContainerChangeEventData];
|
||||||
|
close: [];
|
||||||
|
open: [];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const services = inject<Services>('services');
|
const { codeBlockService, uiService } = useServices();
|
||||||
|
|
||||||
const { height: codeBlockEditorHeight } = useEditorContentHeight();
|
const { height: codeBlockEditorHeight } = useEditorContentHeight();
|
||||||
|
|
||||||
@ -192,7 +194,7 @@ const functionConfig = computed<FormConfig>(() => [
|
|||||||
label: '描述',
|
label: '描述',
|
||||||
name: 'extra',
|
name: 'extra',
|
||||||
},
|
},
|
||||||
services?.codeBlockService.getParamsColConfig() || defaultParamColConfig,
|
codeBlockService.getParamsColConfig() || defaultParamColConfig,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -231,7 +233,7 @@ const changeHandler = (values: CodeBlockContent) => {
|
|||||||
changedValue.value = values;
|
changedValue.value = values;
|
||||||
};
|
};
|
||||||
|
|
||||||
const beforeClose = (done: (cancel?: boolean) => void) => {
|
const beforeClose = (done: (_cancel?: boolean) => void) => {
|
||||||
if (!changedValue.value) {
|
if (!changedValue.value) {
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
@ -259,7 +261,17 @@ const closedHandler = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
||||||
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
|
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
|
||||||
|
|
||||||
|
watch(boxVisible, (visible) => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (!visible) {
|
||||||
|
emit('close');
|
||||||
|
} else {
|
||||||
|
emit('open');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
async show() {
|
async show() {
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<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';
|
import { useZIndex } from '@tmagic/design';
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ const menuEl = useTemplateRef<HTMLDivElement>('menu');
|
|||||||
const buttonRefs = useTemplateRef<InstanceType<typeof ToolButton>[]>('buttons');
|
const buttonRefs = useTemplateRef<InstanceType<typeof ToolButton>[]>('buttons');
|
||||||
const subMenuRef = useTemplateRef<any>('subMenu');
|
const subMenuRef = useTemplateRef<any>('subMenu');
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const subMenuData = ref<(MenuButton | MenuComponent)[]>([]);
|
const subMenuData: Ref<(MenuButton | MenuComponent)[]> = ref<(MenuButton | MenuComponent)[]>([]);
|
||||||
const zIndex = useZIndex();
|
const zIndex = useZIndex();
|
||||||
const curZIndex = ref<number>(0);
|
const curZIndex = ref<number>(0);
|
||||||
|
|
||||||
|
@ -17,14 +17,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<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 { Close } from '@element-plus/icons-vue';
|
||||||
import VanillaMoveable from 'moveable';
|
import VanillaMoveable from 'moveable';
|
||||||
|
|
||||||
import { TMagicButton, useZIndex } from '@tmagic/design';
|
import { TMagicButton, useZIndex } from '@tmagic/design';
|
||||||
|
|
||||||
import MIcon from '@editor/components/Icon.vue';
|
import MIcon from '@editor/components/Icon.vue';
|
||||||
import type { Services } from '@editor/type';
|
import { useServices } from '@editor/hooks/use-services';
|
||||||
|
|
||||||
interface Position {
|
interface Position {
|
||||||
left: number;
|
left: number;
|
||||||
@ -39,7 +39,7 @@ const props = withDefaults(
|
|||||||
defineProps<{
|
defineProps<{
|
||||||
position?: Position;
|
position?: Position;
|
||||||
title?: string;
|
title?: string;
|
||||||
beforeClose?: (done: (cancel?: boolean) => void) => void;
|
beforeClose?: (_done: (_cancel?: boolean) => void) => void;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
title: '',
|
title: '',
|
||||||
@ -66,8 +66,8 @@ const bodyHeight = computed(() => {
|
|||||||
return 'auto';
|
return 'auto';
|
||||||
});
|
});
|
||||||
|
|
||||||
const services = inject<Services>('services');
|
const { uiService } = useServices();
|
||||||
const frameworkWidth = computed(() => services?.uiService.get('frameworkRect').width || 0);
|
const frameworkWidth = computed(() => uiService.get('frameworkRect').width || 0);
|
||||||
const style = computed(() => {
|
const style = computed(() => {
|
||||||
let { left } = props.position;
|
let { left } = props.position;
|
||||||
if (width.value) {
|
if (width.value) {
|
||||||
|
@ -93,7 +93,9 @@ const scrollBy = (delta: number) => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
transition: background-color 0.2s linear, opacity 0.2s linear;
|
transition:
|
||||||
|
background-color 0.2s linear,
|
||||||
|
opacity 0.2s linear;
|
||||||
|
|
||||||
.m-editor-scroll-bar-thumb {
|
.m-editor-scroll-bar-thumb {
|
||||||
background-color: #aaa;
|
background-color: #aaa;
|
||||||
@ -108,7 +110,9 @@ const scrollBy = (delta: number) => {
|
|||||||
|
|
||||||
.m-editor-scroll-bar-thumb {
|
.m-editor-scroll-bar-thumb {
|
||||||
height: 6px;
|
height: 6px;
|
||||||
transition: background-color 0.2s linear, height 0.2s ease-in-out;
|
transition:
|
||||||
|
background-color 0.2s linear,
|
||||||
|
height 0.2s ease-in-out;
|
||||||
bottom: 2px;
|
bottom: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +124,9 @@ const scrollBy = (delta: number) => {
|
|||||||
|
|
||||||
.m-editor-scroll-bar-thumb {
|
.m-editor-scroll-bar-thumb {
|
||||||
width: 6px;
|
width: 6px;
|
||||||
transition: background-color 0.2s linear, width 0.2s ease-in-out;
|
transition:
|
||||||
|
background-color 0.2s linear,
|
||||||
|
width 0.2s ease-in-out;
|
||||||
right: 2px;
|
right: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ const emit = defineEmits(['search']);
|
|||||||
|
|
||||||
const filterText = ref('');
|
const filterText = ref('');
|
||||||
|
|
||||||
let timer: NodeJS.Timeout | null = null;
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||||
const filterTextChangeHandler = () => {
|
const filterTextChangeHandler = () => {
|
||||||
timer && clearTimeout(timer);
|
timer && clearTimeout(timer);
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, inject } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { ArrowDown } from '@element-plus/icons-vue';
|
import { ArrowDown } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -62,8 +62,10 @@ import {
|
|||||||
TMagicTooltip,
|
TMagicTooltip,
|
||||||
} from '@tmagic/design';
|
} from '@tmagic/design';
|
||||||
|
|
||||||
|
import { useServices } from '@editor/hooks/use-services';
|
||||||
|
|
||||||
import MIcon from '../components/Icon.vue';
|
import MIcon from '../components/Icon.vue';
|
||||||
import type { MenuButton, MenuComponent, Services } from '../type';
|
import type { MenuButton, MenuComponent } from '../type';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MEditorToolButton',
|
name: 'MEditorToolButton',
|
||||||
@ -82,7 +84,7 @@ const props = withDefaults(
|
|||||||
eventType: 'click',
|
eventType: 'click',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const services = inject<Services>('services');
|
const services = useServices();
|
||||||
|
|
||||||
const disabled = computed(() => {
|
const disabled = computed(() => {
|
||||||
if (typeof props.data === 'string') return false;
|
if (typeof props.data === 'string') return false;
|
||||||
@ -104,7 +106,7 @@ const display = computed(() => {
|
|||||||
|
|
||||||
const buttonHandler = (item: MenuButton | MenuComponent, event: MouseEvent) => {
|
const buttonHandler = (item: MenuButton | MenuComponent, event: MouseEvent) => {
|
||||||
if (disabled.value) return;
|
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);
|
(item as MenuButton).handler?.(services, event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -38,9 +38,9 @@ import type { LayerNodeStatus, TreeNodeData } from '@editor/type';
|
|||||||
import TreeNode from './TreeNode.vue';
|
import TreeNode from './TreeNode.vue';
|
||||||
|
|
||||||
defineSlots<{
|
defineSlots<{
|
||||||
'tree-node-content'(props: { data: TreeNodeData }): any;
|
'tree-node-content'(_props: { data: TreeNodeData }): any;
|
||||||
'tree-node-label'(props: { data: TreeNodeData }): any;
|
'tree-node-label'(_props: { data: TreeNodeData }): any;
|
||||||
'tree-node-tool'(props: { data: TreeNodeData }): any;
|
'tree-node-tool'(_props: { data: TreeNodeData }): any;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
class="tree-node"
|
class="tree-node"
|
||||||
:class="{ selected, expanded }"
|
:class="{ selected, expanded }"
|
||||||
:style="`padding-left: ${indent}px`"
|
:style="`padding-left: ${indent}px`"
|
||||||
@contextmenu="nodeContentmenuHandler"
|
@contextmenu="nodeContextmenuHandler"
|
||||||
@mouseenter="mouseenterHandler"
|
@mouseenter="mouseenterHandler"
|
||||||
>
|
>
|
||||||
<MIcon
|
<MIcon
|
||||||
@ -72,9 +72,9 @@ import type { LayerNodeStatus, TreeNodeData } from '@editor/type';
|
|||||||
import { updateStatus } from '@editor/utils/tree';
|
import { updateStatus } from '@editor/utils/tree';
|
||||||
|
|
||||||
defineSlots<{
|
defineSlots<{
|
||||||
'tree-node-label'(props: { data: TreeNodeData }): any;
|
'tree-node-label'(_props: { data: TreeNodeData }): any;
|
||||||
'tree-node-tool'(props: { data: TreeNodeData }): any;
|
'tree-node-tool'(_props: { data: TreeNodeData }): any;
|
||||||
'tree-node-content'(props: { data: TreeNodeData }): any;
|
'tree-node-content'(_props: { data: TreeNodeData }): any;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -139,7 +139,7 @@ const handleDragEnd = (event: DragEvent) => {
|
|||||||
treeEmit?.('node-dragend', event, props.data);
|
treeEmit?.('node-dragend', event, props.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const nodeContentmenuHandler = (event: MouseEvent) => {
|
const nodeContextmenuHandler = (event: MouseEvent) => {
|
||||||
treeEmit?.('node-contextmenu', event, props.data);
|
treeEmit?.('node-contextmenu', event, props.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, inject, watch } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
import { isEmpty } from 'lodash-es';
|
import { isEmpty } from 'lodash-es';
|
||||||
|
|
||||||
import { HookCodeType, HookType } from '@tmagic/core';
|
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 type { ContainerChangeEventData, FieldProps, FormItem, GroupListConfig } from '@tmagic/form';
|
||||||
import { MContainer } from '@tmagic/form';
|
import { MContainer } from '@tmagic/form';
|
||||||
|
|
||||||
import type { Services } from '@editor/type';
|
import { useServices } from '@editor/hooks/use-services';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MFieldsCodeSelect',
|
name: 'MFieldsCodeSelect',
|
||||||
@ -34,7 +34,7 @@ const emit = defineEmits<{
|
|||||||
change: [v: any, eventData: ContainerChangeEventData];
|
change: [v: any, eventData: ContainerChangeEventData];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const services = inject<Services>('services');
|
const { dataSourceService, codeBlockService } = useServices();
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<
|
defineProps<
|
||||||
@ -59,7 +59,7 @@ const codeConfig = computed<GroupListConfig>(() => ({
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ds = services?.dataSourceService.getDataSourceById(model.codeId[0]);
|
const ds = dataSourceService.getDataSourceById(model.codeId[0]);
|
||||||
return `${ds?.title} / ${model.codeId[1]}`;
|
return `${ds?.title} / ${model.codeId[1]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,13 +80,11 @@ const codeConfig = computed<GroupListConfig>(() => ({
|
|||||||
{ value: HookCodeType.DATA_SOURCE_METHOD, text: '数据源方法' },
|
{ value: HookCodeType.DATA_SOURCE_METHOD, text: '数据源方法' },
|
||||||
],
|
],
|
||||||
defaultValue: 'code',
|
defaultValue: 'code',
|
||||||
onChange: (mForm, v: HookCodeType, { model, prop, changeRecords }) => {
|
onChange: (_mForm, v: HookCodeType, { setModel }) => {
|
||||||
if (v === HookCodeType.DATA_SOURCE_METHOD) {
|
if (v === HookCodeType.DATA_SOURCE_METHOD) {
|
||||||
model.codeId = [];
|
setModel('codeId', []);
|
||||||
changeRecords.push({ propPath: prop.replace('codeType', 'codeId'), value: [] });
|
|
||||||
} else {
|
} else {
|
||||||
model.codeId = '';
|
setModel('codeId', '');
|
||||||
changeRecords.push({ propPath: prop.replace('codeType', 'codeId'), value: '' });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
@ -97,16 +95,16 @@ const codeConfig = computed<GroupListConfig>(() => ({
|
|||||||
name: 'codeId',
|
name: 'codeId',
|
||||||
span: 18,
|
span: 18,
|
||||||
labelWidth: 0,
|
labelWidth: 0,
|
||||||
display: (mForm, { model }) => model.codeType !== HookCodeType.DATA_SOURCE_METHOD,
|
display: (_mForm, { model }) => model.codeType !== HookCodeType.DATA_SOURCE_METHOD,
|
||||||
notEditable: () => !services?.codeBlockService.getEditStatus(),
|
notEditable: () => !codeBlockService.getEditStatus(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'data-source-method-select',
|
type: 'data-source-method-select',
|
||||||
name: 'codeId',
|
name: 'codeId',
|
||||||
span: 18,
|
span: 18,
|
||||||
labelWidth: 0,
|
labelWidth: 0,
|
||||||
display: (mForm, { model }) => model.codeType === HookCodeType.DATA_SOURCE_METHOD,
|
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 CodeParams from '@editor/components/CodeParams.vue';
|
||||||
import MIcon from '@editor/components/Icon.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';
|
import { SideItemKey } from '@editor/type';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -60,7 +61,7 @@ defineOptions({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
const services = inject<Services>('services');
|
const { codeBlockService, uiService } = useServices();
|
||||||
const eventBus = inject<EventBus>('eventBus');
|
const eventBus = inject<EventBus>('eventBus');
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
change: [v: any, eventData: ContainerChangeEventData];
|
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 notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
|
||||||
|
|
||||||
const hasCodeBlockSidePanel = computed(() =>
|
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]));
|
const paramsConfig = ref<CodeParamStatement[]>(getParamItemsConfig(props.model[props.name]));
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@ -120,24 +121,28 @@ const selectConfig = {
|
|||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
onChange: (formState: any, codeId: Id, { model }: any) => {
|
onChange: (formState: any, codeId: Id, { setModel, model }: any) => {
|
||||||
// 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params
|
// 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params
|
||||||
paramsConfig.value = getParamItemsConfig(codeId);
|
paramsConfig.value = getParamItemsConfig(codeId);
|
||||||
|
|
||||||
if (paramsConfig.value.length) {
|
if (paramsConfig.value.length) {
|
||||||
model.params = createValues(formState, paramsConfig.value, {}, model.params);
|
setModel('params', createValues(formState, paramsConfig.value, {}, model.params));
|
||||||
} else {
|
} else {
|
||||||
model.params = {};
|
setModel('params', {});
|
||||||
}
|
}
|
||||||
|
|
||||||
return codeId;
|
return codeId;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCodeIdChangeHandler = (value: any) => {
|
const onCodeIdChangeHandler = (value: any, eventData: ContainerChangeEventData) => {
|
||||||
props.model.params = value.params;
|
props.model.params = value.params;
|
||||||
|
|
||||||
emit('change', props.model, {
|
emit('change', props.model, {
|
||||||
changeRecords: [
|
changeRecords: eventData.changeRecords?.map((item) => ({
|
||||||
|
prop: `${props.prop.replace(props.name, '')}${item.propPath}`,
|
||||||
|
value: item.value,
|
||||||
|
})) || [
|
||||||
{
|
{
|
||||||
propPath: props.prop,
|
propPath: props.prop,
|
||||||
value: value[props.name],
|
value: value[props.name],
|
||||||
|
@ -27,12 +27,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
|
||||||
import { getDesignConfig, TMagicSelect } from '@tmagic/design';
|
import { getDesignConfig, TMagicSelect } from '@tmagic/design';
|
||||||
import type { FieldProps } from '@tmagic/form';
|
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';
|
import { arrayOptions, eqOptions, numberOptions } from '@editor/utils';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -43,7 +44,7 @@ const emit = defineEmits<{
|
|||||||
change: [value: string];
|
change: [value: string];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { dataSourceService } = inject<Services>('services') || {};
|
const { dataSourceService } = useServices();
|
||||||
|
|
||||||
const props = defineProps<FieldProps<CondOpSelectConfig>>();
|
const props = defineProps<FieldProps<CondOpSelectConfig>>();
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ const optionComponent = getDesignConfig('components')?.option;
|
|||||||
const options = computed(() => {
|
const options = computed(() => {
|
||||||
const [id, ...fieldNames] = [...(props.config.parentFields || []), ...props.model.field];
|
const [id, ...fieldNames] = [...(props.config.parentFields || []), ...props.model.field];
|
||||||
|
|
||||||
const ds = dataSourceService?.getDataSourceById(id);
|
const ds = dataSourceService.getDataSourceById(id);
|
||||||
|
|
||||||
let fields = ds?.fields || [];
|
let fields = ds?.fields || [];
|
||||||
let type = '';
|
let type = '';
|
||||||
|
@ -69,13 +69,14 @@
|
|||||||
import { computed, inject, ref, watch } from 'vue';
|
import { computed, inject, ref, watch } from 'vue';
|
||||||
import { Edit, View } from '@element-plus/icons-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 { getDesignConfig, TMagicButton, TMagicCascader, TMagicSelect, TMagicTooltip } from '@tmagic/design';
|
||||||
import { type FilterFunction, filterFunction, type FormState, type SelectOption } from '@tmagic/form';
|
import { type FilterFunction, filterFunction, type FormState, type SelectOption } from '@tmagic/form';
|
||||||
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
import { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
||||||
|
|
||||||
import MIcon from '@editor/components/Icon.vue';
|
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';
|
import { getCascaderOptionsFromFields, removeDataSourceFieldPrefix } from '@editor/utils';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@ -101,11 +102,11 @@ const modelValue = defineModel<string[] | any>('modelValue', { default: [] });
|
|||||||
|
|
||||||
const optionComponent = getDesignConfig('components')?.option;
|
const optionComponent = getDesignConfig('components')?.option;
|
||||||
|
|
||||||
const services = inject<Services>('services');
|
const { dataSourceService, uiService } = useServices();
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
const eventBus = inject<EventBus>('eventBus');
|
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 valueIsKey = computed(() => props.value === 'key');
|
||||||
const notEditable = computed(() => filterFunction(mForm, props.notEditable, props));
|
const notEditable = computed(() => filterFunction(mForm, props.notEditable, props));
|
||||||
@ -172,7 +173,7 @@ const onChangeHandler = (v: string[] = []) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const hasDataSourceSidePanel = computed(() =>
|
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) => {
|
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 { DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX } from '@tmagic/utils';
|
||||||
|
|
||||||
import MIcon from '@editor/components/Icon.vue';
|
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 { removeDataSourceFieldPrefix } from '@editor/utils';
|
||||||
|
|
||||||
import FieldSelect from './FieldSelect.vue';
|
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 mForm = inject<FormState | undefined>('mForm');
|
||||||
|
|
||||||
const dataSources = computed(() => services?.dataSourceService.get('dataSources') || []);
|
const dataSources = computed(() => dataSourceService.get('dataSources') || []);
|
||||||
|
|
||||||
const type = computed((): string => {
|
const type = computed((): string => {
|
||||||
let type = props.config.fieldConfig?.type;
|
let type = props.config.fieldConfig?.type;
|
||||||
|
@ -64,7 +64,8 @@ import { getDefaultValueFromFields } from '@tmagic/utils';
|
|||||||
import FloatingBox from '@editor/components/FloatingBox.vue';
|
import FloatingBox from '@editor/components/FloatingBox.vue';
|
||||||
import { useEditorContentHeight } from '@editor/hooks';
|
import { useEditorContentHeight } from '@editor/hooks';
|
||||||
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
|
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
|
||||||
import type { Services } from '@editor/type';
|
import { useServices } from '@editor/hooks/use-services';
|
||||||
|
import { error } from '@editor/utils/logger';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'MFieldsDataSourceFields',
|
name: 'MFieldsDataSourceFields',
|
||||||
@ -85,7 +86,7 @@ const emit = defineEmits<{
|
|||||||
change: [v: any, eventData?: ContainerChangeEventData];
|
change: [v: any, eventData?: ContainerChangeEventData];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const services = inject<Services>('services');
|
const { uiService } = useServices();
|
||||||
|
|
||||||
const fieldValues = ref<Record<string, any>>({});
|
const fieldValues = ref<Record<string, any>>({});
|
||||||
const fieldTitle = ref('');
|
const fieldTitle = ref('');
|
||||||
@ -144,6 +145,7 @@ const fieldColumns: ColumnConfig[] = [
|
|||||||
try {
|
try {
|
||||||
return JSON.stringify(row.defaultValue);
|
return JSON.stringify(row.defaultValue);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
error(e);
|
||||||
return row.defaultValue;
|
return row.defaultValue;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -193,9 +195,9 @@ const dataSourceFieldsConfig: FormConfig = [
|
|||||||
{ text: 'null', value: 'null' },
|
{ text: 'null', value: 'null' },
|
||||||
{ text: 'any', value: 'any' },
|
{ text: 'any', value: 'any' },
|
||||||
],
|
],
|
||||||
onChange: (formState, v: string, { model }) => {
|
onChange: (_formState, v: string, { setModel }) => {
|
||||||
if (!['any', 'array', 'object'].includes(v)) {
|
if (!['any', 'array', 'object'].includes(v)) {
|
||||||
model.fields = [];
|
setModel('fields', []);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
},
|
},
|
||||||
@ -344,5 +346,5 @@ const addFromJsonDialogVisible = defineModel<boolean>('visible1', { default: fal
|
|||||||
const { height: editorHeight } = useEditorContentHeight();
|
const { height: editorHeight } = useEditorContentHeight();
|
||||||
|
|
||||||
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
||||||
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
|
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
|
||||||
</script>
|
</script>
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<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 { Coin } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
import type { DataSchema, DataSourceSchema } from '@tmagic/core';
|
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 { getKeysArray, isNumber } from '@tmagic/utils';
|
||||||
|
|
||||||
import Icon from '@editor/components/Icon.vue';
|
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';
|
import { getDisplayField } from '@editor/utils/data-source';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -81,7 +81,7 @@ const emit = defineEmits<{
|
|||||||
change: [value: string];
|
change: [value: string];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { dataSourceService } = inject<Services>('services') || {};
|
const { dataSourceService } = useServices();
|
||||||
|
|
||||||
const autocompleteRef = useTemplateRef<InstanceType<typeof TMagicAutocomplete>>('autocomplete');
|
const autocompleteRef = useTemplateRef<InstanceType<typeof TMagicAutocomplete>>('autocomplete');
|
||||||
const isFocused = ref(false);
|
const isFocused = ref(false);
|
||||||
@ -89,7 +89,7 @@ const state = ref('');
|
|||||||
const displayState = ref<{ value: string; type: 'var' | 'text' }[]>([]);
|
const displayState = ref<{ value: string; type: 'var' | 'text' }[]>([]);
|
||||||
|
|
||||||
const input = computed<HTMLInputElement>(() => autocompleteRef.value?.inputRef?.input);
|
const input = computed<HTMLInputElement>(() => autocompleteRef.value?.inputRef?.input);
|
||||||
const dataSources = computed(() => dataSourceService?.get('dataSources') || []);
|
const dataSources = computed(() => dataSourceService.get('dataSources'));
|
||||||
|
|
||||||
const setDisplayState = () => {
|
const setDisplayState = () => {
|
||||||
displayState.value = getDisplayField(dataSources.value, state.value);
|
displayState.value = getDisplayField(dataSources.value, state.value);
|
||||||
@ -179,7 +179,11 @@ const curCharIsDot = (dotIndex: number) => dotIndex > -1 && dotIndex === getSele
|
|||||||
* @param leftCurlyBracketIndex 左大括号字符索引
|
* @param leftCurlyBracketIndex 左大括号字符索引
|
||||||
* @param cb 建议的方法
|
* @param cb 建议的方法
|
||||||
*/
|
*/
|
||||||
const dsQuerySearch = (queryString: string, leftCurlyBracketIndex: number, cb: (data: { value: string }[]) => void) => {
|
const dsQuerySearch = (
|
||||||
|
queryString: string,
|
||||||
|
leftCurlyBracketIndex: number,
|
||||||
|
cb: (_data: { value: string }[]) => void,
|
||||||
|
) => {
|
||||||
let result: DataSourceSchema[] = [];
|
let result: DataSourceSchema[] = [];
|
||||||
|
|
||||||
if (curCharIsLeftCurlyBracket(leftCurlyBracketIndex)) {
|
if (curCharIsLeftCurlyBracket(leftCurlyBracketIndex)) {
|
||||||
@ -211,7 +215,7 @@ const fieldQuerySearch = (
|
|||||||
queryString: string,
|
queryString: string,
|
||||||
leftAngleIndex: number,
|
leftAngleIndex: number,
|
||||||
dotIndex: number,
|
dotIndex: number,
|
||||||
cb: (data: { value: string }[]) => void,
|
cb: (_data: { value: string }[]) => void,
|
||||||
) => {
|
) => {
|
||||||
let result: DataSchema[] = [];
|
let result: DataSchema[] = [];
|
||||||
|
|
||||||
@ -272,7 +276,7 @@ const fieldQuerySearch = (
|
|||||||
* @param queryString 当前输入框内的字符串
|
* @param queryString 当前输入框内的字符串
|
||||||
* @param cb 建议回调
|
* @param cb 建议回调
|
||||||
*/
|
*/
|
||||||
const querySearch = (queryString: string, cb: (data: { value: string }[]) => void) => {
|
const querySearch = (queryString: string, cb: (_data: { value: string }[]) => void) => {
|
||||||
inputText = queryString;
|
inputText = queryString;
|
||||||
|
|
||||||
const selectionStart = getSelectionStart();
|
const selectionStart = getSelectionStart();
|
||||||
|
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