vue-2024-ui 0.0.5 → 0.0.7

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 ADDED
@@ -0,0 +1,283 @@
1
+ # form 表单 [表格](./README.table.md)
2
+
3
+ ## FORM API 文档说明
4
+
5
+ ### 所有属性和方法都在element-plus FORM 基础上扩展,只显示增加的属性和方法,安装前必须安装element-plus,其他原有属性和方法请查询 [官方文档](https://element-plus.org/zh-CN/component/form.html)
6
+
7
+ ## form 表单新增属性
8
+
9
+ | 属性 | 说明 | 类型 | 默认值 |
10
+ | --------- | ------------------------------------------------------------------- | ------ | -------------------------------------------------------------------------------------------- |
11
+ | columns | 表单列数 | number | 2 |
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: () => {...}, } ``` |
15
+ | formItems | 通过style属性设置所有items的样式 | object | ``` style:{width:100%} ``` |
16
+
17
+ ## form 增加的事件
18
+
19
+ | 事件名 | 说明 | 类型 | 参数 |
20
+ | ------ | ------------ | -------- | -------------------------------------------------------------------------------------- |
21
+ | submit | 表单提交事件 | function | formData:表单要提交的数据 |
22
+ | reset | 表单重置事件 | function | callback(isCustReset=false) 默认已处理了重置事件,如要重写事件则回调时传入true后再处理 |
23
+
24
+ ## form 重写 slots 增加的插槽
25
+
26
+ | 插槽名 | 说明 |
27
+ | ------------ | ---------------------- |
28
+ | footer | 重写表单footer功能按钮 |
29
+ | footer-left | 表单左边增加按钮 |
30
+ | footer-right | 表单右边增加按钮 |
31
+
32
+ ## formItem 重写 slots
33
+
34
+ | 插槽名 | 说明 |
35
+ | --------------------- | -------------------------------- |
36
+ | item.key | 重写表单项item |
37
+ | item.key-label | 重写表单项标题 |
38
+ | item.key-ctrl | 重写表单控件 |
39
+ | item.key-ctrl-options | 重写表单控件有options的字项items |
40
+
41
+ ## formItem 验证 validate
42
+
43
+ | 属性名 | 说明 | 类型 |
44
+ | -------- | ---------------------------------------------------- | -------- |
45
+ | required | 必输字段 | boolean |
46
+ | max,min | 字符串验证最大长度和最小长度,数字验证最大值和最小值 | number |
47
+ | type | number,email,url 验证数字,邮箱,网址 | string |
48
+ | pattern | 正则验证 | regex |
49
+ | validate | 自定义验证 validate(rule, value, callback) | function |
50
+
51
+ ## 示例
52
+
53
+ ### html
54
+
55
+ ``` html
56
+ <template>
57
+ <div>
58
+ <g-form v-model="formData">
59
+ <template #age-label="{ item, model, data }">
60
+ </template>
61
+ <template #age-ctrl-suffix> 岁 </template>
62
+ <template #birthday-ctrl-default="cell">
63
+ {{ cell.data.data.text + "-" }}
64
+ </template>
65
+ <template #email-ctrl-suffix="{ model }">
66
+ {{ model.email.label }}
67
+ </template>
68
+
69
+ <template #sex-ctrl="{ data }">
70
+ <el-radio-button :value="1">男</el-radio-button>
71
+ <el-radio-button :value="2">女</el-radio-button>
72
+ </template>
73
+ <template #isDisabled-ctrl="{ data }">
74
+ {{ data.data.value }}
75
+ </template>
76
+ <template #hobby-ctrl="{ data }">
77
+ <el-checkbox-button :value="1">画画</el-checkbox-button>
78
+ <el-checkbox-button :value="2">游戏</el-checkbox-button>
79
+ </template>
80
+ <template #switch-ctrl-active-action>
81
+ <span class="custom-active-action">T</span>
82
+ </template>
83
+ <template #switch-ctrl-inactive-action>
84
+ <span class="custom-inactive-action">F</span>
85
+ </template>
86
+ <template #select-ctrl-empty="{ data }">
87
+ <el-button type="primary" size="small">增加</el-button>
88
+ </template>
89
+ <template #select2-ctrl-options="{ data }">111 </template>
90
+ <template #select-ctrl-options="{ data }">
91
+ <el-option :label="data.option.label" :value="data.option.value">
92
+ <div style="display: flex;color:#666;border:1px solid #ccc;width:300px;align-items: center;padding:5px;">
93
+ <b>》》</b>
94
+ <span style="display: flex;align-items: center; padding:3px 10px;height: 100%;">{{
95
+ data.option.label
96
+ }}</span>
97
+ </div>
98
+ </el-option>
99
+ </template>
100
+ <template #autoComplete-ctrl-default="{ data }">
101
+ {{ data.data.item.value + '--' + data.data.item.label }}
102
+ </template>
103
+ <template #autoComplete-ctrl-suffix="{ data }">
104
+ auto
105
+ </template>
106
+ <template #autoComplete-ctrl-prefix="{ data }">
107
+ P
108
+ </template>
109
+ <template #transfer-ctrl-default="{ data }">
110
+ {{ data.data.option.label }}
111
+ </template>
112
+ <template #upload-ctrl-default="{ data }">
113
+ <el-button style="width:100px">+</el-button>
114
+ </template>
115
+ <template #footer-left>
116
+ <el-button plain type="info" @click="formData.form.inline = false; formData.form.columns = 1">inline</el-button>
117
+ <el-button plain type="info" @click="formData.form.inline = true; formData.form.columns = 1">一倍</el-button>
118
+ <el-button plain type="success" @click="formData.form.inline = true; formData.form.columns = 2">二倍</el-button>
119
+ </template>
120
+ <template #footer-right v-if="formData.form.columns !== 1">
121
+ <el-button plain type="warning" @click="formData.form.inline = true; formData.form.columns = 3">三倍</el-button>
122
+ <el-button plain type="danger" @click="formData.form.inline = true; formData.form.columns = 4">四倍</el-button>
123
+ </template>
124
+ </g-form>
125
+ </div>
126
+ </template>
127
+ ```
128
+
129
+ ### javascript
130
+
131
+ ``` javascript
132
+
133
+ <script setup>
134
+ import { ref ,reactive} from "vue";
135
+ const formData=reactive({
136
+ form:{
137
+ submit: { hidden: false },
138
+ reset: { hidden: false },
139
+ rules: {
140
+ "email.value": [{ required: true, message: "邮箱不能为空" }, { type: "email", message: "邮箱格式不正确" }],
141
+ "url.value": [{ required: true, message: "官网地址不能为空" }, { type: "url", message: "URL格式不正确" }],
142
+ },
143
+ columns: 2,
144
+ style: { boxShadow: null ,margin:"10px"},
145
+ },
146
+ id: { label: "ID", type: "number", value: 1, disabled: true, edit: false },
147
+ name: {
148
+ label: "姓名", value: "张三", width: 100,
149
+ max: 5,// min: 2,
150
+ //required: true,
151
+ rules: [{ required: true, message: "行内姓名不能为空!" }],
152
+ columns: 2, "show-word-limit": true,
153
+ formItem: { style: { border: "0px solid #fff", padding: "0px" } },
154
+ formatter: (row, column, cellValue, index) => row.name, sortable: true,
155
+ decimals: 2,
156
+ // suffix: " ¥", prefix: '--', width: 150
157
+ },
158
+ age: { label: "年龄", type: "number", value: 18, min: 16, decimals: { num: 0, pad: true }, suffix: '岁', sortable: true },
159
+ email: { label: "邮箱", type: "email", value: "xg816620@163.com", width: 400 },
160
+ qq: { label: "QQ", type: "number", value: 123456789, edit: false },
161
+ url: {
162
+ label: "官网地址", type: "url", columns: 2, value: "https://www.baidu.com", width: 260, align: 'left'
163
+ },
164
+ address: {
165
+ label: "地址", columns: 2, type: "textarea", maxlength: 50, width: 120, value: "重庆巴南万达广场B座22楼1-8", required: true, validate: (rule, value, callback) => {
166
+ if (value.length > 50) {
167
+ callback("字符串长度不能超过20个");
168
+ } else {
169
+ callback();
170
+ }
171
+ },
172
+ formItem: { "label-position": "right" }, suffix: '#'
173
+ },
174
+ sex: {
175
+ label: "性别", type: "radio", value: 2, options: [
176
+ { label: "男", value: 1, border: false },
177
+ { label: "女", value: 2, border: false }]
178
+ },
179
+ select: {
180
+ label: "选择分组", type: "select", value: 2, filterable: true, remote: true,
181
+ change: (a) => { console.log(a); },
182
+ "remote-method": (query, callback) => {
183
+ new Promise((resolve, reject) => {
184
+ setTimeout(() => {
185
+ resolve([
186
+ { label: "apple", value: 1 },
187
+ { label: "xiaomi", value: 2 },
188
+ { label: "huawei", value: 3 },
189
+ { label: "oppo", value: 4, disabled: "disabled" }
190
+ ].filter(a => a.label.includes(query)))
191
+ }, 1000);
192
+ }).then(a => {
193
+ callback(a)
194
+ })
195
+ },
196
+ options: [
197
+ {
198
+ label: "手机", options: [
199
+ { label: "apple", value: 1 },
200
+ { label: "xiaomi", value: 2 },
201
+ { label: "huawei", value: 3 }
202
+ ],
203
+ }, {
204
+ label: "电器", options: [
205
+ { label: "电视", value: 4 },
206
+ { label: "冰箱", value: 5 },
207
+ { label: "空调", value: 6 }
208
+ ],
209
+ },
210
+ ]
211
+ },
212
+ select2: {
213
+ label: "选择", type: "select", value: 3, visible: false,
214
+ options: [
215
+ { label: "apple", value: 1 },
216
+ { label: "xiaomi", value: 2 },
217
+ { label: "huawei", value: 3 }
218
+ ]
219
+ },
220
+ birthday: {
221
+ label: "生日", type: "datetime", value: "1985-01-01", dateFormat: "YYYY年MM月DD日", width: 200,
222
+ //prefix: '日期',
223
+ suffix: '@',
224
+ style: { width: "100%" },
225
+ },
226
+ hobby: {
227
+ label: "爱好", columns: 2, type: "checkbox-group", value: [1, 2], options: [
228
+ { label: "跑步", value: 1, border: false },
229
+ { label: "乒乓球", value: 2, border: false },
230
+ { label: "看书", value: 3, border: false },
231
+ { label: "学习", value: 4, border: false },],
232
+ },
233
+ time: {
234
+ label: "时间", type: "time", value: new Date(1985, 1, 1, 18, 20, 33), dateFormat: "time",
235
+ //prefix: '日期',
236
+ suffix: '@', width: 150,
237
+ style: { width: "100%" },
238
+ },
239
+ timeSelect: { label: "下拉时间", type: "time-select", value: "08:30", dateFormat: "mm:ss" },
240
+ isDisabled: { label: "是否启用", type: "checkbox", value: "是", trueValue: "是", formatter: (row, column, cellValue, index) => row.isDisabled == 2 ? '是' : '否' },
241
+ rate: { label: "星级", type: "rate", value: 3, suffix: '星级' },
242
+ slider: { label: "进度", type: "slider", value: 0.3, style: { width: "90%" }, visible: false, },
243
+ switch: {
244
+ label: "开关", type: "switch", value: 3, inlinePrompt: true, visible: false,
245
+ activeText: "完整展示多个内容",
246
+ inactiveText: "多个内容"
247
+ },
248
+ autoComplete: {
249
+ label: "建议输入", type: "autocomplete", value: "李四", visible: false, fetchSuggestions: (a, b) =>
250
+ b([{ value: "三四", label: 1 }, { value: "张三", label: 2 }, { value: "三德子", label: 3 }, { value: "李四", label: 4 }]
251
+ .filter((c) => c.value.toString().includes(a))), onSelect: (a) => console.log(a)
252
+ },
253
+ cascader: {
254
+ label: "级联选择", type: "cascader", value: [1, 2, 3], visible: false, options: [
255
+ { label: "父一", value: 1, children: [{ label: "父二", value: 2, children: [{ label: "父三", value: 3 }] }] },
256
+ { label: "父四", value: 4 },
257
+ { label: "父五", value: 5 },
258
+ ]
259
+ },
260
+ transfer: {
261
+ label: "穿梭框", type: "hidden", columns: 4, value: [1, 2], titles: ['全部', "已选"], visible: false,
262
+ filterable: true, data: [
263
+ { label: "选项一", key: 1 }, { label: "选项二", key: 2 }, { label: "选项三", key: 3 }, { label: "选项四", key: 4 },
264
+ { label: "选项五", key: 5 }, { label: "选项六", key: 6 }, { label: "选项七", key: 7 }, { label: "选项八", key: 8 },
265
+ ],
266
+
267
+ },
268
+ treeSelect: {
269
+ label: "树形选择", type: "tree-select", value: [1, 2, 3], visible: false,
270
+ "show-checkbox": true, data: [
271
+ {
272
+ label: "父一", value: 1, children: [
273
+ { label: "父二", value: 2, children: [{ label: "父三", value: 3 }] }]
274
+ },
275
+ { label: "父四", value: 4 },
276
+ { label: "父五", value: 5 },
277
+ ],
278
+ }
279
+ })
280
+
281
+ </script>
282
+
283
+ ```
package/README.md CHANGED
@@ -1,29 +1,231 @@
1
- # vue-ele-ui
1
+ # vue-2024-ui
2
2
 
3
- This template should help get you started developing with Vue 3 in Vite.
3
+ ## vue + element-plus
4
4
 
5
- ## Recommended IDE Setup
5
+ ## 安装
6
6
 
7
- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
7
+ ``` javascript
8
+ import { createApp } from 'vue'
9
+ import ElementPlus from 'element-plus'
10
+ import 'element-plus/dist/index.css'
11
+ import zhCn from 'element-plus/es/locale/lang/zh-cn'
12
+ import App from './App.vue'
13
+ import gyc from 'vue-2024-ui'
14
+ const app = createApp(App)
15
+ app.use(ElementPlus, {
16
+ locale: zhCn,
17
+ })
18
+ app.use(gyc)
19
+ app.mount('#app')
8
20
 
