mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-04-24 02:38:26 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5af91f86c | ||
|
|
540d9cd5bb | ||
|
|
407572ee3a | ||
|
|
d7ad63d3a2 | ||
|
|
4cd54d1397 | ||
|
|
7249b5106e | ||
|
|
9ba12e97af | ||
|
|
e106c081c8 | ||
|
|
9f21f8f1d5 | ||
|
|
b46b571214 | ||
|
|
6a4a4ed122 | ||
|
|
63698af00a | ||
|
|
ac755ac3d0 | ||
|
|
9bf42f9007 | ||
|
|
3875ccde33 |
19
CHANGELOG.md
19
CHANGELOG.md
@ -1,3 +1,22 @@
|
|||||||
|
## [1.7.11](https://github.com/Tencent/tmagic-editor/compare/v1.7.10...v1.7.11) (2026-04-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **form:** group-list lastValues 为空时兼容取值报错 ([7249b51](https://github.com/Tencent/tmagic-editor/commit/7249b5106eee06a4e22cc325e83fac4e09e146ba))
|
||||||
|
* **form:** table 全屏每次进入重新获取 z-index ([9ba12e9](https://github.com/Tencent/tmagic-editor/commit/9ba12e97afccbca6bafcacc1b5e79f4d7fed3341)), closes [#672](https://github.com/Tencent/tmagic-editor/issues/672)
|
||||||
|
* **vue-runtime-help:** 删除所有页面后,新增页面出错 ([6a4a4ed](https://github.com/Tencent/tmagic-editor/commit/6a4a4ed122ce19ece81d816cb9b7dfb473dc351a)), closes [#668](https://github.com/Tencent/tmagic-editor/issues/668)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **editor:** 样式面板布局分组新增透明度配置 ([e106c08](https://github.com/Tencent/tmagic-editor/commit/e106c081c8fd6e0e8db9160605190e21ffccc1f7)), closes [#675](https://github.com/Tencent/tmagic-editor/issues/675)
|
||||||
|
* **editor:** 没有参考线时不显示参考线切换按钮 ([b46b571](https://github.com/Tencent/tmagic-editor/commit/b46b5712142c85fc18533f68d52ae0958c2835e0))
|
||||||
|
* **form:** group-list 支持 max 限制和 beforeAddRow 前置校验 ([ac755ac](https://github.com/Tencent/tmagic-editor/commit/ac755ac3d0328a2ca8e77d6f8b117b8b349e1bd0))
|
||||||
|
* **table:** 支持列排序配置 ([4cd54d1](https://github.com/Tencent/tmagic-editor/commit/4cd54d13979da5189ecbd19ec732a4653a4f7d0a))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [1.7.10](https://github.com/Tencent/tmagic-editor/compare/v1.7.9...v1.7.10) (2026-04-13)
|
## [1.7.10](https://github.com/Tencent/tmagic-editor/compare/v1.7.9...v1.7.10) (2026-04-13)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -16,9 +16,9 @@ https://tencent.github.io/tmagic-editor/playground/index.html
|
|||||||
|
|
||||||
## 环境准备
|
## 环境准备
|
||||||
|
|
||||||
node.js >= 18
|
node.js ^20.19.0 || >=22.12.0
|
||||||
|
|
||||||
pnpm >= 9
|
pnpm >= 10
|
||||||
|
|
||||||
先安装 pnpm
|
先安装 pnpm
|
||||||
|
|
||||||
|
|||||||
18
package.json
18
package.json
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "tmagic",
|
"name": "tmagic",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -44,8 +44,8 @@
|
|||||||
"@commitlint/config-conventional": "^20.0.0",
|
"@commitlint/config-conventional": "^20.0.0",
|
||||||
"@tmagic/eslint-config": "workspace:*",
|
"@tmagic/eslint-config": "workspace:*",
|
||||||
"@types/node": "24.0.10",
|
"@types/node": "24.0.10",
|
||||||
"@vitejs/plugin-vue": "^6.0.5",
|
"@vitejs/plugin-vue": "^6.0.6",
|
||||||
"@vitest/coverage-v8": "^4.1.0",
|
"@vitest/coverage-v8": "^4.1.5",
|
||||||
"@vue/compiler-sfc": "catalog:",
|
"@vue/compiler-sfc": "catalog:",
|
||||||
"c8": "^10.1.3",
|
"c8": "^10.1.3",
|
||||||
"commitizen": "^4.3.1",
|
"commitizen": "^4.3.1",
|
||||||
@ -54,7 +54,7 @@
|
|||||||
"cz-conventional-changelog": "^3.3.0",
|
"cz-conventional-changelog": "^3.3.0",
|
||||||
"element-plus": "^2.11.8",
|
"element-plus": "^2.11.8",
|
||||||
"enquirer": "^2.4.1",
|
"enquirer": "^2.4.1",
|
||||||
"eslint": "^10.0.3",
|
"eslint": "^10.2.1",
|
||||||
"execa": "^9.6.0",
|
"execa": "^9.6.0",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
@ -62,12 +62,12 @@
|
|||||||
"lint-staged": "^16.2.7",
|
"lint-staged": "^16.2.7",
|
||||||
"minimist": "^1.2.8",
|
"minimist": "^1.2.8",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.3",
|
||||||
"recast": "^0.23.11",
|
"recast": "^0.23.11",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rolldown": "^1.0.0-rc.9",
|
"rolldown": "^1.0.0-rc.17",
|
||||||
"rolldown-plugin-dts": "^0.22.5",
|
"rolldown-plugin-dts": "^0.23.2",
|
||||||
"sass-embedded": "^1.93.3",
|
"sass-embedded": "^1.99.0",
|
||||||
"semver": "^7.7.3",
|
"semver": "^7.7.3",
|
||||||
"serialize-javascript": "^7.0.0",
|
"serialize-javascript": "^7.0.0",
|
||||||
"shx": "^0.3.4",
|
"shx": "^0.3.4",
|
||||||
@ -76,7 +76,7 @@
|
|||||||
"vitepress": "^1.6.4",
|
"vitepress": "^1.6.4",
|
||||||
"vitest": "^4.1.0",
|
"vitest": "^4.1.0",
|
||||||
"vue": "catalog:",
|
"vue": "catalog:",
|
||||||
"vue-tsc": "^3.2.6"
|
"vue-tsc": "^3.2.7"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"commitizen": {
|
"commitizen": {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/cli",
|
"name": "@tmagic/cli",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"types": "lib/index.d.ts",
|
"types": "lib/index.d.ts",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/core",
|
"name": "@tmagic/core",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/data-source",
|
"name": "@tmagic/data-source",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/dep",
|
"name": "@tmagic/dep",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/design",
|
"name": "@tmagic/design",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
|||||||
@ -342,7 +342,7 @@ export interface TableColumnOptions<T = any> {
|
|||||||
prop?: string;
|
prop?: string;
|
||||||
align?: string;
|
align?: string;
|
||||||
headerAlign?: string;
|
headerAlign?: string;
|
||||||
sortable?: boolean;
|
sortable?: boolean | string;
|
||||||
sortOrders?: Array<'ascending' | 'descending'>;
|
sortOrders?: Array<'ascending' | 'descending'>;
|
||||||
selectable?: (row: T, index: number) => boolean;
|
selectable?: (row: T, index: number) => boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/editor",
|
"name": "@tmagic/editor",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
|||||||
@ -67,6 +67,7 @@ const config = computed<GroupListConfig>(() => ({
|
|||||||
name: props.name,
|
name: props.name,
|
||||||
titlePrefix: props.config.titlePrefix,
|
titlePrefix: props.config.titlePrefix,
|
||||||
expandAll: true,
|
expandAll: true,
|
||||||
|
enableToggleMode: false,
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
type: 'table',
|
type: 'table',
|
||||||
|
|||||||
@ -59,10 +59,12 @@ export const useStage = (stageOptions: StageOptions) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
stage.mask?.setGuides([
|
const hGuidesCache = getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY));
|
||||||
getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY)),
|
const vGuidesCache = getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY));
|
||||||
getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY)),
|
|
||||||
]);
|
stage.mask?.setGuides([hGuidesCache, vGuidesCache]);
|
||||||
|
|
||||||
|
uiService.set('hasGuides', hGuidesCache.length > 0 || vGuidesCache.length > 0);
|
||||||
|
|
||||||
stage.on('page-el-update', () => {
|
stage.on('page-el-update', () => {
|
||||||
editorService.set('stageLoading', false);
|
editorService.set('stageLoading', false);
|
||||||
@ -124,6 +126,11 @@ export const useStage = (stageOptions: StageOptions) => {
|
|||||||
stage.on('change-guides', (e) => {
|
stage.on('change-guides', (e) => {
|
||||||
uiService.set('showGuides', true);
|
uiService.set('showGuides', true);
|
||||||
|
|
||||||
|
uiService.set(
|
||||||
|
'hasGuides',
|
||||||
|
(stage.mask?.horizontalGuidelines.length ?? 0) > 0 || (stage.mask?.verticalGuidelines.length ?? 0) > 0,
|
||||||
|
);
|
||||||
|
|
||||||
if (!root.value || !page.value) return;
|
if (!root.value || !page.value) return;
|
||||||
|
|
||||||
const storageKey = getGuideLineKey(
|
const storageKey = getGuideLineKey(
|
||||||
|
|||||||
@ -37,6 +37,7 @@ const columnWidth = computed(() => uiService.get('columnWidth'));
|
|||||||
const keys = Object.values(ColumnLayout);
|
const keys = Object.values(ColumnLayout);
|
||||||
|
|
||||||
const showGuides = computed((): boolean => uiService.get('showGuides'));
|
const showGuides = computed((): boolean => uiService.get('showGuides'));
|
||||||
|
const hasGuides = computed((): boolean => uiService.get('hasGuides'));
|
||||||
const showRule = computed((): boolean => uiService.get('showRule'));
|
const showRule = computed((): boolean => uiService.get('showRule'));
|
||||||
const zoom = computed((): number => uiService.get('zoom'));
|
const zoom = computed((): number => uiService.get('zoom'));
|
||||||
|
|
||||||
@ -143,6 +144,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'guides':
|
case 'guides':
|
||||||
|
if (!hasGuides.value) break;
|
||||||
config.push({
|
config.push({
|
||||||
type: 'button',
|
type: 'button',
|
||||||
className: 'guides',
|
className: 'guides',
|
||||||
|
|||||||
@ -55,6 +55,7 @@ const state = shallowReactive<UiState>({
|
|||||||
DEFAULT_RIGHT_COLUMN_WIDTH,
|
DEFAULT_RIGHT_COLUMN_WIDTH,
|
||||||
},
|
},
|
||||||
showGuides: true,
|
showGuides: true,
|
||||||
|
hasGuides: false,
|
||||||
showRule: true,
|
showRule: true,
|
||||||
propsPanelSize: 'small',
|
propsPanelSize: 'small',
|
||||||
showAddPageButton: true,
|
showAddPageButton: true,
|
||||||
|
|||||||
@ -253,6 +253,8 @@ export interface UiState {
|
|||||||
columnWidth: GetColumnWidth;
|
columnWidth: GetColumnWidth;
|
||||||
/** 是否显示画布参考线,true: 显示,false: 不显示,默认为true */
|
/** 是否显示画布参考线,true: 显示,false: 不显示,默认为true */
|
||||||
showGuides: boolean;
|
showGuides: boolean;
|
||||||
|
/** 画布上是否存在参考线 */
|
||||||
|
hasGuides: boolean;
|
||||||
/** 是否显示标尺,true: 显示,false: 不显示,默认为true */
|
/** 是否显示标尺,true: 显示,false: 不显示,默认为true */
|
||||||
showRule: boolean;
|
showRule: boolean;
|
||||||
/** 用于控制该属性配置表单内组件的尺寸 */
|
/** 用于控制该属性配置表单内组件的尺寸 */
|
||||||
|
|||||||
@ -106,6 +106,7 @@ export const styleTabConfig: TabPaneConfig = {
|
|||||||
'borderWidth',
|
'borderWidth',
|
||||||
'borderStyle',
|
'borderStyle',
|
||||||
'borderColor',
|
'borderColor',
|
||||||
|
'opacity',
|
||||||
],
|
],
|
||||||
} as unknown as ChildConfig,
|
} as unknown as ChildConfig,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/element-plus-adapter",
|
"name": "@tmagic/element-plus-adapter",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/form-schema",
|
"name": "@tmagic/form-schema",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -761,7 +761,7 @@ export interface TableConfig extends FormItem {
|
|||||||
titleTip?: FilterFunction<string>;
|
titleTip?: FilterFunction<string>;
|
||||||
rowKey?: string;
|
rowKey?: string;
|
||||||
/** table 新增行时前置回调 */
|
/** table 新增行时前置回调 */
|
||||||
beforeAddRow?: (mForm: FormState | undefined, data: any) => boolean;
|
beforeAddRow?: (mForm: FormState | undefined, data: any) => boolean | Promise<boolean>;
|
||||||
addButtonConfig?: {
|
addButtonConfig?: {
|
||||||
props?: Record<string, any>;
|
props?: Record<string, any>;
|
||||||
text?: string;
|
text?: string;
|
||||||
@ -804,6 +804,9 @@ export interface GroupListConfig<T = never> extends FormItem {
|
|||||||
props?: Record<string, any>;
|
props?: Record<string, any>;
|
||||||
text?: string;
|
text?: string;
|
||||||
};
|
};
|
||||||
|
/** 最大行数 */
|
||||||
|
max?: number;
|
||||||
|
beforeAddRow?: (mForm: FormState | undefined, data: any) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StepItemConfig<T = never> extends FormItem, ContainerCommonConfig<T> {
|
interface StepItemConfig<T = never> extends FormItem, ContainerCommonConfig<T> {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/form",
|
"name": "@tmagic/form",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
v-for="(item, index) in model[name]"
|
v-for="(item, index) in model[name]"
|
||||||
:key="index"
|
:key="index"
|
||||||
:model="item"
|
:model="item"
|
||||||
:lastValues="getLastValues(lastValues[name], Number(index))"
|
:lastValues="getLastValues(lastValues?.[name], Number(index))"
|
||||||
:is-compare="isCompare"
|
:is-compare="isCompare"
|
||||||
:config="config"
|
:config="config"
|
||||||
:prop="prop"
|
:prop="prop"
|
||||||
@ -27,30 +27,19 @@
|
|||||||
></MFieldsGroupListItem>
|
></MFieldsGroupListItem>
|
||||||
|
|
||||||
<div class="m-fields-group-list-footer">
|
<div class="m-fields-group-list-footer">
|
||||||
<TMagicButton v-if="config.enableToggleMode" :icon="Grid" size="small" @click="toggleMode"
|
<slot name="toggle-button"></slot>
|
||||||
>切换为表格</TMagicButton
|
|
||||||
>
|
|
||||||
<div style="display: flex; justify-content: flex-end; flex: 1">
|
<div style="display: flex; justify-content: flex-end; flex: 1">
|
||||||
<TMagicButton
|
<slot name="add-button" :trigger="addHandler"></slot>
|
||||||
v-if="addable"
|
|
||||||
:size="config.enableToggleMode ? 'small' : 'default'"
|
|
||||||
:icon="Plus"
|
|
||||||
v-bind="config.addButtonConfig?.props || { type: 'primary' }"
|
|
||||||
:disabled="disabled"
|
|
||||||
@click="addHandler"
|
|
||||||
>{{ config.addButtonConfig?.text || '新增' }}</TMagicButton
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, inject } from 'vue';
|
import { inject } from 'vue';
|
||||||
import { Grid, Plus } from '@element-plus/icons-vue';
|
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
import { TMagicButton } from '@tmagic/design';
|
import { tMagicMessage } from '@tmagic/design';
|
||||||
|
|
||||||
import type { ContainerChangeEventData, FormState, GroupListConfig } from '../schema';
|
import type { ContainerChangeEventData, FormState, GroupListConfig } from '../schema';
|
||||||
import { initValue } from '../utils/form';
|
import { initValue } from '../utils/form';
|
||||||
@ -71,6 +60,7 @@ const props = defineProps<{
|
|||||||
prop?: string;
|
prop?: string;
|
||||||
size?: string;
|
size?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
showIndex?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@ -80,21 +70,6 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
|
|
||||||
const addable = computed(() => {
|
|
||||||
if (!props.name) return false;
|
|
||||||
|
|
||||||
if (typeof props.config.addable === 'function') {
|
|
||||||
return props.config.addable(mForm, {
|
|
||||||
model: props.model[props.name],
|
|
||||||
formValue: mForm?.values,
|
|
||||||
prop: props.prop,
|
|
||||||
config: props.config,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
|
||||||
});
|
|
||||||
|
|
||||||
const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
||||||
emit('change', props.model, eventData);
|
emit('change', props.model, eventData);
|
||||||
};
|
};
|
||||||
@ -102,6 +77,20 @@ const changeHandler = (v: any, eventData: ContainerChangeEventData) => {
|
|||||||
const addHandler = async () => {
|
const addHandler = async () => {
|
||||||
if (!props.name) return false;
|
if (!props.name) return false;
|
||||||
|
|
||||||
|
if (props.config.max && props.model[props.name].length >= props.config.max) {
|
||||||
|
tMagicMessage.error(`最多新增配置不能超过${props.config.max}条`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof props.config.beforeAddRow === 'function') {
|
||||||
|
const beforeCheckRes = await props.config.beforeAddRow(mForm, {
|
||||||
|
model: props.model[props.name],
|
||||||
|
formValue: mForm?.values,
|
||||||
|
prop: props.prop,
|
||||||
|
});
|
||||||
|
if (!beforeCheckRes) return;
|
||||||
|
}
|
||||||
|
|
||||||
let initValues = {};
|
let initValues = {};
|
||||||
|
|
||||||
if (typeof props.config.defaultAdd === 'function') {
|
if (typeof props.config.defaultAdd === 'function') {
|
||||||
@ -153,17 +142,6 @@ const swapHandler = (idx1: number, idx2: number) => {
|
|||||||
emit('change', props.model[props.name]);
|
emit('change', props.model[props.name]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleMode = () => {
|
|
||||||
props.config.type = 'table';
|
|
||||||
props.config.groupItems = props.config.items;
|
|
||||||
props.config.items = (props.config.tableItems ||
|
|
||||||
props.config.items.map((item: any) => ({
|
|
||||||
...item,
|
|
||||||
label: item.label || item.text,
|
|
||||||
text: null,
|
|
||||||
}))) as any;
|
|
||||||
};
|
|
||||||
|
|
||||||
const onAddDiffCount = () => emit('addDiffCount');
|
const onAddDiffCount = () => emit('addDiffCount');
|
||||||
|
|
||||||
const getLastValues = (item: any, index: number) => item?.[index] || {};
|
const getLastValues = (item: any, index: number) => item?.[index] || {};
|
||||||
|
|||||||
181
packages/form/src/containers/TableGroupList.vue
Normal file
181
packages/form/src/containers/TableGroupList.vue
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
<template>
|
||||||
|
<component
|
||||||
|
:is="displayMode === 'table' ? MFormTable : MFormGroupList"
|
||||||
|
v-bind="$attrs"
|
||||||
|
:model="model"
|
||||||
|
:name="`${name}`"
|
||||||
|
:config="currentConfig"
|
||||||
|
:disabled="disabled"
|
||||||
|
:size="size"
|
||||||
|
:is-compare="isCompare"
|
||||||
|
:last-values="lastValues"
|
||||||
|
:prop="prop"
|
||||||
|
:label-width="labelWidth"
|
||||||
|
:show-index="showIndex"
|
||||||
|
:sort-key="sortKey"
|
||||||
|
:sort="sort"
|
||||||
|
@change="onChange"
|
||||||
|
@select="onSelect"
|
||||||
|
@addDiffCount="onAddDiffCount"
|
||||||
|
>
|
||||||
|
<template #toggle-button>
|
||||||
|
<TMagicButton
|
||||||
|
v-if="config.enableToggleMode || enableToggleMode"
|
||||||
|
:icon="Grid"
|
||||||
|
size="small"
|
||||||
|
@click="toggleDisplayMode"
|
||||||
|
>
|
||||||
|
{{ displayMode === 'table' ? '展开配置' : '切换为表格' }}
|
||||||
|
</TMagicButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #add-button="{ trigger }">
|
||||||
|
<TMagicButton
|
||||||
|
v-if="addable"
|
||||||
|
:class="displayMode === 'table' ? 'm-form-table-add-button' : ''"
|
||||||
|
:size="addButtonSize"
|
||||||
|
:plain="displayMode === 'table'"
|
||||||
|
:icon="Plus"
|
||||||
|
:disabled="disabled"
|
||||||
|
v-bind="currentConfig.addButtonConfig?.props || { type: 'primary' }"
|
||||||
|
@click="trigger"
|
||||||
|
>
|
||||||
|
{{ currentConfig.addButtonConfig?.text || (displayMode === 'table' ? '新增一行' : '新增') }}
|
||||||
|
</TMagicButton>
|
||||||
|
</template>
|
||||||
|
</component>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, inject, ref } from 'vue';
|
||||||
|
import { Grid, Plus } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
import { TMagicButton } from '@tmagic/design';
|
||||||
|
import type { FormState, GroupListConfig, TableConfig } from '@tmagic/form-schema';
|
||||||
|
|
||||||
|
import type { ContainerChangeEventData } from '../schema';
|
||||||
|
import MFormTable from '../table/Table.vue';
|
||||||
|
|
||||||
|
import MFormGroupList from './GroupList.vue';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'MFormTableGroupList',
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
model: any;
|
||||||
|
lastValues?: any;
|
||||||
|
isCompare?: boolean;
|
||||||
|
config: TableConfig | GroupListConfig;
|
||||||
|
name: string;
|
||||||
|
prop?: string;
|
||||||
|
labelWidth?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
size?: string;
|
||||||
|
enableToggleMode?: true;
|
||||||
|
showIndex?: boolean;
|
||||||
|
sortKey?: string;
|
||||||
|
sort?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits(['change', 'select', 'addDiffCount']);
|
||||||
|
|
||||||
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
|
|
||||||
|
const addable = computed(() => {
|
||||||
|
const modelName = props.name || props.config.name || '';
|
||||||
|
|
||||||
|
if (!modelName) return false;
|
||||||
|
|
||||||
|
if (!props.model[modelName].length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof props.config.addable === 'function') {
|
||||||
|
return props.config.addable(mForm, {
|
||||||
|
model: props.model[modelName],
|
||||||
|
formValue: mForm?.values,
|
||||||
|
prop: props.prop,
|
||||||
|
config: props.config,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isGroupListType = (type: string | undefined) => type === 'groupList' || type === 'group-list';
|
||||||
|
|
||||||
|
const displayMode = ref<'table' | 'groupList'>(isGroupListType(props.config.type) ? 'groupList' : 'table');
|
||||||
|
|
||||||
|
const calcLabelWidth = (label: string) => {
|
||||||
|
if (!label) return '0px';
|
||||||
|
const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
|
||||||
|
const chLength = label.length - zhLength;
|
||||||
|
return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 当原始 config 是 table 形态时,table 模式直接透传;
|
||||||
|
// 若原始是 groupList,则基于它派生出 table 所需的 config
|
||||||
|
const tableConfig = computed<TableConfig>(() => {
|
||||||
|
if (!isGroupListType(props.config.type)) {
|
||||||
|
return props.config as TableConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = props.config as GroupListConfig;
|
||||||
|
return {
|
||||||
|
...props.config,
|
||||||
|
type: 'table',
|
||||||
|
groupItems: source.items,
|
||||||
|
items:
|
||||||
|
source.tableItems ||
|
||||||
|
(source.items as any[]).map((item: any) => ({
|
||||||
|
...item,
|
||||||
|
label: item.label || item.text,
|
||||||
|
text: null,
|
||||||
|
})),
|
||||||
|
} as any as TableConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 反向派生 groupList 所需的 config
|
||||||
|
const groupListConfig = computed<GroupListConfig>(() => {
|
||||||
|
if (isGroupListType(props.config.type)) {
|
||||||
|
return props.config as GroupListConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = props.config as TableConfig;
|
||||||
|
return {
|
||||||
|
...props.config,
|
||||||
|
type: 'groupList',
|
||||||
|
tableItems: source.items,
|
||||||
|
items:
|
||||||
|
source.groupItems ||
|
||||||
|
(source.items as any[]).map((item: any) => {
|
||||||
|
const text = item.text || item.label;
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
text,
|
||||||
|
labelWidth: calcLabelWidth(text),
|
||||||
|
span: item.span || 12,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
} as any as GroupListConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 运行时类型由 displayMode 决定,`<component :is>` 无法做联合类型收窄,统一转 any 交给子组件处理
|
||||||
|
const currentConfig = computed<any>(() => (displayMode.value === 'table' ? tableConfig.value : groupListConfig.value));
|
||||||
|
|
||||||
|
// 保持原 Table/GroupList 模式下新增按钮的不同尺寸策略
|
||||||
|
const addButtonSize = computed(() => {
|
||||||
|
if (displayMode.value === 'table') return 'small';
|
||||||
|
return props.config.enableToggleMode !== false ? 'small' : 'default';
|
||||||
|
});
|
||||||
|
|
||||||
|
const toggleDisplayMode = () => {
|
||||||
|
displayMode.value = displayMode.value === 'table' ? 'groupList' : 'table';
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (v: any, eventData?: ContainerChangeEventData) => emit('change', v, eventData);
|
||||||
|
const onSelect = (...args: any[]) => emit('select', ...args);
|
||||||
|
const onAddDiffCount = () => emit('addDiffCount');
|
||||||
|
</script>
|
||||||
@ -32,8 +32,9 @@ export { default as MFlexLayout } from './containers/FlexLayout.vue';
|
|||||||
export { default as MPanel } from './containers/Panel.vue';
|
export { default as MPanel } from './containers/Panel.vue';
|
||||||
export { default as MRow } from './containers/Row.vue';
|
export { default as MRow } from './containers/Row.vue';
|
||||||
export { default as MTabs } from './containers/Tabs.vue';
|
export { default as MTabs } from './containers/Tabs.vue';
|
||||||
export { default as MTable } from './table/Table.vue';
|
export { default as MTable } from './containers/TableGroupList.vue';
|
||||||
export { default as MGroupList } from './containers/GroupList.vue';
|
export { default as MGroupList } from './containers/TableGroupList.vue';
|
||||||
|
export { default as MTableGroupList } from './containers/TableGroupList.vue';
|
||||||
export { default as MText } from './fields/Text.vue';
|
export { default as MText } from './fields/Text.vue';
|
||||||
export { default as MNumber } from './fields/Number.vue';
|
export { default as MNumber } from './fields/Number.vue';
|
||||||
export { default as MNumberRange } from './fields/NumberRange.vue';
|
export { default as MNumberRange } from './fields/NumberRange.vue';
|
||||||
|
|||||||
@ -21,10 +21,10 @@ import { type App } from 'vue';
|
|||||||
import Container from './containers/Container.vue';
|
import Container from './containers/Container.vue';
|
||||||
import Fieldset from './containers/Fieldset.vue';
|
import Fieldset from './containers/Fieldset.vue';
|
||||||
import FlexLayout from './containers/FlexLayout.vue';
|
import FlexLayout from './containers/FlexLayout.vue';
|
||||||
import GroupList from './containers/GroupList.vue';
|
|
||||||
import Panel from './containers/Panel.vue';
|
import Panel from './containers/Panel.vue';
|
||||||
import Row from './containers/Row.vue';
|
import Row from './containers/Row.vue';
|
||||||
import MStep from './containers/Step.vue';
|
import MStep from './containers/Step.vue';
|
||||||
|
import TableGroupList from './containers/TableGroupList.vue';
|
||||||
import Tabs from './containers/Tabs.vue';
|
import Tabs from './containers/Tabs.vue';
|
||||||
import Cascader from './fields/Cascader.vue';
|
import Cascader from './fields/Cascader.vue';
|
||||||
import Checkbox from './fields/Checkbox.vue';
|
import Checkbox from './fields/Checkbox.vue';
|
||||||
@ -46,7 +46,6 @@ import Text from './fields/Text.vue';
|
|||||||
import Textarea from './fields/Textarea.vue';
|
import Textarea from './fields/Textarea.vue';
|
||||||
import Time from './fields/Time.vue';
|
import Time from './fields/Time.vue';
|
||||||
import Timerange from './fields/Timerange.vue';
|
import Timerange from './fields/Timerange.vue';
|
||||||
import Table from './table/Table.vue';
|
|
||||||
import { setConfig } from './utils/config';
|
import { setConfig } from './utils/config';
|
||||||
import Form from './Form.vue';
|
import Form from './Form.vue';
|
||||||
import FormDialog from './FormDialog.vue';
|
import FormDialog from './FormDialog.vue';
|
||||||
@ -70,11 +69,11 @@ export default {
|
|||||||
app.component('m-form-dialog', FormDialog);
|
app.component('m-form-dialog', FormDialog);
|
||||||
app.component('m-form-container', Container);
|
app.component('m-form-container', Container);
|
||||||
app.component('m-form-fieldset', Fieldset);
|
app.component('m-form-fieldset', Fieldset);
|
||||||
app.component('m-form-group-list', GroupList);
|
app.component('m-form-group-list', TableGroupList);
|
||||||
app.component('m-form-panel', Panel);
|
app.component('m-form-panel', Panel);
|
||||||
app.component('m-form-row', Row);
|
app.component('m-form-row', Row);
|
||||||
app.component('m-form-step', MStep);
|
app.component('m-form-step', MStep);
|
||||||
app.component('m-form-table', Table);
|
app.component('m-form-table', TableGroupList);
|
||||||
app.component('m-form-tab', Tabs);
|
app.component('m-form-tab', Tabs);
|
||||||
app.component('m-form-flex-layout', FlexLayout);
|
app.component('m-form-flex-layout', FlexLayout);
|
||||||
app.component('m-fields-text', Text);
|
app.component('m-fields-text', Text);
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
class="m-fields-table-wrap"
|
class="m-fields-table-wrap"
|
||||||
:class="{ fixed: isFullscreen }"
|
:class="{ fixed: isFullscreen }"
|
||||||
:style="isFullscreen ? `z-index: ${nextZIndex()}` : ''"
|
:style="isFullscreen ? `z-index: ${fullscreenZIndex}` : ''"
|
||||||
>
|
>
|
||||||
<div class="m-fields-table" :class="{ 'm-fields-table-item-extra': config.itemExtra }">
|
<div class="m-fields-table" :class="{ 'm-fields-table-item-extra': config.itemExtra }">
|
||||||
<span v-if="config.extra" style="color: rgba(0, 0, 0, 0.45)" v-html="config.extra"></span>
|
<span v-if="config.extra" style="color: rgba(0, 0, 0, 0.45)" v-html="config.extra"></span>
|
||||||
@ -34,13 +34,7 @@
|
|||||||
|
|
||||||
<div style="display: flex; justify-content: space-between; margin: 10px 0">
|
<div style="display: flex; justify-content: space-between; margin: 10px 0">
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
<TMagicButton
|
<slot name="toggle-button" v-if="!isFullscreen"></slot>
|
||||||
:icon="Grid"
|
|
||||||
size="small"
|
|
||||||
@click="toggleMode"
|
|
||||||
v-if="enableToggleMode && config.enableToggleMode !== false && !isFullscreen"
|
|
||||||
>展开配置</TMagicButton
|
|
||||||
>
|
|
||||||
<TMagicButton
|
<TMagicButton
|
||||||
:icon="FullScreen"
|
:icon="FullScreen"
|
||||||
size="small"
|
size="small"
|
||||||
@ -64,17 +58,7 @@
|
|||||||
>清空</TMagicButton
|
>清空</TMagicButton
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<TMagicButton
|
<slot name="add-button" :trigger="newHandler"></slot>
|
||||||
v-if="addable"
|
|
||||||
class="m-form-table-add-button"
|
|
||||||
size="small"
|
|
||||||
plain
|
|
||||||
:icon="Plus"
|
|
||||||
v-bind="config.addButtonConfig?.props || { type: 'primary' }"
|
|
||||||
:disabled="disabled"
|
|
||||||
@click="newHandler()"
|
|
||||||
>{{ config.addButtonConfig?.text || '新增一行' }}</TMagicButton
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bottom" style="text-align: right" v-if="config.pagination">
|
<div class="bottom" style="text-align: right" v-if="config.pagination">
|
||||||
@ -96,8 +80,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, useTemplateRef } from 'vue';
|
import { computed, ref, useTemplateRef, watch } from 'vue';
|
||||||
import { FullScreen, Grid, Plus } from '@element-plus/icons-vue';
|
import { FullScreen } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
import { TMagicButton, TMagicPagination, TMagicTable, TMagicTooltip, TMagicUpload, useZIndex } from '@tmagic/design';
|
import { TMagicButton, TMagicPagination, TMagicTable, TMagicTooltip, TMagicUpload, useZIndex } from '@tmagic/design';
|
||||||
|
|
||||||
@ -120,7 +104,6 @@ defineOptions({
|
|||||||
const props = withDefaults(defineProps<TableProps>(), {
|
const props = withDefaults(defineProps<TableProps>(), {
|
||||||
prop: '',
|
prop: '',
|
||||||
sortKey: '',
|
sortKey: '',
|
||||||
enableToggleMode: true,
|
|
||||||
showIndex: true,
|
showIndex: true,
|
||||||
lastValues: () => ({}),
|
lastValues: () => ({}),
|
||||||
isCompare: false,
|
isCompare: false,
|
||||||
@ -138,42 +121,24 @@ const { pageSize, currentPage, paginationData, handleSizeChange, handleCurrentCh
|
|||||||
|
|
||||||
const { nextZIndex } = useZIndex();
|
const { nextZIndex } = useZIndex();
|
||||||
const updateKey = ref(1);
|
const updateKey = ref(1);
|
||||||
|
const fullscreenZIndex = ref(nextZIndex());
|
||||||
|
|
||||||
const { addable, newHandler } = useAdd(props, emit);
|
const { newHandler } = useAdd(props, emit);
|
||||||
const { columns } = useTableColumns(props, emit, currentPage, pageSize, modelName);
|
const { columns } = useTableColumns(props, emit, currentPage, pageSize, modelName);
|
||||||
useSortable(props, emit, tMagicTableRef, modelName, updateKey);
|
useSortable(props, emit, tMagicTableRef, modelName, updateKey);
|
||||||
const { isFullscreen, toggleFullscreen } = useFullscreen();
|
const { isFullscreen, toggleFullscreen } = useFullscreen();
|
||||||
|
|
||||||
|
watch(isFullscreen, (value) => {
|
||||||
|
if (value) {
|
||||||
|
fullscreenZIndex.value = nextZIndex();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const { importable, excelHandler, clearHandler } = useImport(props, emit, newHandler);
|
const { importable, excelHandler, clearHandler } = useImport(props, emit, newHandler);
|
||||||
const { selectHandle, toggleRowSelection } = useSelection(props, emit, tMagicTableRef);
|
const { selectHandle, toggleRowSelection } = useSelection(props, emit, tMagicTableRef);
|
||||||
|
|
||||||
const data = computed(() => (props.config.pagination ? paginationData.value : props.model[modelName.value]));
|
const data = computed(() => (props.config.pagination ? paginationData.value : props.model[modelName.value]));
|
||||||
|
|
||||||
const toggleMode = () => {
|
|
||||||
const calcLabelWidth = (label: string) => {
|
|
||||||
if (!label) return '0px';
|
|
||||||
const zhLength = label.match(/[^\x00-\xff]/g)?.length || 0;
|
|
||||||
const chLength = label.length - zhLength;
|
|
||||||
return `${Math.max(chLength * 8 + zhLength * 20, 80)}px`;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 切换为groupList的形式
|
|
||||||
props.config.type = 'groupList';
|
|
||||||
props.config.enableToggleMode = true;
|
|
||||||
props.config.tableItems = props.config.items;
|
|
||||||
props.config.items =
|
|
||||||
props.config.groupItems ||
|
|
||||||
props.config.items.map((item: any) => {
|
|
||||||
const text = item.text || item.label;
|
|
||||||
const labelWidth = calcLabelWidth(text);
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
text,
|
|
||||||
labelWidth,
|
|
||||||
span: item.span || 12,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const sortChangeHandler = (sortOptions: SortProp) => {
|
const sortChangeHandler = (sortOptions: SortProp) => {
|
||||||
const modelName = props.name || props.config.name || '';
|
const modelName = props.name || props.config.name || '';
|
||||||
sortChange(props.model[modelName], sortOptions);
|
sortChange(props.model[modelName], sortOptions);
|
||||||
|
|||||||
@ -13,6 +13,5 @@ export interface TableProps {
|
|||||||
sortKey?: string;
|
sortKey?: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
size?: string;
|
size?: string;
|
||||||
enableToggleMode?: boolean;
|
|
||||||
showIndex?: boolean;
|
showIndex?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { computed, inject } from 'vue';
|
import { inject } from 'vue';
|
||||||
|
|
||||||
import { tMagicMessage } from '@tmagic/design';
|
import { tMagicMessage } from '@tmagic/design';
|
||||||
import type { FormConfig, FormState } from '@tmagic/form-schema';
|
import type { FormConfig, FormState } from '@tmagic/form-schema';
|
||||||
@ -13,21 +13,6 @@ export const useAdd = (
|
|||||||
) => {
|
) => {
|
||||||
const mForm = inject<FormState | undefined>('mForm');
|
const mForm = inject<FormState | undefined>('mForm');
|
||||||
|
|
||||||
const addable = computed(() => {
|
|
||||||
const modelName = props.name || props.config.name || '';
|
|
||||||
if (!props.model[modelName].length) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (typeof props.config.addable === 'function') {
|
|
||||||
return props.config.addable(mForm, {
|
|
||||||
model: props.model[modelName],
|
|
||||||
formValue: mForm?.values,
|
|
||||||
prop: props.prop,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return typeof props.config.addable === 'undefined' ? true : props.config.addable;
|
|
||||||
});
|
|
||||||
|
|
||||||
const newHandler = async (row?: any) => {
|
const newHandler = async (row?: any) => {
|
||||||
const modelName = props.name || props.config.name || '';
|
const modelName = props.name || props.config.name || '';
|
||||||
|
|
||||||
@ -37,7 +22,7 @@ export const useAdd = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof props.config.beforeAddRow === 'function') {
|
if (typeof props.config.beforeAddRow === 'function') {
|
||||||
const beforeCheckRes = props.config.beforeAddRow(mForm, {
|
const beforeCheckRes = await props.config.beforeAddRow(mForm, {
|
||||||
model: props.model[modelName],
|
model: props.model[modelName],
|
||||||
formValue: mForm?.values,
|
formValue: mForm?.values,
|
||||||
prop: props.prop,
|
prop: props.prop,
|
||||||
@ -106,7 +91,6 @@ export const useAdd = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addable,
|
|
||||||
newHandler,
|
newHandler,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/schema",
|
"name": "@tmagic/schema",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/stage",
|
"name": "@tmagic/stage",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/table",
|
"name": "@tmagic/table",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": [
|
"sideEffects": [
|
||||||
|
|||||||
@ -139,6 +139,7 @@ const tableColumns = computed(() =>
|
|||||||
prop: item.prop,
|
prop: item.prop,
|
||||||
type,
|
type,
|
||||||
selectable: item.selectable,
|
selectable: item.selectable,
|
||||||
|
sortable: item.sortable,
|
||||||
},
|
},
|
||||||
cell: type === 'selection' ? undefined : ({ row, $index }: any) => cellRender(item, { row, $index }),
|
cell: type === 'selection' ? undefined : ({ row, $index }: any) => cellRender(item, { row, $index }),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/tdesign-vue-next-adapter",
|
"name": "@tmagic/tdesign-vue-next-adapter",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"name": "@tmagic/utils",
|
"name": "@tmagic/utils",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tmagic-playground",
|
"name": "tmagic-playground",
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -12,11 +12,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.2",
|
"@element-plus/icons-vue": "^2.3.2",
|
||||||
"@tmagic/core": "1.7.10",
|
"@tmagic/core": "1.7.11",
|
||||||
"@tmagic/design": "1.7.10",
|
"@tmagic/design": "1.7.11",
|
||||||
"@tmagic/editor": "1.7.10",
|
"@tmagic/editor": "1.7.11",
|
||||||
"@tmagic/element-plus-adapter": "1.7.10",
|
"@tmagic/element-plus-adapter": "1.7.11",
|
||||||
"@tmagic/tdesign-vue-next-adapter": "1.7.10",
|
"@tmagic/tdesign-vue-next-adapter": "1.7.11",
|
||||||
"@tmagic/tmagic-form-runtime": "1.1.3",
|
"@tmagic/tmagic-form-runtime": "1.1.3",
|
||||||
"element-plus": "^2.11.8",
|
"element-plus": "^2.11.8",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
@ -30,8 +30,8 @@
|
|||||||
"@types/lodash-es": "^4.17.4",
|
"@types/lodash-es": "^4.17.4",
|
||||||
"@types/node": "^24.0.10",
|
"@types/node": "^24.0.10",
|
||||||
"@types/serialize-javascript": "^5.0.4",
|
"@types/serialize-javascript": "^5.0.4",
|
||||||
"@vitejs/plugin-legacy": "^8.0.0",
|
"@vitejs/plugin-legacy": "^8.0.1",
|
||||||
"@vitejs/plugin-vue": "^6.0.5",
|
"@vitejs/plugin-vue": "^6.0.6",
|
||||||
"@vitejs/plugin-vue-jsx": "^5.1.5",
|
"@vitejs/plugin-vue-jsx": "^5.1.5",
|
||||||
"@vue/compiler-sfc": "catalog:",
|
"@vue/compiler-sfc": "catalog:",
|
||||||
"typescript": "catalog:",
|
"typescript": "catalog:",
|
||||||
|
|||||||
1941
pnpm-lock.yaml
generated
1941
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,13 @@
|
|||||||
packages:
|
packages:
|
||||||
- 'packages/*'
|
- "packages/*"
|
||||||
- 'playground'
|
- "playground"
|
||||||
- 'runtime/*'
|
- "runtime/*"
|
||||||
- 'vue-components/*'
|
- "vue-components/*"
|
||||||
- 'react-components/*'
|
- "react-components/*"
|
||||||
- 'eslint-config'
|
- "eslint-config"
|
||||||
|
|
||||||
catalog:
|
catalog:
|
||||||
vue: ^3.5.24
|
vue: ^3.5.33
|
||||||
'@vue/compiler-sfc': ^3.5.24
|
"@vue/compiler-sfc": ^3.5.33
|
||||||
vite: ^8.0.3
|
vite: ^8.0.10
|
||||||
typescript: "^6.0.2"
|
typescript: "^6.0.3"
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "runtime-react",
|
"name": "runtime-react",
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -16,16 +16,16 @@
|
|||||||
"build:playground": "node scripts/build.mjs --type=playground"
|
"build:playground": "node scripts/build.mjs --type=playground"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tmagic/core": "1.7.10",
|
"@tmagic/core": "1.7.11",
|
||||||
"@tmagic/react-runtime-help": "0.2.2",
|
"@tmagic/react-runtime-help": "0.2.2",
|
||||||
"@tmagic/stage": "1.7.10",
|
"@tmagic/stage": "1.7.11",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"qrcode": "^1.5.0",
|
"qrcode": "^1.5.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "^18.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tmagic/cli": "1.7.10",
|
"@tmagic/cli": "1.7.11",
|
||||||
"@types/fs-extra": "^11.0.4",
|
"@types/fs-extra": "^11.0.4",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "2.0.1",
|
"version": "2.0.2",
|
||||||
"name": "@tmagic/vue-runtime-help",
|
"name": "@tmagic/vue-runtime-help",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { computed, inject, nextTick, reactive, ref, watch } from 'vue';
|
import { computed, inject, nextTick, reactive, ref, watch } from 'vue';
|
||||||
|
|
||||||
import type TMagicApp from '@tmagic/core';
|
import type TMagicApp from '@tmagic/core';
|
||||||
import type { Id, MApp, MNode } from '@tmagic/core';
|
import type { Id, MApp, MNode, MPage, MPageFragment } from '@tmagic/core';
|
||||||
import { getElById, getNodePath, replaceChildNode } from '@tmagic/core';
|
import { asyncLoadCss, getElById, getNodePath, replaceChildNode } from '@tmagic/core';
|
||||||
import type { Magic, RemoveData, UpdateData } from '@tmagic/stage';
|
import type { Magic, RemoveData, Runtime, UpdateData } from '@tmagic/stage';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -11,7 +11,22 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useEditorDsl = (app = inject<TMagicApp>('app'), win = window) => {
|
let styleEl: HTMLStyleElement | null = null;
|
||||||
|
|
||||||
|
const createCss = async (config: MPage | MPageFragment) => {
|
||||||
|
if (config.cssFile) {
|
||||||
|
await asyncLoadCss(config.cssFile, window.document);
|
||||||
|
}
|
||||||
|
if (config.css) {
|
||||||
|
if (!styleEl) {
|
||||||
|
styleEl = window.document.createElement('style');
|
||||||
|
window.document.head.appendChild(styleEl);
|
||||||
|
}
|
||||||
|
styleEl.innerHTML = config.css;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useEditorDsl = (app = inject<TMagicApp>('app'), runtimeApi: Runtime = {}, win = window) => {
|
||||||
const root = ref<MApp>();
|
const root = ref<MApp>();
|
||||||
const curPageId = ref<Id>();
|
const curPageId = ref<Id>();
|
||||||
const selectedId = ref<Id>();
|
const selectedId = ref<Id>();
|
||||||
@ -20,31 +35,37 @@ export const useEditorDsl = (app = inject<TMagicApp>('app'), win = window) => {
|
|||||||
() => root.value?.items?.find((item: MNode) => item.id === curPageId.value) || root.value?.items?.[0],
|
() => root.value?.items?.find((item: MNode) => item.id === curPageId.value) || root.value?.items?.[0],
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(pageConfig, async () => {
|
watch(pageConfig, (config) => {
|
||||||
await nextTick();
|
if (!config) return;
|
||||||
const page =
|
|
||||||
document.querySelector<HTMLElement>('.magic-ui-page') ||
|
setTimeout(() => {
|
||||||
document.querySelector<HTMLElement>('.magic-ui-page-fragment');
|
const page =
|
||||||
page && win.magic?.onPageElUpdate(page);
|
document.querySelector<HTMLElement>('.magic-ui-page') ||
|
||||||
|
document.querySelector<HTMLElement>('.magic-ui-page-fragment');
|
||||||
|
page && win.magic?.onPageElUpdate(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
createCss(config);
|
||||||
});
|
});
|
||||||
|
|
||||||
win.magic?.onRuntimeReady({
|
const updateRoot = (config: MApp) => {
|
||||||
getApp() {
|
root.value = config;
|
||||||
return app;
|
if (typeof curPageId.value === 'undefined') {
|
||||||
},
|
curPageId.value = config.items?.[0]?.id;
|
||||||
|
}
|
||||||
|
|
||||||
updateRootConfig(config: MApp) {
|
if (typeof selectedId.value === 'undefined') {
|
||||||
root.value = config;
|
selectedId.value = curPageId.value;
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof curPageId.value === 'undefined') {
|
app?.setConfig(config, curPageId.value);
|
||||||
curPageId.value = config.items?.[0]?.id;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof selectedId.value === 'undefined') {
|
window.magic?.onRuntimeReady({
|
||||||
selectedId.value = curPageId.value;
|
getApp: () => app,
|
||||||
}
|
|
||||||
|
|
||||||
app?.setConfig(config, curPageId.value);
|
updateRootConfig: (config: MApp) => {
|
||||||
|
updateRoot(config);
|
||||||
},
|
},
|
||||||
|
|
||||||
updatePageId(id: Id) {
|
updatePageId(id: Id) {
|
||||||
@ -65,8 +86,14 @@ export const useEditorDsl = (app = inject<TMagicApp>('app'), win = window) => {
|
|||||||
return nextTick().then(() => getElById()(document, `${id}`));
|
return nextTick().then(() => getElById()(document, `${id}`));
|
||||||
},
|
},
|
||||||
|
|
||||||
add({ config, parentId }: UpdateData) {
|
add: ({ config, parentId, root: appConfig }: UpdateData) => {
|
||||||
if (!root.value) throw new Error('error');
|
if (!root.value) {
|
||||||
|
if (appConfig) {
|
||||||
|
updateRoot(appConfig);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Error('error');
|
||||||
|
}
|
||||||
if (!selectedId.value) throw new Error('error');
|
if (!selectedId.value) throw new Error('error');
|
||||||
if (!parentId) throw new Error('error');
|
if (!parentId) throw new Error('error');
|
||||||
|
|
||||||
@ -87,13 +114,15 @@ export const useEditorDsl = (app = inject<TMagicApp>('app'), win = window) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
update({ config, parentId }: UpdateData) {
|
update: ({ config, parentId, root: appConfig }: UpdateData) => {
|
||||||
if (!root.value || !app) throw new Error('error');
|
if (!root.value) {
|
||||||
|
if (appConfig) {
|
||||||
if (config.type === 'app') {
|
updateRoot(appConfig);
|
||||||
this.updateRootConfig?.(config as MApp);
|
return;
|
||||||
return;
|
}
|
||||||
|
throw new Error('error');
|
||||||
}
|
}
|
||||||
|
if (!app) throw new Error('error');
|
||||||
|
|
||||||
const newNode = app.dataSourceManager?.compiledNode(config, undefined, true) || config;
|
const newNode = app.dataSourceManager?.compiledNode(config, undefined, true) || config;
|
||||||
|
|
||||||
@ -109,7 +138,7 @@ export const useEditorDsl = (app = inject<TMagicApp>('app'), win = window) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
remove({ id, parentId }: RemoveData) {
|
remove: ({ id, parentId }: RemoveData) => {
|
||||||
if (!root.value) throw new Error('error');
|
if (!root.value) throw new Error('error');
|
||||||
|
|
||||||
const node = getNodePath(id, [root.value]).pop();
|
const node = getNodePath(id, [root.value]).pop();
|
||||||
@ -127,6 +156,8 @@ export const useEditorDsl = (app = inject<TMagicApp>('app'), win = window) => {
|
|||||||
const index = parent.items?.findIndex((child: MNode) => child.id === node.id);
|
const index = parent.items?.findIndex((child: MNode) => child.id === node.id);
|
||||||
parent.items.splice(index, 1);
|
parent.items.splice(index, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
...runtimeApi,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "runtime-vue",
|
"name": "runtime-vue",
|
||||||
"version": "1.7.10",
|
"version": "1.7.11",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -16,18 +16,18 @@
|
|||||||
"build:playground": "node scripts/build.mjs --type=playground"
|
"build:playground": "node scripts/build.mjs --type=playground"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tmagic/core": "1.7.10",
|
"@tmagic/core": "1.7.11",
|
||||||
"@tmagic/stage": "1.7.10",
|
"@tmagic/stage": "1.7.11",
|
||||||
"@tmagic/vue-runtime-help": "^2.0.0",
|
"@tmagic/vue-runtime-help": "^2.0.1",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"vue": "catalog:"
|
"vue": "catalog:"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tmagic/cli": "1.7.10",
|
"@tmagic/cli": "1.7.11",
|
||||||
"@types/fs-extra": "^11.0.4",
|
"@types/fs-extra": "^11.0.4",
|
||||||
"@types/node": "^24.0.10",
|
"@types/node": "^24.0.10",
|
||||||
"@vitejs/plugin-legacy": "^8.0.0",
|
"@vitejs/plugin-legacy": "^8.0.1",
|
||||||
"@vitejs/plugin-vue": "^6.0.5",
|
"@vitejs/plugin-vue": "^6.0.6",
|
||||||
"@vitejs/plugin-vue-jsx": "^5.1.5",
|
"@vitejs/plugin-vue-jsx": "^5.1.5",
|
||||||
"@vue/compiler-sfc": "catalog:",
|
"@vue/compiler-sfc": "catalog:",
|
||||||
"fs-extra": "^11.3.1",
|
"fs-extra": "^11.3.1",
|
||||||
|
|||||||
@ -20,9 +20,10 @@ if (args.package) {
|
|||||||
const pkgRoot = path.resolve(packagesDir, args.package);
|
const pkgRoot = path.resolve(packagesDir, args.package);
|
||||||
if (fs.statSync(pkgRoot).isDirectory()) {
|
if (fs.statSync(pkgRoot).isDirectory()) {
|
||||||
rimraf.sync(path.resolve(packagesDir, `./${args.package}/dist`));
|
rimraf.sync(path.resolve(packagesDir, `./${args.package}/dist`));
|
||||||
|
const pkg = createRequire(import.meta.url)(`../packages/${args.package}/package.json`);
|
||||||
|
|
||||||
build({ packageName: args.package, format: 'es' });
|
build({ packageName: args.package, format: 'es', pkg, packagesDir });
|
||||||
build({ packageName: args.package, format: 'umd' });
|
build({ packageName: args.package, format: 'umd', pkg, packagesDir });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const packages = getPackageNames(packagesDir);
|
const packages = getPackageNames(packagesDir);
|
||||||
@ -45,6 +46,30 @@ if (args.package) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rolldown 在 UMD 输出顶部会注入
|
||||||
|
// Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||||
|
// 当内联的依赖(如 lodash-es 的 _Symbol.js)声明 `var Symbol = root.Symbol;`
|
||||||
|
// 时,由于 var hoisting,该局部 `Symbol` 会把上面一行引用到的全局 `Symbol`
|
||||||
|
// 遮蔽掉(此时局部变量还未赋值),运行时抛出
|
||||||
|
// TypeError: Cannot read properties of undefined (reading 'toStringTag')
|
||||||
|
// 这里通过后处理把该引用改为 `globalThis.Symbol.toStringTag`,绕开被 hoist
|
||||||
|
// 的局部绑定。rolldown 修好前先用此 workaround。
|
||||||
|
function fixUmdSymbolShadow() {
|
||||||
|
return {
|
||||||
|
name: 'tmagic:fix-umd-symbol-shadow',
|
||||||
|
generateBundle(outputOptions, bundle) {
|
||||||
|
if (outputOptions.format !== 'umd') return;
|
||||||
|
for (const file of Object.values(bundle)) {
|
||||||
|
if (file.type !== 'chunk' || typeof file.code !== 'string') continue;
|
||||||
|
file.code = file.code.replace(
|
||||||
|
/Object\.defineProperty\(exports,\s*Symbol\.toStringTag,/g,
|
||||||
|
'Object.defineProperty(exports, globalThis.Symbol.toStringTag,',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function build({ packageName, format, pkg, packagesDir }) {
|
async function build({ packageName, format, pkg, packagesDir }) {
|
||||||
await buildVite({
|
await buildVite({
|
||||||
root: path.resolve(packagesDir, `./${packageName}`),
|
root: path.resolve(packagesDir, `./${packageName}`),
|
||||||
@ -69,6 +94,7 @@ async function build({ packageName, format, pkg, packagesDir }) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
rolldownOptions: {
|
rolldownOptions: {
|
||||||
|
plugins: [fixUmdSymbolShadow()],
|
||||||
// 确保外部化处理那些你不想打包进库的依赖
|
// 确保外部化处理那些你不想打包进库的依赖
|
||||||
external(id) {
|
external(id) {
|
||||||
if (format === 'umd' && id === 'lodash-es') {
|
if (format === 'umd' && id === 'lodash-es') {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user