@tmagic/form 1.7.0-beta.1 → 1.7.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.7.0-beta.1",
2
+ "version": "1.7.0-beta.3",
3
3
  "name": "@tmagic/form",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -51,9 +51,9 @@
51
51
  "peerDependencies": {
52
52
  "vue": "^3.5.22",
53
53
  "typescript": "^5.9.3",
54
- "@tmagic/design": "1.7.0-beta.1",
55
- "@tmagic/form-schema": "1.7.0-beta.1",
56
- "@tmagic/utils": "1.7.0-beta.1"
54
+ "@tmagic/design": "1.7.0-beta.3",
55
+ "@tmagic/utils": "1.7.0-beta.3",
56
+ "@tmagic/form-schema": "1.7.0-beta.3"
57
57
  },
58
58
  "peerDependenciesMeta": {
59
59
  "typescript": {
package/src/FormBox.vue CHANGED
@@ -101,8 +101,9 @@ watchEffect(() => {
101
101
 
102
102
  const submitHandler = async () => {
103
103
  try {
104
+ const changeRecords = form.value?.changeRecords;
104
105
  const values = await form.value?.submitForm();
105
- emit('submit', values, { changeRecords: form.value?.changeRecords });
106
+ emit('submit', values, { changeRecords });
106
107
  } catch (e) {
107
108
  emit('error', e);
108
109
  }
@@ -131,8 +131,9 @@ const closeHandler = () => {
131
131
 
132
132
  const save = async () => {
133
133
  try {
134
+ const changeRecords = form.value?.changeRecords;
134
135
  const values = await form.value?.submitForm();
135
- emit('submit', values, { changeRecords: form.value?.changeRecords });
136
+ emit('submit', values, { changeRecords });
136
137
  } catch (e) {
137
138
  emit('error', e);
138
139
  }
@@ -109,8 +109,9 @@ watchEffect(() => {
109
109
 
110
110
  const submitHandler = async () => {
111
111
  try {
112
+ const changeRecords = form.value?.changeRecords;
112
113
  const values = await form.value?.submitForm();
113
- emit('submit', values, { changeRecords: form.value?.changeRecords });
114
+ emit('submit', values, { changeRecords });
114
115
  } catch (e) {
115
116
  emit('error', e);
116
117
  }
@@ -208,10 +208,7 @@ const items = computed(() => (props.config as ContainerCommonConfig).items);
208
208
 
209
209
  const itemProp = computed(() => {
210
210
  let n: string | number = '';
211
- const { names } = props.config as any;
212
- if (names?.[0]) {
213
- [n] = names;
214
- } else if (name.value) {
211
+ if (name.value) {
215
212
  n = name.value;
216
213
  } else {
217
214
  return props.prop;
@@ -2,7 +2,7 @@
2
2
  <div class="m-fields-group-list">
3
3
  <div v-if="config.extra" v-html="config.extra" style="color: rgba(0, 0, 0, 0.45)"></div>
4
4
  <div v-if="!model[name] || !model[name].length" class="el-table__empty-block">
5
- <span class="el-table__empty-text">暂无数据</span>
5
+ <span class="el-table__empty-text t-table__empty">暂无数据</span>
6
6
  </div>
7
7
 
8
8
  <MFieldsGroupListItem
@@ -26,16 +26,21 @@
26
26
  @addDiffCount="onAddDiffCount()"
27
27
  ></MFieldsGroupListItem>
28
28
 
29
- <TMagicButton
30
- v-if="addable"
31
- type="primary"
32
- :size="config.enableToggleMode ? 'small' : 'default'"
33
- :disabled="disabled"
34
- @click="addHandler"
35
- >新增</TMagicButton
36
- >
37
-
38
- <TMagicButton :icon="Grid" size="small" @click="toggleMode" v-if="config.enableToggleMode">切换为表格</TMagicButton>
29
+ <div class="m-fields-group-list-footer">
30
+ <TMagicButton v-if="config.enableToggleMode" :icon="Grid" size="small" @click="toggleMode"
31
+ >切换为表格</TMagicButton
32
+ >
33
+ <div style="display: flex; justify-content: flex-end; flex: 1">
34
+ <TMagicButton
35
+ v-if="addable"
36
+ type="primary"
37
+ :size="config.enableToggleMode ? 'small' : 'default'"
38
+ :disabled="disabled"
39
+ @click="addHandler"
40
+ >新增</TMagicButton
41
+ >
42
+ </div>
43
+ </div>
39
44
  </div>
40
45
  </template>
41
46
 
@@ -1,90 +1,92 @@
1
1
  <template>
2
- <div class="m-fields-group-list-item">
3
- <div>
4
- <TMagicButton link :disabled="disabled" @click="expandHandler">
5
- <TMagicIcon><CaretBottom v-if="expand" /><CaretRight v-else /></TMagicIcon>{{ title }}
6
- </TMagicButton>
7
-
8
- <TMagicButton
9
- v-show="showDelete"
10
- type="danger"
11
- size="small"
12
- link
13
- :icon="Delete"
14
- :disabled="disabled"
15
- @click="removeHandler"
16
- ></TMagicButton>
17
-
18
- <TMagicButton
19
- v-if="copyable"
20
- link
21
- size="small"
22
- type="primary"
23
- :icon="DocumentCopy"
24
- :disabled="disabled"
25
- @click="copyHandler"
26
- >复制</TMagicButton
27
- >
28
-
29
- <template v-if="movable">
2
+ <TMagicCard class="m-fields-group-list-item" :body-style="{ display: expand ? 'block' : 'none' }">
3
+ <template #header>
4
+ <div>
5
+ <TMagicButton link :disabled="disabled" @click="expandHandler">
6
+ <TMagicIcon><CaretBottom v-if="expand" /><CaretRight v-else /></TMagicIcon>{{ title }}
7
+ </TMagicButton>
8
+
30
9
  <TMagicButton
31
- v-show="index !== 0"
32
- link
10
+ v-show="showDelete"
11
+ type="danger"
33
12
  size="small"
13
+ link
14
+ :icon="Delete"
34
15
  :disabled="disabled"
35
- :icon="CaretTop"
36
- @click="changeOrder(-1)"
37
- >上移</TMagicButton
38
- >
16
+ @click="removeHandler"
17
+ ></TMagicButton>
18
+
39
19
  <TMagicButton
40
- v-show="index !== length - 1"
20
+ v-if="copyable"
41
21
  link
42
22
  size="small"
23
+ type="primary"
24
+ :icon="DocumentCopy"
43
25
  :disabled="disabled"
44
- :icon="CaretBottom"
45
- @click="changeOrder(1)"
46
- >下移</TMagicButton
26
+ @click="copyHandler"
27
+ >复制</TMagicButton
47
28
  >
48
- </template>
49
-
50
- <TMagicPopover
51
- v-if="config.moveSpecifyLocation"
52
- trigger="click"
53
- placement="top"
54
- width="200"
55
- :visible="moveSpecifyLocationVisible"
56
- >
57
- <template #reference>
29
+
30
+ <template v-if="movable">
31
+ <TMagicButton
32
+ v-show="index !== 0"
33
+ link
34
+ size="small"
35
+ :disabled="disabled"
36
+ :icon="CaretTop"
37
+ @click="changeOrder(-1)"
38
+ >上移</TMagicButton
39
+ >
58
40
  <TMagicButton
41
+ v-show="index !== length - 1"
59
42
  link
60
43
  size="small"
61
- type="primary"
62
- :icon="Position"
63
44
  :disabled="disabled"
64
- @click="moveSpecifyLocationVisible = true"
65
- >移动至</TMagicButton
45
+ :icon="CaretBottom"
46
+ @click="changeOrder(1)"
47
+ >下移</TMagicButton
66
48
  >
67
49
  </template>
68
- <div>
69
- <div>
70
- 第<TMagicInputNumber
71
- style="margin: 0 5px"
72
- v-model="moveSpecifyLocationIndex"
50
+
51
+ <TMagicPopover
52
+ v-if="config.moveSpecifyLocation"
53
+ trigger="click"
54
+ placement="top"
55
+ width="200"
56
+ :visible="moveSpecifyLocationVisible"
57
+ >
58
+ <template #reference>
59
+ <TMagicButton
60
+ link
73
61
  size="small"
74
- :min="1"
62
+ type="primary"
63
+ :icon="Position"
75
64
  :disabled="disabled"
76
- ></TMagicInputNumber
77
- >行
78
- </div>
79
- <div style="text-align: right; margin-top: 20px">
80
- <TMagicButton size="small" text @click="moveSpecifyLocationVisible = false">取消</TMagicButton>
81
- <TMagicButton size="small" type="primary" @click="moveSpecifyLocationHandler">确认</TMagicButton>
65
+ @click="moveSpecifyLocationVisible = true"
66
+ >移动至</TMagicButton
67
+ >
68
+ </template>
69
+ <div>
70
+ <div>
71
+ 第<TMagicInputNumber
72
+ style="margin: 0 5px"
73
+ v-model="moveSpecifyLocationIndex"
74
+ size="small"
75
+ :min="1"
76
+ :disabled="disabled"
77
+ ></TMagicInputNumber
78
+ >行
79
+ </div>
80
+ <div style="text-align: right; margin-top: 20px">
81
+ <TMagicButton size="small" text @click="moveSpecifyLocationVisible = false">取消</TMagicButton>
82
+ <TMagicButton size="small" type="primary" @click="moveSpecifyLocationHandler">确认</TMagicButton>
83
+ </div>
82
84
  </div>
83
- </div>
84
- </TMagicPopover>
85
+ </TMagicPopover>
85
86
 
86
- <span v-if="itemExtra" v-html="itemExtra" class="m-form-tip"></span>
87
- </div>
87
+ <span v-if="itemExtra" v-html="itemExtra" class="m-form-tip"></span>
88
+ </div>
89
+ </template>
88
90
 
89
91
  <Container
90
92
  v-if="expand"
@@ -99,14 +101,14 @@
99
101
  @change="changeHandler"
100
102
  @addDiffCount="onAddDiffCount()"
101
103
  ></Container>
102
- </div>
104
+ </TMagicCard>
103
105
  </template>
104
106
 
105
107
  <script setup lang="ts">
106
108
  import { computed, inject, ref } from 'vue';
107
109
  import { CaretBottom, CaretRight, CaretTop, Delete, DocumentCopy, Position } from '@element-plus/icons-vue';
108
110
 
109
- import { TMagicButton, TMagicIcon, TMagicInputNumber, TMagicPopover } from '@tmagic/design';
111
+ import { TMagicButton, TMagicCard, TMagicIcon, TMagicInputNumber, TMagicPopover } from '@tmagic/design';
110
112
 
111
113
  import type { ContainerChangeEventData, FormState, GroupListConfig } from '../schema';
112
114
  import { filterFunction } from '../utils/form';
@@ -9,6 +9,7 @@
9
9
  :unlink-panels="true"
10
10
  :disabled="disabled"
11
11
  :default-time="config.defaultTime"
12
+ :format="`${config.dateFormat || 'YYYY/MM/DD'} ${config.timeFormat || 'HH:mm:ss'}`"
12
13
  :value-format="config.valueFormat || 'YYYY/MM/DD HH:mm:ss'"
13
14
  :date-format="config.dateFormat || 'YYYY/MM/DD'"
14
15
  :time-format="config.timeFormat || 'HH:mm:ss'"
@@ -17,11 +18,11 @@
17
18
  </template>
18
19
 
19
20
  <script lang="ts" setup>
20
- import { ref, watch } from 'vue';
21
+ import { onUnmounted, ref, watch } from 'vue';
21
22
 
22
23
  import { TMagicDatePicker } from '@tmagic/design';
23
24
 
24
- import type { DaterangeConfig, FieldProps } from '../schema';
25
+ import type { ChangeRecord, DaterangeConfig, FieldProps } from '../schema';
25
26
  import { datetimeFormatter } from '../utils/form';
26
27
  import { useAddField } from '../utils/useAddField';
27
28
 
@@ -40,7 +41,7 @@ const value = ref<(Date | string | undefined)[] | null>([]);
40
41
 
41
42
  if (props.model !== undefined) {
42
43
  if (names?.length) {
43
- watch(
44
+ const unWatch = watch(
44
45
  [() => props.model[names[0]], () => props.model[names[1]]],
45
46
  ([start, end], [preStart, preEnd]) => {
46
47
  if (!value.value) {
@@ -56,8 +57,12 @@ if (props.model !== undefined) {
56
57
  immediate: true,
57
58
  },
58
59
  );
60
+
61
+ onUnmounted(() => {
62
+ unWatch();
63
+ });
59
64
  } else if (props.name && props.model[props.name]) {
60
- watch(
65
+ const unWatch = watch(
61
66
  () => props.model[props.name],
62
67
  (start, preStart) => {
63
68
  const format = `${props.config.dateFormat || 'YYYY/MM/DD'} ${props.config.timeFormat || 'HH:mm:ss'}`;
@@ -71,32 +76,41 @@ if (props.model !== undefined) {
71
76
  immediate: true,
72
77
  },
73
78
  );
79
+ onUnmounted(() => {
80
+ unWatch();
81
+ });
74
82
  }
75
83
  }
76
84
 
77
- const setValue = (v: Date[] | Date) => {
78
- names?.forEach((item, index) => {
79
- if (!props.model) {
80
- return;
81
- }
82
- if (Array.isArray(v)) {
83
- props.model[item] = v[index];
84
- } else {
85
- props.model[item] = undefined;
86
- }
87
- });
88
- };
89
-
90
85
  const changeHandler = (v: Date[]) => {
91
86
  const value = v || [];
92
87
 
93
88
  if (props.name) {
94
89
  emit('change', value);
95
90
  } else {
96
- if (names?.length) {
97
- setValue(value);
91
+ if (props.config.names?.length) {
92
+ const newChangeRecords: ChangeRecord[] = [];
93
+ props.config.names.forEach((item, index) => {
94
+ if (!props.model) {
95
+ return;
96
+ }
97
+ if (Array.isArray(v)) {
98
+ newChangeRecords.push({
99
+ propPath: props.prop ? `${props.prop}.${item}` : item,
100
+ value: v[index],
101
+ });
102
+ } else {
103
+ newChangeRecords.push({
104
+ propPath: props.prop ? `${props.prop}.${item}` : item,
105
+ value: undefined,
106
+ });
107
+ }
108
+ });
109
+
110
+ emit('change', props.model, {
111
+ changeRecords: newChangeRecords,
112
+ });
98
113
  }
99
- emit('change', props.model);
100
114
  }
101
115
  };
102
116
  </script>
@@ -17,7 +17,7 @@
17
17
  </template>
18
18
 
19
19
  <script lang="ts" setup>
20
- import { computed, inject, ref } from 'vue';
20
+ import { computed, inject, readonly, ref } from 'vue';
21
21
 
22
22
  import { TMagicButton } from '@tmagic/design';
23
23
 
@@ -54,7 +54,8 @@ const formConfig = computed(() => {
54
54
  if (typeof props.config.form === 'function') {
55
55
  return props.config.form(mForm, {
56
56
  model: props.model || {},
57
- values: props.values || {},
57
+ values: mForm ? readonly(mForm.initValues) : null,
58
+ formValue: props.values || {},
58
59
  });
59
60
  }
60
61
  return props.config.form;
@@ -41,7 +41,7 @@
41
41
  </template>
42
42
 
43
43
  <script lang="ts" setup>
44
- import { computed, inject, ref, shallowRef, watch } from 'vue';
44
+ import { computed, inject, readonly, ref, shallowRef, watch } from 'vue';
45
45
  import type { Instance } from '@popperjs/core';
46
46
  import { createPopper } from '@popperjs/core';
47
47
  import { debounce } from 'lodash-es';
@@ -49,7 +49,7 @@ import { debounce } from 'lodash-es';
49
49
  import { TMagicButton, TMagicInput } from '@tmagic/design';
50
50
  import { isNumber } from '@tmagic/utils';
51
51
 
52
- import type { FieldProps, FormState, TextConfig } from '../schema';
52
+ import type { ChangeRecord, ContainerChangeEventData, FieldProps, FormState, TextConfig } from '../schema';
53
53
  import { useAddField } from '../utils/useAddField';
54
54
 
55
55
  defineOptions({
@@ -59,7 +59,7 @@ defineOptions({
59
59
  const props = defineProps<FieldProps<TextConfig>>();
60
60
 
61
61
  const emit = defineEmits<{
62
- change: [value: string];
62
+ change: [value: string, eventData?: ContainerChangeEventData];
63
63
  input: [value: string];
64
64
  }>();
65
65
 
@@ -121,10 +121,28 @@ const inputHandler = (v: string) => {
121
121
  const buttonClickHandler = () => {
122
122
  if (!appendConfig.value) return;
123
123
  if (typeof appendConfig.value.handler === 'function') {
124
+ const newChangeRecords: ChangeRecord[] = [];
125
+ const setModel = (key: string, value: any) => {
126
+ newChangeRecords.push({ propPath: props.prop.replace(`${props.name}`, key), value });
127
+ };
128
+
129
+ const setFormValue = (key: string, value: any) => {
130
+ newChangeRecords.push({ propPath: key, value });
131
+ };
132
+
124
133
  appendConfig.value.handler(mForm, {
125
134
  model: props.model,
126
- values: mForm?.values,
135
+ values: mForm ? readonly(mForm.initValues) : null,
136
+ formValue: props.values || {},
137
+ setModel,
138
+ setFormValue,
127
139
  });
140
+
141
+ if (newChangeRecords.length > 0) {
142
+ emit('change', props.model[props.name], {
143
+ changeRecords: newChangeRecords,
144
+ });
145
+ }
128
146
  }
129
147
  };
130
148
 
@@ -1,7 +1,12 @@
1
1
  <template>
2
- <div class="m-fields-table-wrap">
3
- <teleport to="body" :disabled="!isFullscreen">
4
- <div ref="mTable" class="m-fields-table" :class="{ 'm-fields-table-item-extra': config.itemExtra }">
2
+ <teleport to="body" :disabled="!isFullscreen">
3
+ <div
4
+ v-bind="$attrs"
5
+ class="m-fields-table-wrap"
6
+ :class="{ fixed: isFullscreen }"
7
+ :style="isFullscreen ? `z-index: ${nextZIndex()}` : ''"
8
+ >
9
+ <div class="m-fields-table" :class="{ 'm-fields-table-item-extra': config.itemExtra }">
5
10
  <span v-if="config.extra" style="color: rgba(0, 0, 0, 0.45)" v-html="config.extra"></span>
6
11
  <TMagicTooltip content="拖拽可排序" placement="left-start" :disabled="config.dropSort !== true">
7
12
  <TMagicTable
@@ -24,15 +29,10 @@
24
29
  <slot></slot>
25
30
 
26
31
  <div style="display: flex; justify-content: space-between; margin: 10px 0">
27
- <TMagicButton v-if="addable" size="small" type="primary" :disabled="disabled" plain @click="newHandler()"
28
- >新增一行</TMagicButton
29
- >
30
-
31
32
  <div style="display: flex">
32
33
  <TMagicButton
33
34
  :icon="Grid"
34
35
  size="small"
35
- type="primary"
36
36
  @click="toggleMode"
37
37
  v-if="enableToggleMode && config.enableToggleMode !== false && !isFullscreen"
38
38
  >展开配置</TMagicButton
@@ -40,7 +40,6 @@
40
40
  <TMagicButton
41
41
  :icon="FullScreen"
42
42
  size="small"
43
- type="primary"
44
43
  @click="toggleFullscreen"
45
44
  v-if="config.enableFullscreen !== false"
46
45
  >
@@ -61,6 +60,9 @@
61
60
  >清空</TMagicButton
62
61
  >
63
62
  </div>
63
+ <TMagicButton v-if="addable" size="small" type="primary" :disabled="disabled" plain @click="newHandler()"
64
+ >新增一行</TMagicButton
65
+ >
64
66
  </div>
65
67
 
66
68
  <div class="bottom" style="text-align: right" v-if="config.pagination">
@@ -77,15 +79,15 @@
77
79
  </TMagicPagination>
78
80
  </div>
79
81
  </div>
80
- </teleport>
81
- </div>
82
+ </div>
83
+ </teleport>
82
84
  </template>
83
85
 
84
86
  <script setup lang="ts">
85
87
  import { computed, ref, useTemplateRef } from 'vue';
86
88
  import { FullScreen, Grid } from '@element-plus/icons-vue';
87
89
 
88
- import { TMagicButton, TMagicPagination, TMagicTable, TMagicTooltip, TMagicUpload } from '@tmagic/design';
90
+ import { TMagicButton, TMagicPagination, TMagicTable, TMagicTooltip, TMagicUpload, useZIndex } from '@tmagic/design';
89
91
 
90
92
  import type { SortProp } from '../schema';
91
93
  import { sortChange } from '../utils/form';
@@ -122,6 +124,8 @@ const { pageSize, currentPage, paginationData, handleSizeChange, handleCurrentCh
122
124
  modelName,
123
125
  );
124
126
 
127
+ const { nextZIndex } = useZIndex();
128
+
125
129
  const { addable, newHandler } = useAdd(props, emit);
126
130
  const { columns } = useTableColumns(props, emit, currentPage, pageSize, modelName);
127
131
  useSortable(props, emit, tMagicTableRef, modelName);
@@ -78,6 +78,7 @@ export const useAdd = (
78
78
  if (typeof props.config.defaultAdd === 'function') {
79
79
  inputs = await props.config.defaultAdd(mForm, {
80
80
  model: props.model[modelName],
81
+ prop: props.prop,
81
82
  formValue: mForm?.values,
82
83
  });
83
84
  } else if (props.config.defaultAdd) {
@@ -1,22 +1,12 @@
1
- import { ref, useTemplateRef } from 'vue';
2
-
3
- import { useZIndex } from '@tmagic/design';
1
+ import { ref } from 'vue';
4
2
 
5
3
  export const useFullscreen = () => {
6
4
  const isFullscreen = ref(false);
7
- const mTableEl = useTemplateRef<HTMLDivElement>('mTable');
8
-
9
- const { nextZIndex } = useZIndex();
10
5
 
11
6
  const toggleFullscreen = () => {
12
- if (!mTableEl.value) return;
13
-
14
7
  if (isFullscreen.value) {
15
- mTableEl.value.classList.remove('fixed');
16
8
  isFullscreen.value = false;
17
9
  } else {
18
- mTableEl.value.classList.add('fixed');
19
- mTableEl.value.style.zIndex = `${nextZIndex()}`;
20
10
  isFullscreen.value = true;
21
11
  }
22
12
  };
@@ -20,4 +20,19 @@
20
20
  border-bottom: 0;
21
21
  }
22
22
  }
23
+
24
+ .tmagic-design-card {
25
+ .el-card__header {
26
+ padding: 5px 20px;
27
+ }
28
+ .t-card__header {
29
+ padding: 5px 0;
30
+ }
31
+ }
32
+
33
+ .m-fields-group-list-footer {
34
+ display: flex;
35
+ justify-content: space-between;
36
+ margin-top: 10px;
37
+ }
23
38
  }
@@ -1,9 +1,6 @@
1
1
  .m-fields-table-wrap {
2
2
  width: 100%;
3
- }
4
3
 
5
- .m-fields-table {
6
- width: 100%;
7
4
  &.fixed {
8
5
  position: fixed;
9
6
  height: 100%;
@@ -14,6 +11,8 @@
14
11
  bottom: 0;
15
12
  z-index: 100;
16
13
  background: rgba(0, 0, 0, 0.5);
14
+ align-items: center;
15
+ display: flex;
17
16
 
18
17
  & > .el-form-item__content {
19
18
  z-index: 101;
@@ -25,6 +24,10 @@
25
24
  width: 95vw !important;
26
25
  }
27
26
  }
27
+ }
28
+
29
+ .m-fields-table {
30
+ width: 100%;
28
31
 
29
32
  th {
30
33
  background-color: #f2f2f2 !important;