9
- ## Customize configuration
21
+ ```
22
+
23
+ [表单](./README.form.md) [表格](./README.table.md)
10
24
 
11
- See [Vite Configuration Reference](https://vitejs.dev/config/).
25
+ ## 快速上手
12
26
 
13
- ## Project Setup
27
+ ``` html
28
+ <template>
29
+ <div>
30
+ <g-table v-model="formData" @select-all="all" @load="load" @delete="del" @view="read">
31
+ </g-table>
32
+ </div>
33
+ </template>
14
34
 
15
- ```sh
16
- npm install
17
35
  ```
18
36
 
19
- ### Compile and Hot-Reload for Development
37
+ ``` javascript
38
+ <script setup>
39
+ import { reactive } from "vue";
40
+ const formData = reactive({
41
+ id: { label: "ID", type: "number", value: 1, disabled: true, edit: false },
42
+ name: {
43
+ label: "姓名", value: "张三", width: 100,
44
+ max: 5,// min: 2,
45
+ //required: true,
46
+ rules: [{ required: true, message: "行内姓名不能为空!" }],
47
+ columns: 2, "show-word-limit": true,
48
+ formItem: { style: { border: "0px solid #fff", padding: "0px" } },
49
+ formatter: (row, column, cellValue, index) => row.name, sortable: true,
50
+ decimals: 2,
51
+ // suffix: " ¥", prefix: '--', width: 150
52
+ },
53
+ age: { label: "年龄", type: "number", value: 18, min: 16, decimals: { num: 0, pad: true }, suffix: '岁', sortable: true },
54
+ email: { label: "邮箱", type: "email", value: "xg816620@163.com", width: 400 },
55
+ qq: { label: "QQ", type: "number", value: 123456789, edit: false },
56
+ url: {
57
+ label: "官网地址", type: "url", columns: 2, value: "https://www.baidu.com", width: 260, align: 'left'
58
+ },
59
+ address: {
60
+ label: "地址", columns: 2, type: "textarea", maxlength: 50, width: 120, value: "重庆巴南万达广场B座22楼1-8", required: true, validate: (rule, value, callback) => {
61
+ if (value.length > 50) {
62
+ callback("字符串长度不能超过20个");
63
+ } else {
64
+ callback();
65
+ }
66
+ },
67
+ formItem: { "label-position": "right" }, suffix: '#'
68
+ },
69
+ sex: {
70
+ label: "性别", type: "radio", value: 2, options: [
71
+ { label: "男", value: 1, border: false },
72
+ { label: "女", value: 2, border: false }]
73
+ },
74
+ select: {
75
+ label: "选择分组", type: "select", value: 2, filterable: true, remote: true,
76
+ change: (a) => { console.log(a); },
77
+ "remote-method": (query, callback) => {
78
+ new Promise((resolve, reject) => {
79
+ setTimeout(() => {
80
+ resolve([
81
+ { label: "apple", value: 1 },
82
+ { label: "xiaomi", value: 2 },
83
+ { label: "huawei", value: 3 },
84
+ { label: "oppo", value: 4, disabled: "disabled" }
85
+ ].filter(a => a.label.includes(query)))
86
+ }, 1000);
87
+ }).then(a => {
88
+ callback(a)
89
+ })
90
+ },
91
+ options: [
92
+ {
93
+ label: "手机", options: [
94
+ { label: "apple", value: 1 },
95
+ { label: "xiaomi", value: 2 },
96
+ { label: "huawei", value: 3 }
97
+ ],
98
+ }, {
99
+ label: "电器", options: [
100
+ { label: "电视", value: 4 },
101
+ { label: "冰箱", value: 5 },
102
+ { label: "空调", value: 6 }
103
+ ],
104
+ },
105
+ ]
106
+ },
107
+ select2: {
108
+ label: "选择", type: "select", value: 3, visible: false,
109
+ options: [
110
+ { label: "apple", value: 1 },
111
+ { label: "xiaomi", value: 2 },
112
+ { label: "huawei", value: 3 }
113
+ ]
114
+ },
115
+ birthday: {
116
+ label: "生日", type: "datetime", value: "1985-01-01", dateFormat: "YYYY年MM月DD日", width: 200,
117
+ //prefix: '日期',
118
+ suffix: '@',
119
+ style: { width: "100%" },
120
+ },
121
+ hobby: {
122
+ label: "爱好", columns: 2, type: "checkbox-group", value: [1, 2], options: [
123
+ { label: "跑步", value: 1, border: false },
124
+ { label: "乒乓球", value: 2, border: false },
125
+ { label: "看书", value: 3, border: false },
126
+ { label: "学习", value: 4, border: false },],
127
+ },
128
+ time: {
129
+ label: "时间", type: "time", value: new Date(1985, 1, 1, 18, 20, 33), dateFormat: "time",
130
+ //prefix: '日期',
131
+ suffix: '@', width: 150,
132
+ style: { width: "100%" },
133
+ },
134
+ timeSelect: { label: "下拉时间", type: "time-select", value: "08:30", dateFormat: "mm:ss" },
135
+ isDisabled: { label: "是否启用", type: "checkbox", value: "是", trueValue: "是", formatter: (row, column, cellValue, index) => row.isDisabled == 2 ? '是' : '否' },
136
+ rate: { label: "星级", type: "rate", value: 3, suffix: '星级' },
137
+ slider: { label: "进度", type: "slider", value: 0.3, style: { width: "90%" }, visible: false, },
138
+ switch: {
139
+ label: "开关", type: "switch", value: 3, inlinePrompt: true, visible: false,
140
+ activeText: "完整展示多个内容",
141
+ inactiveText: "多个内容"
142
+ },
143
+ autoComplete: {
144
+ label: "建议输入", type: "autocomplete", value: "李四", visible: false, fetchSuggestions: (a, b) =>
145
+ b([{ value: "三四", label: 1 }, { value: "张三", label: 2 }, { value: "三德子", label: 3 }, { value: "李四", label: 4 }]
146
+ .filter((c) => c.value.toString().includes(a))), onSelect: (a) => console.log(a)
147
+ },
148
+ cascader: {
149
+ label: "级联选择", type: "cascader", value: [1, 2, 3], visible: false, options: [
150
+ { label: "父一", value: 1, children: [{ label: "父二", value: 2, children: [{ label: "父三", value: 3 }] }] },
151
+ { label: "父四", value: 4 },
152
+ { label: "父五", value: 5 },
153
+ ]
154
+ },
155
+ transfer: {
156
+ label: "穿梭框", type: "hidden", columns: 4, value: [1, 2], titles: ['全部', "已选"], visible: false,
157
+ filterable: true, data: [
158
+ { label: "选项一", key: 1 }, { label: "选项二", key: 2 }, { label: "选项三", key: 3 }, { label: "选项四", key: 4 },
159
+ { label: "选项五", key: 5 }, { label: "选项六", key: 6 }, { label: "选项七", key: 7 }, { label: "选项八", key: 8 },
160
+ ],
161
+
162
+ },
163
+ treeSelect: {
164
+ label: "树形选择", type: "tree-select", value: [1, 2, 3], visible: false,
165
+ "show-checkbox": true, data: [
166
+ {
167
+ label: "父一", value: 1, children: [
168
+ { label: "父二", value: 2, children: [{ label: "父三", value: 3 }] }]
169
+ },
170
+ { label: "父四", value: 4 },
171
+ { label: "父五", value: 5 },
172
+ ],
173
+ },
174
+ upload: {
175
+ label: "上传", type: "upload", value: [], style: { width: "100%" }, visible: false,
176
+ action: "https://jsonplaceholder.typicode.com/posts/",
177
+ headers: { "Authorization": "Bearer " + "your-token" }
178
+ },
179
+ control:{
180
+ view:{
181
+ auth:()=>true
182
+ }
183
+ }
184
+ });
185
+
186
+ const createData = () => {
187
+ const list = [];
188
+ for (let i = 0; i < 210; i++) {
189
+ list.push({
190
+ id: i + 1,
191
+ name: `测试数据${i + 1}`,
192
+ age: Math.floor(Math.random() * 30) + 18,
193
+ email: `test${i + 1}@example.com`,
194
+ sex: (Math.floor(Math.random() * 2) + 1) == 2 ? '男' : '女',
195
+ select: 'xiaomi',
196
+ hobby: `测试数据${i + 1}`,
197
+ url: `https://www.example.com/test${i + 1}`,
198
+ birthday: new Date(2000, Math.floor(Math.random() * 12), Math.floor(Math.random() * 28) + 1),
199
+ address: `测试地址${i + 1}`,
200
+ rate: Math.floor(Math.random() * 5) + 1,
201
+ timeSelect: new Date(),
202
+ isDisabled: Math.floor(Math.random() * 2) + 1,
203
+ qq: "123"
204
+ });
205
+ }
206
+ return list;
207
+ };
208
+
209
+ const del = (row, back) => {
210
+ back(true)
211
+ }
212
+
213
+ const edit = (row, c, i, m) => {
214
+
215
+ }
216
+ const read = (row, c, i, m) => {
217
+ }
218
+ formData.table = {
219
+ border: undefined,
220
+ page: { pageSize: 10, style: { justifyContent: 'flex-end' }, onChange: (a, b) => console.log(a, b) }
221
+ }
222
+ const all = (d) => console.log(d);
223
+ const load = (d, callback) => {
224
+ const { pageSize, currentPage } = d;
225
+ callback(createData().filter((item, index) => index >= (currentPage - 1) * pageSize && index < currentPage * pageSize), createData().length);
226
+ }
20
227
 
