vue-2024-ui 0.0.7 → 0.0.8

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/README.form.md CHANGED
@@ -10,8 +10,8 @@
10
10
  | --------- | ------------------------------------------------------------------- | ------ | -------------------------------------------------------------------------------------------- |
11
11
  | columns | 表单列数 | number | 2 |
12
12
  | footer | 控制表单底部按钮是否显示和样式设置,hidden默认是false,style控制样式 | object | ```{hidden: false, style:{ display:"flex","align-items":"center",justifyContent:"center"}``` |
13
- | submit | 表单提交按钮,增加了submitText,hidden 属性和submit方法 | object | ``` {type: "primary",submitText: "提交",hidden: false,submit: async (model) => {...}, } ``` |
14
- | reset | 表单重置按钮,增加了restText,hidden 属性和reset方法 | object | ``` {type: "primary",resetText: "重置",hidden: false,reset: () => {...}, } ``` |
13
+ | submit | 表单提交按钮,增加了label,hidden 属性和click方法 | object | ``` {type: "primary",label: "提交",hidden: false,click: async (model) => {...}, } ``` |
14
+ | reset | 表单重置按钮,增加了label,hidden 属性和click方法 | object | ``` {type: "primary",label: "重置",hidden: false,click: () => {...}, } ``` |
15
15
  | formItems | 通过style属性设置所有items的样式 | object | ``` style:{width:100%} ``` |
16
16
 
17
17
  ## form 增加的事件
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-2024-ui",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "src/components/index.js",
@@ -2,8 +2,8 @@
2
2
  <el-form ref="gform" :model="model" v-bind="model.form" class="g-form-container">
3
3
  <slot>
4
4
  <el-form-item :label="item.label" :prop="`${key}.value`" :rules="getItemRulesByItem(item)"
5
- v-for="(item, key) of items" :key="key" v-bind="{ ...model.formItems, ...item.formItem }"
6
- :style="{ ...model.formItems.style, ...item?.formItem?.style }">
5
+ v-for="(item, key) of items" :key="key" v-bind="{ ...model?.formItems, ...item?.formItem }"
6
+ :style="{ ...model?.formItems?.style, ...item?.formItem?.style }">
7
7
  <slot :name="key" :item :model>
8
8
  <g-ctrl v-model="model[key].value" :item :ctrlKey="key" :model class="g-ctrl-container">
9
9
  <template v-for="(slot, slotKey, index) in $slots" :key="index" #[slotKey]="data">
@@ -15,29 +15,28 @@
15
15
  <slot :name="`${key}-label`" :data :item :model>{{ item.label }}</slot>
16
16
  </template>
17
17
  </el-form-item>
18
- <el-form-item style="width: 100%;" v-if="!model.form.footer.hidden">
19
- <slot name="footer">
20
- <div :style="model.form.footer.style">
21
- <slot name="footer-left"></slot>
22
- <el-button @click="model.form.submit.submit(model)" v-bind="model.form.submit"
23
- v-if="!model.form.submit.hidden">
24
- {{ model.form.submit.submitText }}
25
- </el-button>
26
- <el-button @click="model.form.reset.reset(model)" v-bind="model.form.reset"
27
- v-if="!model.form.reset.hidden">{{
28
- model.form.reset.resetText
29
- }}</el-button>
30
- <slot name="footer-right"></slot>
31
- </div>
32
- </slot>
33
- </el-form-item>
18
+ <slot name="footer" v-if="!model.form.footer.hidden">
19
+ <div :style="model.form.footer.style">
20
+ <slot name="footer-left"></slot>
21
+ <el-button @click="model.form.submit.click(model)" v-bind="model.form.submit"
22
+ v-if="!model?.form?.submit?.hidden">
23
+ {{ model?.form?.submit?.label }}
24
+ </el-button>
25
+ <el-button @click="model.form.reset.click(model)" v-bind="model.form.reset"
26
+ v-if="!model?.form?.reset?.hidden">{{
27
+ model?.form?.reset?.label
28
+ }}</el-button>
29
+ <slot name="footer-right"></slot>
30
+ </div>
31
+ </slot>
34
32
  </slot>
35
33
  </el-form>
36
34
  </template>
37
35
 
38
36
  <script setup>
39
- import { computed, inject, onMounted, ref, useAttrs, watch } from "vue";
37
+ import { computed, inject, onMounted, ref, useAttrs, watch, watchEffect } from "vue";
40
38
  import gCtrl from "./g-ctrl.vue";
39
+ import { convertToPx, mergeObjects } from "./index";
41
40
  defineOptions({
42
41
  name: "g-form",
43
42
  inheritAttrs: false
@@ -45,11 +44,10 @@ defineOptions({
45
44
  const model = defineModel({ required: true });
46
45
  const emits = defineEmits(["submit", "reset"]);
47
46
  const gform = ref(null);
48
- const columnsWidth = ref(0);
49
47
  let marginRight = ref(32);
50
- const options=inject('options');
51
- //合并表单默认属性
52
- model.value.form = {
48
+ const options = inject('options');
49
+
50
+ const defaultFormAttrs = {
53
51
  inline: true,
54
52
  type: "hidden",
55
53
  "scroll-to-error": true,
@@ -57,40 +55,25 @@ model.value.form = {
57
55
  "status-icon": true,
58
56
  "scroll-into-view-options": true,
59
57
  columns: 2,
60
- ...options?.form,
61
- ...model.value.form,
62
58
  style: {
63
59
  width: "600px",
64
- border: "1px solid rgba(0, 0, 0,0.09)",
65
- borderRadius: "10px",
66
- padding: "0px",
67
- paddingTop: "20px",
68
- margin: "0px",
69
- boxShadow: "0 0 5px rgba(0, 0, 0, 0.1)",
70
- ...options?.form?.style,
71
- ...model.value.form?.style,
72
- ...useAttrs().style
60
+ ...useAttrs()?.style
73
61
  },
74
62
  // 表单底部属性
75
63
  footer: {
76
64
  hidden: false,
77
- ...options?.form?.footer,
78
- ...model.value.form?.footer,
79
65
  style: {
80
- display: "flex", width: "100%", "align-items": "center", justifyContent: "center", margin: "5px",
81
- ...options?.form?.footer?.style,
82
- ...model.value.form?.footer?.style
66
+ display: "flex", width: "100%", "align-items": "center", justifyContent: "center", margin: "5px",
83
67
  },
84
68
  },
85
69
  //表单提交按钮属性
86
70
  submit: {
87
71
  type: "primary",
88
72
  disabled: false,
89
- submitText: "提交",
73
+ label: "提交",
90
74
  plain: true,
91
75
  hidden: false,
92
- ...options?.form?.submit,
93
- submit: async (model) => {
76
+ click: async (model) => {
94
77
  if (!gform.value) return
95
78
  await gform.value.validate((valid, fields) => {
96
79
  if (valid) {
@@ -100,15 +83,14 @@ model.value.form = {
100
83
  }
101
84
  })
102
85
  },
103
- ...model.value.form?.submit
104
86
  },
105
87
  //表单重置按钮属性
106
88
  reset: {
107
89
  disabled: false,
108
- resetText: "重置",
90
+ label: "重置",
109
91
  hidden: false,
110
92
  plain: true,
111
- reset: () => {
93
+ click: () => {
112
94
  if (!gform.value) return
113
95
  let isreset = true;
114
96
  emits("reset", (flag) => {
@@ -118,25 +100,24 @@ model.value.form = {
118
100
  gform.value.resetFields();
119
101
  }
120
102
  },
121
- ...options?.form?.reset,
122
- ...model.value.form?.reset
123
103
  },
124
- dialog: {
125
- width: 635,
126
- ...options?.form?.dialog,
127
- ...model.value.form?.dialog
128
- }
129
104
  };
130
- //合并表单项默认属性
131
- model.value.formItems = {
105
+ model.value.form = mergeObjects(
106
+ defaultFormAttrs,
107
+ options?.form,
108
+ model.value?.form
109
+ );
110
+ const defaultFormItemsAttrs = {
132
111
  type: "hidden",
133
112
  style: {
134
113
  width: "100%",
135
- ...options?.formItems?.style,
136
- ...model.value.formItems?.style
137
- },
138
- ...model.value.formItems,
114
+ }
139
115
  };
116
+ model.value.formItems = mergeObjects(
117
+ defaultFormItemsAttrs,
118
+ options?.formItems,
119
+ model?.formItems
120
+ );
140
121
 
141
122
  //获取表单项验证规则
142
123
  const getItemRulesByItem = (item) => {
@@ -223,48 +204,38 @@ const getItemRulesByItem = (item) => {
223
204
  return itemRules;
224
205
  }
225
206
 
226
- onMounted(() => {
227
- load();
228
- })
207
+ onMounted(() => { load(); })
229
208
 
230
209
  const load = () => {
231
210
  if (!model.value.form.inline) {
232
211
  model.value.form.columns = 1;
233
212
  }
234
- if (model.value.form.style.width) {
235
- columnsWidth.value = removePx(model.value.form.style.width) / model.value.form.columns;
236
- }
237
- else {
238
- model.value.form.style.width = "600px";
239
- }
240
- model.value.form.dialog.width = +model.value?.form?.style?.width.replace("px", "") + 35 + "px";
241
213
  for (const [key, value] of Object.entries(items.value)) {
242
- model.value[key].formItem = { ...model.value[key].formItem, ...value.formItem }
214
+ model.value[key].formItem = { ...model.value[key].formItem, ...value.formItem };
243
215
  model.value[key].formItem.style = { ...model.value[key].formItem.style, ...value.formItem.style };
244
- if (value.columns && value.columns > 1) {
245
- if (model.value.form.inline) {
246
- let column = columnsWidth.value * value.columns - (value.columns - 1) * marginRight.value;
247
- model.value[key].formItem.style.width = `calc(${column}px)`;
248
- } else {
249
- model.value[key].formItem.style.width = `calc(${columnsWidth.value - marginRight.value}px)`;
250
- }
251
- } else {
252
- model.value[key].formItem.style.width = `calc(${columnsWidth.value - marginRight.value}px)`;
253
- }
216
+
217
+ const columnWidth = value.columns && value.columns > 1 ?
218
+ columnsWidth.value * value.columns - (value.columns - 1) * marginRight.value :
219
+ columnsWidth.value - marginRight.value;
220
+ model.value[key].formItem.style.width = `calc(${columnWidth}px)`;
254
221
  }
255
- }
222
+ };
256
223
 
257
224
  watch(() => model.value.form.columns, () => load());
258
225
  watch(() => model.value.form.inline, () => load());
259
226
 
260
- const removePx = (el) => parseFloat(el.replace("px", ""));
227
+ const columnsWidth = computed(() => convertToPx(model.value.form.style.width) / model.value.form.columns);
228
+ console.log(columnsWidth.value);
261
229
  //表单项
262
- const items = computed(() => Object.fromEntries(Object.entries(model.value).filter(a => a[1].type != "hidden")
230
+ const items = computed(() => Object.fromEntries(Object.entries(model.value)
231
+ .filter(a => a[1].type != "hidden")
263
232
  .filter(a => (a[1].edit !== false))
264
233
  .filter(a => (a[1].type !== "control"))
265
234
  .map(key => [key[0], key[1]])));
266
235
  //表单提交对象
267
- const formInfo = computed(() => Object.fromEntries(Object.entries(model.value).filter(a => a[1].type != "hidden").map(key => [key[0], key[1].value])));
268
- //表单列数
269
- const columns = computed(() => model.value.form.columns);
236
+ const formInfo = computed(() => Object.fromEntries(Object.entries(model.value)
237
+ .filter(a => a[1].type != "hidden")
238
+ .filter(a => a[1].type != "control")
239
+ .map(key => [key[0], key[1].value])));
240
+
270
241
  </script>
@@ -16,7 +16,7 @@
16
16
  <slot name="control-view" :row :column :$index
17
17
  v-if="model.control.view.auth(row, column, $index)">
18
18
  <el-button v-bind="model.control.view"
19
- @click="model.control.view.view(row, column, $index, model)">{{
19
+ @click="model.control.view.click(row, column, $index, model)">{{
20
20
  model.control.view.label
21
21
  }}</el-button>
22
22
  </slot>
@@ -24,7 +24,7 @@
24
24
  <slot name="control-edit" :row :column :$index
25
25
  v-if="model.control.edit.auth(row, column, $index)">
26
26
  <el-button v-bind="model.control.edit"
27
- @click="model.control.edit.edit(row, column, $index, model)">{{
27
+ @click="model.control.edit.click(row, column, $index, model)">{{
28
28
  model.control.edit.label
29
29
  }}</el-button>
30
30
  </slot>
@@ -32,7 +32,7 @@
32
32
  <slot name="control-delete" :row :column :$index
33
33
  v-if="model.control.delete.auth(row, column, $index)">
34
34
  <el-button v-bind="model.control.delete"
35
- @click="model.control.delete.delete(row, column, $index)">{{
35
+ @click="model.control.delete.click(row, column, $index)">{{
36
36
  model.control.delete.label }}</el-button>
37
37
  </slot>
38
38
  <slot name="control-right" :row :column :$index> </slot>
@@ -65,9 +65,9 @@
65
65
  <script setup>
66
66
  import dayjs from 'dayjs';
67
67
  import { ElMessageBox } from 'element-plus';
68
- import { computed, onMounted, reactive, watchEffect, h ,inject} from 'vue';
68
+ import { computed, onMounted, ref, watchEffect, h, inject } from 'vue';
69
69
  import GForm from './g-form.vue';
70
- import { openModal } from './index';
70
+ import { openModal, mergeObjects,convertToPx } from './index';
71
71
 
72
72
  defineOptions({
73
73
  name: "g-table",
@@ -79,7 +79,7 @@ const model = defineModel({ required: true });
79
79
  const options = inject('options');
80
80
 
81
81
  //table default attrs
82
- model.value.table = {
82
+ const defaultTableAttrs = {
83
83
  data: [],
84
84
  border: true,
85
85
  stripe: true,
@@ -87,8 +87,6 @@ model.value.table = {
87
87
  fit: false,
88
88
  type: "hidden",
89
89
  height: "calc(100vh - 55px)",
90
- ...options?.table,
91
- ...model.value.table,
92
90
  load: () => {
93
91
  let { currentPage, pageSize } = model.value.table.page;
94
92
  emits('load', { currentPage, pageSize }, (data, total) => {
@@ -97,112 +95,139 @@ model.value.table = {
97
95
  });
98
96
  },
99
97
  page: {
100
- background: true,
98
+ background: "red",
101
99
  total: 0,
102
100
  pageSize: 20,
103
101
  currentPage: 1,
104
102
  pageSizes: [5, 10, 20, 30, 40, 50],
105
103
  layout: 'total, sizes, prev, pager, next, jumper',
106
- ...options?.table?.page,
107
- ...model.value.table?.page,
108
104
  style: {
109
105
  display: 'flex',
110
106
  justifyContent: 'flex-end',
111
107
  padding: "10px",
112
- ...model.value.table?.page?.style
113
108
  },
114
109
  }
115
- }
110
+ };
111
+ model.value.table = mergeObjects(
112
+ defaultTableAttrs,
113
+ options?.table,
114
+ model.value.table
115
+ );
116
116
 
117
- model.value.form = {
118
- type: 'hidden',
119
- ...options?.form,
120
- ...model.value.form,
121
- dialog: {
122
- width: 635,
123
- ...model.value.form?.dialog,
124
- style: {
125
- ...model.value.form?.dialog?.style
126
- }
127
- }
128
- }
129
- model.value.control = {
130
- type: 'control', label: '操作', edit: false, width: 250, fixed: 'right',...options?.control, ...model.value?.control,
117
+ const defaultControl = {
118
+ type: 'control', label: '操作', edit: false, width: 250, fixed: 'right',
131
119
  style: { ...model.value?.control?.style },
120
+ add: {
121
+ label: '新增', text: false, type: 'primary',
122
+ dialog: {
123
+ title: '新增',
124
+ popMode: "dialog",
125
+ slots: {
126
+ default: () => h(GForm, { modelValue: model.value }),
127
+ },
128
+ },
129
+ auth: () => {
130
+ return true;
131
+ },
132
+ click: (row, column, $index, m) => {
133
+ model.value.form.disabled = undefined;
134
+ emits("add", row, column, $index, m);
135
+ Object.keys(row).forEach(key => {
136
+ if (model.value[key]) {
137
+ model.value[key].value = row[key];
138
+ }
139
+ });
140
+ openModal(model.value.control.add.dialog, model.value?.control?.add?.dialog?.popMode);
141
+ },
142
+ },
132
143
  view: {
133
144
  label: '查看', text: true, type: 'success',
145
+ dialog: {
146
+ title: '查看',
147
+ popMode: "dialog",
148
+ slots: {
149
+ default: () => h(GForm, { modelValue: model.value }),
150
+ },
151
+ },
134
152
  auth: (row, column, $index) => {
135
153
  return false;
136
154
  },
137
- view: (row, column, $index, m) => {
155
+ click: (row, column, $index, m) => {
156
+ let w = model.value?.form?.style?.width || 600;
157
+ if (model.value.control.view.dialog.popMode == "drawer") {
158
+ model.value.control.view.dialog.size = convertToPx(w) + 45;
159
+ } else {
160
+ model.value.control.view.dialog.width = convertToPx(w) + 35;
161
+ }
138
162
  model.value.form.disabled = true;
139
163
  emits("view", row, column, $index, m);
140
- model.value.form.dialog.width = +(model.value?.form?.style?.width?.replace("px", "")) + 35 || 635;
141
- openModal({
142
- title: '查看',
143
- width: model.value.form?.dialog?.width,
144
- ...model.value.form.dialog,
145
- slots: {
146
- // 自定义插槽内容
147
- default: () => h(GForm, { modelValue: model.value }),
148
- ...model.value?.form?.dialog?.slots
149
- },
164
+ Object.keys(row).forEach(key => {
165
+ if (model.value[key]) {
166
+ model.value[key].value = row[key];
167
+ }
150
168
  });
169
+ openModal(model.value.control.view.dialog, model.value?.control?.view?.dialog?.popMode);
151
170
  },
152
- ...options?.control?.view,
153
- ...model.value?.control?.view
154
171
  },
155
172
  edit: {
156
173
  label: '编辑', text: true, type: 'primary',
174
+ dialog: {
175
+ title: '编辑',
176
+ popMode: "dialog",
177
+ slots: {
178
+ default: () => h(GForm, { modelValue: model.value }),
179
+ },
180
+ },
157
181
  auth: (row, column, $index) => {
158
182
  return true;
159
183
  },
160
- edit: (row, column, $index, m) => {
184
+ click: (row, column, $index, m) => {
161
185
  model.value.form.disabled = undefined;
186
+ let w = model.value?.form?.style?.width || 600;
187
+ if (model.value.control.edit.dialog.popMode == "drawer") {
188
+ model.value.control.edit.dialog.size = convertToPx(w) + 45;
189
+ } else {
190
+ model.value.control.edit.dialog.width = convertToPx(w) + 35;
191
+ }
162
192
  emits("edit", row, column, $index, m);
163
- model.value.form.dialog.width = +(model.value?.form?.style?.width?.replace("px", "")) + 35 || 635;
164
- openModal({
165
- title: '编辑',
166
- width: model.value.form?.dialog?.width,
167
- ...model.value.form.dialog,
168
- slots: {
169
- // 自定义插槽内容
170
- default: () => h(GForm, { modelValue: model.value }),
171
- ...model.value?.form?.dialog?.slots
172
- },
193
+ Object.keys(row).forEach(key => {
194
+ if (model.value[key]) {
195
+ model.value[key].value = row[key];
196
+ }
173
197
  });
174
-
175
- },
176
- ...options?.control?.edit,
177
- ...model.value?.control?.edit
198
+ openModal(model.value?.control?.edit?.dialog, model.value?.control?.edit?.dialog?.popMode);
199
+ },
178
200
  },
179
201
  delete: {
180
202
  text: true, label: '删除', type: 'danger',
181
203
  auth: (row, column, $index) => {
182
204
  return true;
183
205
  },
184
- delete: (row, column, $index) => {
185
- ElMessageBox.confirm('此操作将永久删除该文件, 是否继续?', '提示', {
186
- confirmButtonText: '确定',
187
- cancelButtonText: '取消',
188
- type: 'warning'
189
- }).then(() => {
206
+ dialog: {
207
+ message: '此操作将永久删除该文件, 是否继续?', title: '提示', options: { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
208
+ },
209
+ click: (row, column, $index) => {
210
+ let { message, title, options } = model.value.control.delete.dialog;
211
+ ElMessageBox.confirm(message, title, options).then(() => {
190
212
  emits("delete", { row, column, $index }, (res) => {
191
213
  if (res) {
192
214
  model.value.table.data.splice($index, 1);
193
- console.log(model.value.table.data)
194
215
  }
195
216
  })
196
217
  }).catch(() => { });
197
218
 
198
- },
199
- ...options?.control?.delete,
200
- ...model.value?.control?.delete
219
+ },
201
220
  },
202
221
  };
203
222
 
223
+ model.value.control = mergeObjects(
224
+ defaultControl,
225
+ options?.control,
226
+ model.value?.control
227
+ );
228
+
204
229
  //table column default attrs
205
- const itemValue = reactive({
230
+ const itemValue = ref({
206
231
  width: 100, align: "center", formatter: (row, column, cellValue, index) => {
207
232
  return cellValue;
208
233
  }
@@ -260,7 +285,10 @@ const tableColumns = computed(() => Object.fromEntries(
260
285
  Object.entries(model.value)
261
286
  .filter(a => a[1].type != "hidden")
262
287
  .filter(a => a[1].visible !== false)
263
- .map(key => [key[0], key[1]]))
288
+ .map(key => {
289
+ key[1].sort = key[1].sort || 0;
290
+ return [key[0], key[1]]
291
+ }).sort((a, b) => a[1].sort - b[1].sort))
264
292
  );
265
293
  </script>
266
294
 
@@ -1,19 +1,34 @@
1
1
  import { App } from 'vue';
2
+ import { Component } from 'vue';
3
+ import { ElDialogProps, ElDrawerProps } from 'element-plus';
2
4
 
3
- interface ModalProps {
4
- slots: {
5
- header?: () => JSX.Element;
6
- default?: () => JSX.Element;
7
- footer?: () => JSX.Element;
8
- [key: string]: (() => JSX.Element) | undefined;
5
+ declare module 'vue' {
6
+ interface ComponentCustomProperties {
7
+ openModel: typeof openModal;
8
+ }
9
+ }
10
+
11
+ export interface GlobalOptions {
12
+ // 在这里定义全局选项的类型
13
+ }
14
+
15
+ export interface OpenModalProps {
16
+ slots?: {
17
+ default?: () => any;
18
+ header?: () => any;
19
+ footer?: () => any;
9
20
  };
10
- [key: string]: any;
21
+ // 在这里定义其他传递给openModal函数的属性
11
22
  }
12
23
 
13
- declare const _default: {
14
- install(app: App, options?: any): void;
15
- };
24
+ export function install(app: App, options?: GlobalOptions): void;
25
+ export function openModal(props?: OpenModalProps, popMode?: 'dialog' | 'drawer'): void;
26
+ export function convertToPx(value: string | number, referenceSize?: number): number;
27
+ export function mergeObjects<T extends object>(...objects: T[]): T;
16
28
 
17
- export default _default;
29
+ declare const components: {
30
+ gTable: Component;
31
+ gForm: Component;
32
+ };
18
33
 
19
- export declare const openModal: (props?: ModalProps, comType?: 'dialog' | 'drawer') => void;
34
+ export default components;
@@ -4,18 +4,25 @@ import ElementPlus from 'element-plus'
4
4
  import { ElDialog, ElDrawer } from "element-plus";
5
5
  import gTable from "./g-table.vue";
6
6
  import gForm from "./g-form.vue";
7
- import { createApp, h, provide, reactive, readonly, ref } from "vue";
8
- const goptions={};
7
+ import { createApp, h, provide, readonly, ref } from "vue";
8
+ const globalOptions = {};
9
+
10
+ const components = [
11
+ gTable,
12
+ gForm
13
+ ]
9
14
 
10
15
  export default {
11
16
  install(app, options = {}) {
12
- Object.assign(goptions, options);
13
- app.component("g-table", gTable);
14
- app.component("g-form", gForm);
17
+ Object.assign(globalOptions, options);
18
+ for (const component of components) {
19
+ app.component(component.name, component);
20
+ }
15
21
  app.provide("options", readonly(options));
22
+ app.config.globalProperties.openModel = openModal;
16
23
  }
17
24
  }
18
- const openModal = (props = {}, comType = "dialog") => {
25
+ const openModal = (props = {}, popMode = "dialog") => {
19
26
  const el = document.createElement('div');
20
27
  const app = createApp({
21
28
  setup() {
@@ -25,25 +32,95 @@ const openModal = (props = {}, comType = "dialog") => {
25
32
  app.unmount(); // 关闭对话框时卸载组件
26
33
  delete el.remove(); // 关闭对话框时删除元素
27
34
  };
28
- provide("options", goptions);
29
- return () => h(comType == "dialog" ? ElDialog : comType == "drawer" ? ElDrawer : null, {
35
+ provide("options", globalOptions);
36
+ return () => h(popMode == "dialog" ? ElDialog : popMode == "drawer" ? ElDrawer : null, {
30
37
  modelValue: visible.value,
31
38
  'onUpdate:modelValue': closeModal,
32
39
  draggable: true,
33
40
  "append-to-body": true,
34
- "v-if": visible.value,
35
41
  ...props
36
42
  },
37
- () => [
38
- props.slots.header ? h('div', { slot: 'header' }, props.slots.header()) : null,
39
- props.slots.default ? h(props.slots.default()) : null,
40
- props.slots.footer ? h('div', { slot: 'footer' }, props.slots.footer()) : null,
41
- ]
43
+ {
44
+ default: props.slots?.default ? () => h('div', {}, props.slots.default()) : null,
45
+ header: props.slots?.header ? () => h('div', {}, props.slots.header()) : null,
46
+ footer: props.slots?.footer ? () => h('div', {}, props.slots.footer()) : null
47
+ }
42
48
  );
43
49
  }
44
50
  });
51
+ for (const component of components) {
52
+ app.component(component.name, component);
53
+ }
45
54
  app.use(ElementPlus).mount(el);
46
55
  document.body.appendChild(el);
47
56
  };
48
57
 
49
- export { openModal };
58
+ function convertToPx(value, referenceSize = window.innerWidth) {
59
+ // 如果已经是px,直接返回
60
+ if (typeof value === 'number') {
61
+ return value;
62
+ }
63
+ if (value.endsWith('px')) {
64
+ return parseFloat(value);
65
+ }
66
+
67
+ // 处理vh和vw
68
+ const viewportHeight = window.innerHeight;
69
+ const viewportWidth = window.innerWidth;
70
+ if (value.endsWith('vh')) {
71
+ return (viewportHeight * parseFloat(value) / 100);
72
+ }
73
+ if (value.endsWith('vw')) {
74
+ return (viewportWidth * parseFloat(value) / 100);
75
+ }
76
+
77
+ // 处理%值,需要提供参考大小
78
+ if (value.endsWith('%')) {
79
+ if (typeof referenceSize !== 'number') {
80
+ throw new Error('Reference size is required to convert % to px');
81
+ }
82
+ return (referenceSize * parseFloat(value) / 100);
83
+ }
84
+
85
+ // 处理calc表达式
86
+ if (value.startsWith('calc(') && value.endsWith(')')) {
87
+ const calcExpr = value.slice(5, -1).trim();
88
+ // 使用一个安全的eval替代方案来解析calc表达式
89
+ function safeEval(expr) {
90
+ // 只允许数字、加减乘除运算符、小括号和空格
91
+ if (/[0-9+\-*/().\s]+$/.test(expr)) {
92
+ return new Function('return ' + expr)();
93
+ } else {
94
+ throw new Error('Invalid calc expression');
95
+ }
96
+ }
97
+ // 在这里,我们假设calc表达式中可能包含其他单位,因此递归调用parseValueToPx
98
+ const result = safeEval(calcExpr.replace(/([0-9.]+)([a-z%]+)/g, (match, number, unit) => {
99
+ return convertToPx(number + unit, referenceSize);
100
+ }));
101
+ return result;
102
+ }
103
+
104
+ // 如果无法识别单位,抛出错误
105
+ throw new Error('Unsupported unit in value: ' + value);
106
+ }
107
+
108
+
109
+ function mergeObjects(...objects) {
110
+ const result = ref({});
111
+ for (const obj of objects) {
112
+ if (obj && typeof obj === 'object') {
113
+ for (const key in obj) {
114
+ if (obj.hasOwnProperty(key)) {
115
+ if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
116
+ result.value[key] = mergeObjects(result.value[key], obj[key]);
117
+ } else {
118
+ result.value[key] = obj[key];
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
124
+ return result.value;
125
+ }
126
+ export { openModal, convertToPx, mergeObjects };