21
- ```sh
22
- npm run dev
23
- ```
24
228
 
25
- ### Compile and Minify for Production
229
+ </script>
26
230
 
27
- ```sh
28
- npm run build
29
231
  ```
@@ -0,0 +1,58 @@
1
+ # table 表格
2
+ [表单](./README.form.md)
3
+
4
+
5
+ # API 说明
6
+ ### 所有属性和方法都在element-plus 基础上扩展,只显示增加的属性和方法,安装前必须安装element-plus,其他原有属性和方法请查询 [官方文档](https://element-plus.org/zh-CN/component/table.html)
7
+
8
+ # table 表格新增属性
9
+
10
+ | 属性 | 说明 | 类型 | 默认值 |
11
+ | --------- | ------------------------------------------------------------------- | ------ | -------------------------------------------------------------------------------------------- |
12
+ | columns | 表单列数 | number | 2 |
13
+ | footer | 控制表单底部按钮是否显示和样式设置,hidden默认是false,style控制样式 | object | ```{hidden: false, style:{ display:"flex","align-items":"center",justifyContent:"center"}``` |
14
+ | submit | 表单提交按钮,增加了submitText,hidden 属性和submit方法 | object | ``` {type: "primary",submitText: "提交",hidden: false,submit: async (model) => {...}, } ``` |
15
+ | reset | 表单重置按钮,增加了restText,hidden 属性和reset方法 | object | ``` {type: "primary",resetText: "重置",hidden: false,reset: () => {...}, } ``` |
16
+ | formItems | 通过style属性设置所有items的样式 | object | ``` style:{width:100%} ``` |
17
+
18
+
19
+ # table 增加的事件
20
+
21
+ | 事件名 | 说明 | 类型 | 参数 |
22
+ | ------ | ------------ | -------- | -------------------------------------------------------------------------------------- |
23
+ | submit | 表单提交事件 | function | formData:表单要提交的数据 |
24
+ | reset | 表单重置事件 | function | callback(isCustReset=false) 默认已处理了重置事件,如要重写事件则回调时传入true后再处理 |
25
+
26
+
27
+
28
+ # table 重写 slots 增加的插槽
29
+
30
+ | 插槽名 | 说明 |
31
+ | ------------ | ---------------------- |
32
+ | footer | 重写表单footer功能按钮 |
33
+ | footer-left | 表单左边增加按钮 |
34
+ | footer-right | 表单右边增加按钮 |
35
+
36
+ # tablecolumn 重写 slots
37
+
38
+ | 插槽名 | 说明 |
39
+ | --------------------- | -------------------------------- |
40
+ | item.key | 重写表单项item |
41
+ | item.key-label | 重写表单项标题 |
42
+ | item.key-ctrl | 重写表单控件 |
43
+ | item.key-ctrl-options | 重写表单控件有options的字项items |
44
+
45
+ # 示例
46
+ ### html
47
+ ```
48
+ <template>
49
+
50
+ </template>
51
+ ```
52
+ ### javascript
53
+ ```
54
+ <script setup>
55
+
56
+ </script>
57
+ ```
58
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-2024-ui",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "src/components/index.js",
@@ -36,7 +36,7 @@
36
36
  </template>
37
37
 
38
38
  <script setup>
39
- import { computed, onMounted, ref, useAttrs, watch } from "vue";
39
+ import { computed, inject, onMounted, ref, useAttrs, watch } from "vue";
40
40
  import gCtrl from "./g-ctrl.vue";
41
41
  defineOptions({
42
42
  name: "g-form",
@@ -47,6 +47,7 @@ const emits = defineEmits(["submit", "reset"]);
47
47
  const gform = ref(null);
48
48
  const columnsWidth = ref(0);
49
49
  let marginRight = ref(32);
50
+ const options=inject('options');
50
51
  //合并表单默认属性
51
52
  model.value.form = {
52
53
  inline: true,
@@ -56,6 +57,7 @@ model.value.form = {
56
57
  "status-icon": true,
57
58
  "scroll-into-view-options": true,
58
59
  columns: 2,
60
+ ...options?.form,
59
61
  ...model.value.form,
60
62
  style: {
61
63
  width: "600px",
@@ -65,15 +67,19 @@ model.value.form = {
65
67
  paddingTop: "20px",
66
68
  margin: "0px",
67
69
  boxShadow: "0 0 5px rgba(0, 0, 0, 0.1)",
70
+ ...options?.form?.style,
68
71
  ...model.value.form?.style,
69
72
  ...useAttrs().style
70
73
  },
71
74
  // 表单底部属性
72
75
  footer: {
73
76
  hidden: false,
77
+ ...options?.form?.footer,
74
78
  ...model.value.form?.footer,
75
79
  style: {
76
- display: "flex", width: "100%", "align-items": "center", justifyContent: "center", margin: "5px", ...model.value.form?.footer?.style
80
+ display: "flex", width: "100%", "align-items": "center", justifyContent: "center", margin: "5px",
81
+ ...options?.form?.footer?.style,
82
+ ...model.value.form?.footer?.style
77
83
  },
78
84
  },
79
85
  //表单提交按钮属性
@@ -83,8 +89,8 @@ model.value.form = {
83
89
  submitText: "提交",
84
90
  plain: true,
85
91
  hidden: false,
92
+ ...options?.form?.submit,
86
93
  submit: async (model) => {
87
- console.log(model);
88
94
  if (!gform.value) return
89
95
  await gform.value.validate((valid, fields) => {
90
96
  if (valid) {
@@ -112,10 +118,12 @@ model.value.form = {
112
118
  gform.value.resetFields();
113
119
  }
114
120
  },
121
+ ...options?.form?.reset,
115
122
  ...model.value.form?.reset
116
123
  },
117
124
  dialog: {
118
125
  width: 635,
126
+ ...options?.form?.dialog,
119
127
  ...model.value.form?.dialog
120
128
  }
121
129
  };
@@ -124,6 +132,7 @@ model.value.formItems = {
124
132
  type: "hidden",
125
133
  style: {
126
134
  width: "100%",
135
+ ...options?.formItems?.style,
127
136
  ...model.value.formItems?.style
128
137
  },
129
138
  ...model.value.formItems,
@@ -228,8 +237,7 @@ const load = () => {
228
237
  else {
229
238
  model.value.form.style.width = "600px";
230
239
  }
231
- model.value.form.dialog.width = +model.value?.form?.style?.width.replace("px", "")+35+"px";
232
- console.log(model.value.form.dialog.width);
240
+ model.value.form.dialog.width = +model.value?.form?.style?.width.replace("px", "") + 35 + "px";
233
241
  for (const [key, value] of Object.entries(items.value)) {
234
242
  model.value[key].formItem = { ...model.value[key].formItem, ...value.formItem }
235
243
  model.value[key].formItem.style = { ...model.value[key].formItem.style, ...value.formItem.style };
@@ -64,12 +64,10 @@
64
64
 
65
65
  <script setup>
66
66
  import dayjs from 'dayjs';
67
- import ElementPlus from 'element-plus'
68
67
  import { ElMessageBox } from 'element-plus';
69
- import { computed, onMounted, reactive, watchEffect, watch, h, createApp, ref } from 'vue';
70
- import { ElDialog } from 'element-plus';
71
- //import gyc from "./index"
68
+ import { computed, onMounted, reactive, watchEffect, h ,inject} from 'vue';
72
69
  import GForm from './g-form.vue';
70
+ import { openModal } from './index';
73
71
 
74
72
  defineOptions({
75
73
  name: "g-table",
@@ -78,6 +76,7 @@ defineOptions({
78
76
 
79
77
  const emits = defineEmits(['load', 'view', "edit", "delete"]);
80
78
  const model = defineModel({ required: true });
79
+ const options = inject('options');
81
80
 
82
81
  //table default attrs
83
82
  model.value.table = {
@@ -88,6 +87,7 @@ model.value.table = {
88
87
  fit: false,
89
88
  type: "hidden",
90
89
  height: "calc(100vh - 55px)",
90
+ ...options?.table,
91
91
  ...model.value.table,
92
92
  load: () => {
93
93
  let { currentPage, pageSize } = model.value.table.page;
@@ -103,6 +103,7 @@ model.value.table = {
103
103
  currentPage: 1,
104
104
  pageSizes: [5, 10, 20, 30, 40, 50],
105
105
  layout: 'total, sizes, prev, pager, next, jumper',
106
+ ...options?.table?.page,
106
107
  ...model.value.table?.page,
107
108
  style: {
108
109
  display: 'flex',
@@ -112,8 +113,21 @@ model.value.table = {
112
113
  },
113
114
  }
114
115
  }
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
+ }
115
129
  model.value.control = {
116
- type: model.value?.control ? "control" : 'hidden', label: '操作', edit: false, width: 250, fixed: 'right', ...model.value?.control,
130
+ type: 'control', label: '操作', edit: false, width: 250, fixed: 'right',...options?.control, ...model.value?.control,
117
131
  style: { ...model.value?.control?.style },
118
132
  view: {
119
133
  label: '查看', text: true, type: 'success',
@@ -123,8 +137,10 @@ model.value.control = {
123
137
  view: (row, column, $index, m) => {
124
138
  model.value.form.disabled = true;
125
139
  emits("view", row, column, $index, m);
140
+ model.value.form.dialog.width = +(model.value?.form?.style?.width?.replace("px", "")) + 35 || 635;
126
141
  openModal({
127
142
  title: '查看',
143
+ width: model.value.form?.dialog?.width,
128
144
  ...model.value.form.dialog,
129
145
  slots: {
130
146
  // 自定义插槽内容
@@ -132,7 +148,9 @@ model.value.control = {
132
148
  ...model.value?.form?.dialog?.slots
133
149
  },
134
150
  });
135
- }, ...model.value?.control?.view
151
+ },
152
+ ...options?.control?.view,
153
+ ...model.value?.control?.view
136
154
  },
137
155
  edit: {
138
156
  label: '编辑', text: true, type: 'primary',
@@ -142,8 +160,10 @@ model.value.control = {
142
160
  edit: (row, column, $index, m) => {
143
161
  model.value.form.disabled = undefined;
144
162
  emits("edit", row, column, $index, m);
163
+ model.value.form.dialog.width = +(model.value?.form?.style?.width?.replace("px", "")) + 35 || 635;
145
164
  openModal({
146
165
  title: '编辑',
166
+ width: model.value.form?.dialog?.width,
147
167
  ...model.value.form.dialog,
148
168
  slots: {
149
169
  // 自定义插槽内容
@@ -152,7 +172,9 @@ model.value.control = {
152
172
  },
153
173
  });
154
174
 
155
- }, ...model.value?.control?.edit
175
+ },
176
+ ...options?.control?.edit,
177
+ ...model.value?.control?.edit
156
178
  },
157
179
  delete: {
158
180
  text: true, label: '删除', type: 'danger',
@@ -173,7 +195,9 @@ model.value.control = {
173
195
  })
174
196
  }).catch(() => { });
175
197
 
176
- }, ...model.value?.control?.delete
198
+ },
199
+ ...options?.control?.delete,
200
+ ...model.value?.control?.delete
177
201
  },
178
202
  };
179
203
 
@@ -184,41 +208,6 @@ const itemValue = reactive({
184
208
  }
185
209
  });
186
210
 
187
- // 用 createApp 方法封装打开模态窗的方法
188
- const openModal = (props = {}) => {
189
- const el = document.createElement('div');
190
- const app = createApp({
191
- setup() {
192
- const visible = ref(true);
193
- const closeModal = () => {
194
- visible.value = false;
195
- app.unmount(); // 关闭对话框时卸载组件
196
- delete el.remove(); // 关闭对话框时删除元素
197
- };
198
- return () => h(ElDialog, {
199
- modelValue: visible.value,
200
- 'onUpdate:modelValue': closeModal,
201
- draggable: true,
202
- "append-to-body": true,
203
- "v-if": visible.value,
204
- width:model.value.form.dialog.width,
205
- ...props
206
- },
207
- () => [
208
- props.slots.header ? h('div', { slot: 'header' }, props.slots.header()) : null,
209
- // 传递名为 'default' 的插槽
210
- props.slots.default ? h(props.slots.default()) : null,
211
- // 传递名为 'footer' 的插槽
212
- props.slots.footer ? h('div', { slot: 'footer' }, props.slots.footer()) : null,
213
- // 可以继续添加其他插槽...
214
- ]
215
- );
216
- }
217
- });
218
- app.use(ElementPlus).mount(el);
219
- document.body.appendChild(el);
220
- };
221
-
222
211
  //扩展formatter方法
223
212
  const formatterExtends = (item, str) => {
224
213
  let trueValue = str;
@@ -0,0 +1,19 @@
1
+ import { App } from 'vue';
2
+
3
+ interface ModalProps {
4
+ slots: {
5
+ header?: () => JSX.Element;
6
+ default?: () => JSX.Element;
7
+ footer?: () => JSX.Element;
8
+ [key: string]: (() => JSX.Element) | undefined;
9
+ };
10
+ [key: string]: any;
11
+ }
12
+
13
+ declare const _default: {
14
+ install(app: App, options?: any): void;
15
+ };
16
+
17
+ export default _default;
18
+
19
+ export declare const openModal: (props?: ModalProps, comType?: 'dialog' | 'drawer') => void;
@@ -1,10 +1,49 @@
1
+
2
+
3
+ import ElementPlus from 'element-plus'
4
+ import { ElDialog, ElDrawer } from "element-plus";
1
5
  import gTable from "./g-table.vue";
2
6
  import gForm from "./g-form.vue";
3
-
7
+ import { createApp, h, provide, reactive, readonly, ref } from "vue";
8
+ const goptions={};
4
9
 
5
10
  export default {
6
- install(app, options) {
11
+ install(app, options = {}) {
12
+ Object.assign(goptions, options);
7
13
  app.component("g-table", gTable);
8
14
  app.component("g-form", gForm);
15
+ app.provide("options", readonly(options));
9
16
  }
10
17
  }
18
+ const openModal = (props = {}, comType = "dialog") => {
19
+ const el = document.createElement('div');
20
+ const app = createApp({
21
+ setup() {
22
+ const visible = ref(true);
23
+ const closeModal = () => {
24
+ visible.value = false;
25
+ app.unmount(); // 关闭对话框时卸载组件
26
+ delete el.remove(); // 关闭对话框时删除元素
27
+ };
28
+ provide("options", goptions);
29
+ return () => h(comType == "dialog" ? ElDialog : comType == "drawer" ? ElDrawer : null, {
30
+ modelValue: visible.value,
31
+ 'onUpdate:modelValue': closeModal,
32
+ draggable: true,
33
+ "append-to-body": true,
34
+ "v-if": visible.value,
35
+ ...props
36
+ },
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
+ ]
42
+ );
43
+ }
44
+ });
45
+ app.use(ElementPlus).mount(el);
46
+ document.body.appendChild(el);
47
+ };
48
+
49
+ export { openModal };