vue-2024-ui 0.0.1

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.md ADDED
@@ -0,0 +1,29 @@
1
+ # vue-ele-ui
2
+
3
+ This template should help get you started developing with Vue 3 in Vite.
4
+
5
+ ## Recommended IDE Setup
6
+
7
+ [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).
8
+
9
+ ## Customize configuration
10
+
11
+ See [Vite Configuration Reference](https://vitejs.dev/config/).
12
+
13
+ ## Project Setup
14
+
15
+ ```sh
16
+ npm install
17
+ ```
18
+
19
+ ### Compile and Hot-Reload for Development
20
+
21
+ ```sh
22
+ npm run dev
23
+ ```
24
+
25
+ ### Compile and Minify for Production
26
+
27
+ ```sh
28
+ npm run build
29
+ ```
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "vue-2024-ui",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "type": "module",
6
+ "main": "src/components/index.js",
7
+ "author": {
8
+ "name": "guoyuanchao",
9
+ "email": "xg816620@163.com"
10
+ },
11
+ "files": [
12
+ "src/components"
13
+ ],
14
+ "scripts": {
15
+ "dev": "vite",
16
+ "build": "vite build",
17
+ "preview": "vite preview"
18
+ },
19
+ "dependencies": {
20
+ "element-plus": "^2.8.4",
21
+ "vue": "^3.4.29"
22
+ },
23
+ "license": "MIT",
24
+ "devDependencies": {
25
+ "@vitejs/plugin-vue": "^5.0.5",
26
+ "@vitejs/plugin-vue-jsx": "^4.0.0",
27
+ "vite": "^5.3.1",
28
+ "vite-plugin-vue-devtools": "^7.3.1"
29
+ }
30
+ }
@@ -0,0 +1,168 @@
1
+ <template>
2
+ <div style="display: flex; width: 100%;" class="g-ctrl-container">
3
+ <!--radio-->
4
+ <el-radio-group v-model="ctrlValue" v-bind="itemInfo" v-if="ctrlType == 'radio'">
5
+ <slot :name="`${ctrlKey}-ctrl`" :data="itemInfo">
6
+ <el-radio v-bind="option" v-for="option in itemInfo.options">
7
+ <slot :name="`${ctrlKey}-ctrl-options`" :option></slot>
8
+ </el-radio>
9
+ </slot>
10
+ </el-radio-group>
11
+ <!--radio-button-->
12
+ <el-radio-group v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'radio-button'">
13
+ <slot :name="`${ctrlKey}-ctrl`" :data="itemInfo">
14
+ <el-radio-button v-bind="option" v-for="option in itemInfo.options">
15
+ <slot :name="`${ctrlKey}-ctrl-options`" :option></slot>
16
+ </el-radio-button>
17
+ </slot>
18
+ </el-radio-group>
19
+ <!--checkbox-->
20
+ <el-checkbox v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'checkbox'">
21
+ <slot :name="`${ctrlKey}-ctrl`" :data="itemInfo">{{ " " }}</slot>
22
+ </el-checkbox>
23
+ <!--checkbox-group-->
24
+ <el-checkbox-group v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'checkbox-group'">
25
+ <slot :name="`${ctrlKey}-ctrl`" :data="itemInfo">
26
+ <el-checkbox v-bind="option" v-for="option in itemInfo.options">
27
+ <slot :name="`${ctrlKey}-ctrl-options`" :option>{{ option.label }}</slot>
28
+ </el-checkbox>
29
+ </slot>
30
+ </el-checkbox-group>
31
+ <!--checkbox-group-button-->
32
+ <el-checkbox-group v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'checkbox-group-button'">
33
+ <slot :name="`${ctrlKey}-ctrl`" :data="itemInfo">
34
+ <el-checkbox-button v-bind="option" v-for="option in itemInfo.options">
35
+ <slot :name="`${ctrlKey}-ctrl-options`" :option></slot>
36
+ </el-checkbox-button>
37
+ </slot>
38
+ </el-checkbox-group>
39
+ <!--select-->
40
+ <el-select v-model="ctrlValue" v-bind="selectModel" v-else-if="ctrlType == 'select'">
41
+ <template #default v-if="itemInfo?.options?.some(a => a.options)">
42
+ <slot :name="`${ctrlKey}-ctrl`" :options="itemInfo.options">
43
+ <el-option-group v-for="group in itemInfo.options" :label="group.label">
44
+ <el-option v-bind="option" v-for="option in group.options"
45
+ @click.native="selectModel.change && selectModel.change(option)">
46
+ <slot :name="`${ctrlKey}-ctrl-options`" :option></slot>
47
+ </el-option>
48
+ </el-option-group>
49
+ </slot>
50
+ </template>
51
+ <template #default v-else>
52
+ <slot :name="`${ctrlKey}-ctrl`" :options="itemInfo.options">
53
+ <el-option v-bind="option" v-for="option in itemInfo.options"
54
+ @click.native="selectModel.change && selectModel.change(option)">
55
+ <slot :name="`${ctrlKey}-ctrl-options`" :option></slot>
56
+ </el-option>
57
+ </slot>
58
+ </template>
59
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
60
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
61
+ </template>
62
+ </el-select>
63
+ <!--tree-select-->
64
+ <el-tree-select v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'tree-select'">
65
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
66
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
67
+ </template>
68
+ </el-tree-select>
69
+ <!--time-->
70
+ <el-time-picker v-model="ctrlValue" arrow-control v-bind="itemInfo" v-else-if="ctrlType == 'time'" />
71
+ <!--time-select-->
72
+ <el-time-select v-model="ctrlValue" start="06:30" step="00:15" end="23:30" v-bind="itemInfo"
73
+ v-else-if="ctrlType == 'time-select'" />
74
+ <!--date-->
75
+ <el-date-picker v-model="ctrlValue" type="date" v-bind="itemInfo" v-else-if="ctrlType == 'date'">
76
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
77
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
78
+ </template>
79
+ </el-date-picker>
80
+ <!--datetime-->
81
+ <el-date-picker v-model="ctrlValue" type="datetime" v-bind="itemInfo" v-else-if="ctrlType == 'datetime'">
82
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
83
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
84
+ </template>
85
+ </el-date-picker>
86
+ <!--color-->
87
+ <el-color-picker v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'color'" />
88
+ <!--rate-->
89
+ <el-rate v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'rate'" />
90
+ <!--slider-->
91
+ <el-slider v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'slider'" />
92
+ <!--switch-->
93
+ <el-switch v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'switch'">
94
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
95
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
96
+ </template>
97
+ </el-switch>
98
+ <!--transfer-->
99
+ <el-transfer v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'transfer'">
100
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
101
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
102
+ </template>
103
+ </el-transfer>
104
+ <!--cascader-->
105
+ <el-cascader v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'cascader'">
106
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
107
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
108
+ </template>
109
+ </el-cascader>
110
+ <!--upload-->
111
+ <el-upload v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'upload'">
112
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
113
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
114
+ </template>
115
+ </el-upload>
116
+ <!--autocomplete-->
117
+ <el-autocomplete v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'autocomplete'">
118
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
119
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
120
+ </template>
121
+ </el-autocomplete>
122
+ <!--input-number-->
123
+ <el-input-number v-model="ctrlValue" :min="0" :max="100000000" v-bind="itemInfo"
124
+ v-else-if="ctrlType == 'input-number'">
125
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
126
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
127
+ </template>
128
+ </el-input-number>
129
+ <!--input-->
130
+ <el-input v-model="ctrlValue" show-word-limit :maxlength="itemInfo.max || 25" :clearable="true"
131
+ v-bind="itemInfo" v-else>
132
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
133
+ <slot :name="`${ctrlKey}-ctrl-${slot}`" :data></slot>
134
+ </template>
135
+ </el-input>
136
+ </div>
137
+ </template>
138
+
139
+ <script setup>
140
+ defineOptions({ inheritAttrs: false });
141
+ import { onMounted, useAttrs, useSlots } from "vue";
142
+ const ctrlValue = defineModel({ required: true });
143
+ const itemInfo = useAttrs().item;
144
+ const ctrlKey = useAttrs().ctrlKey;
145
+ const ctrlType = itemInfo.type;
146
+ const model = useAttrs().model;
147
+ const slots = () => Object.keys(useSlots()).filter(a => a.startsWith(ctrlKey)).filter(a => a.includes('-ctrl-')).map(a => a.split("-ctrl-")[1]);
148
+
149
+ //select 默认属性
150
+ const selectModel = {
151
+ ...{
152
+ filterable: true,
153
+ remote: itemInfo["remote-method"] ? true : false,
154
+ }, ...itemInfo
155
+ };
156
+ const selectRemoteMethod = (query) => {
157
+ itemInfo["remote-method"](query, (a) => {
158
+ model[ctrlKey].options = a;
159
+ })
160
+ }
161
+
162
+ onMounted(() => {
163
+ if (itemInfo["remote-method"]) {
164
+ selectModel['remote-method'] = selectRemoteMethod;
165
+
166
+ }
167
+ })
168
+ </script>
@@ -0,0 +1,266 @@
1
+ <template>
2
+ <el-form ref="gform" :model="model" v-bind="model.form" class="g-form-container">
3
+ <slot>
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 }">
7
+ <slot :name="key" :item :model>
8
+ <g-ctrl v-model="model[key].value" :item :ctrlKey="key" :model class="g-ctrl-container">
9
+ <template v-for="(slot, slotKey, index) in $slots" :key="index" #[slotKey]="data">
10
+ <slot :name="slotKey" :data :item :model></slot>
11
+ </template>
12
+ </g-ctrl>
13
+ </slot>
14
+ <template #label="data">
15
+ <slot :name="`${key}-label`" :data :item :model>{{ item.label }}</slot>
16
+ </template>
17
+ </el-form-item>
18
+ <el-form-item style="width: 100%;">
19
+ <slot name="footer">
20
+ <div style="display: flex; width:100%;align-items: center;" :style="model.form.footer">
21
+ <slot name="footer-left"></slot>
22
+ <el-button @click="submitForm(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="resetForm(ruleFormRef)" 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>
34
+ </slot>
35
+ </el-form>
36
+ </template>
37
+
38
+ <script setup>
39
+ import { computed, onMounted, ref, useAttrs, watch } from "vue";
40
+ import gCtrl from "./g-ctrl.vue";
41
+ defineOptions({
42
+ name: "g-form",
43
+ inheritAttrs: false
44
+ })
45
+ const model = defineModel({ required: true });
46
+ const emits = defineEmits(["submit", "reset"]);
47
+ const gform = ref(null);
48
+ const columnsWidth = ref(0);
49
+ let marginRight = ref(32);
50
+ //合并表单默认属性
51
+ model.value.form = {
52
+ inline: true,
53
+ type: "hidden",
54
+ "scroll-to-error": true,
55
+ "label-width": "100px",
56
+ "status-icon": true,
57
+ "scroll-into-view-options": true,
58
+ columns: 2,
59
+ ...model.value.form,
60
+ style: {
61
+ width: "600px",
62
+ border: "1px solid rgba(0, 0, 0,0.09)",
63
+ borderRadius: "10px",
64
+ padding: "0px",
65
+ paddingTop: "20px",
66
+ margin: "0px",
67
+ boxShadow: "0 0 5px rgba(0, 0, 0, 0.1)",
68
+ ...model.value.form?.style,
69
+ ...useAttrs().style
70
+ },
71
+ // 表单底部属性
72
+ footer: {
73
+ justifyContent: "center",
74
+ ...model.value.form?.footer
75
+ },
76
+ //表单提交按钮属性
77
+ submit: {
78
+ type: "primary",
79
+ disabled: false,
80
+ submitText: "提交",
81
+ plain: true,
82
+ hidden: false,
83
+ ...model.value.form?.submit
84
+ },
85
+ //表单重置按钮属性
86
+ reset: {
87
+ disabled: false,
88
+ resetText: "重置",
89
+ hidden: false,
90
+ plain: true,
91
+ ...model.value.form?.reset
92
+ },
93
+ };
94
+ //合并表单项默认属性
95
+ model.value.formItems = {
96
+ type: "hidden",
97
+ ...model.value.formItems,
98
+ style: {
99
+ width: "100%",
100
+ ...model.value.formItems?.style
101
+ }
102
+ };
103
+
104
+ // 提交表单
105
+ const submitForm = async (model) => {
106
+ if (!gform.value) return
107
+ await gform.value.validate((valid, fields) => {
108
+ if (valid) {
109
+ emits("submit", formInfo.value, model);
110
+ } else {
111
+ console.log('error submit!', fields);
112
+ }
113
+ })
114
+ }
115
+
116
+ // 重置表单
117
+ const resetForm = () => {
118
+ if (!gform.value) return
119
+ const isreset = true;
120
+ emits("reset", (flag) => {
121
+ isreset = flag;
122
+ });
123
+ if (isreset) {
124
+ gform.value.resetFields();
125
+ }
126
+ }
127
+
128
+ // 定义对外暴露的函数
129
+ defineExpose({
130
+ submit: submitForm, reset: resetForm
131
+ })
132
+
133
+ //获取表单项验证规则
134
+ const getItemRulesByItem = (item) => {
135
+ // 组装验证规则
136
+ let itemRules = [];
137
+ if (item.rules) {
138
+ itemRules = item.rules;
139
+ } else {
140
+ //默认验证规则
141
+ const itemDefaultRule = {
142
+ required: undefined,
143
+ max: undefined,
144
+ min: undefined,
145
+ email: undefined,
146
+ url: undefined,
147
+ pattern: undefined,
148
+ validate: undefined
149
+ }
150
+ // 获取item属性并合并规则
151
+ const itemInfo = { ...itemDefaultRule, ...item };
152
+
153
+ //必填验证
154
+ if (itemInfo.required) {
155
+ itemRules.push({ required: true, message: `${itemInfo.label}不能为空!`, trigger: 'blur' });
156
+ }
157
+ // 数字范围验证 和 字符串长度验证
158
+ if (itemInfo.max && itemInfo.min) {
159
+ itemRules.push({
160
+ validator: (rule, value, callback) => {
161
+ if (value && item.type == "number" && (value < itemInfo.min || value > itemInfo.max)) {
162
+ callback(new Error(`${itemInfo.label} 必须在 ${itemInfo.min} 和 ${itemInfo.max} 之间!`));
163
+ } else if (value && item.type !== "number" && (value.toString().length < itemInfo.min || value.toString().length > itemInfo.max)) {
164
+ callback(new Error(`字符长度必须在 ${itemInfo.min} 和 ${itemInfo.max} 之间!`));
165
+ } else {
166
+ callback();
167
+ }
168
+ }
169
+ });
170
+ }
171
+
172
+ //验证数字不能大于一个值
173
+ if (itemInfo.max && !itemInfo.min && item.type == "number") {
174
+ itemRules.push({
175
+ validator: (rule, value, callback) => {
176
+ if (value && (value > itemInfo.max)) {
177
+ callback(new Error(`${itemInfo.label}不能大于${itemInfo.max}!`));
178
+ } else {
179
+ callback();
180
+ }
181
+ }
182
+ });
183
+ }
184
+ //验证数字不能小于一个值
185
+ if (itemInfo.min && !itemInfo.max && item.type == "number") {
186
+ itemRules.push({
187
+ validator: (rule, value, callback) => {
188
+ if (value && (value < itemInfo.min)) {
189
+ callback(new Error(`${itemInfo.label}不能小于${itemInfo.min}!`));
190
+ } else {
191
+ callback();
192
+ }
193
+ }
194
+ });
195
+ }
196
+ //验证邮箱格式
197
+ if (itemInfo.type == "email") {
198
+ itemRules.push({ type: "email", message: "不是一个正确的邮箱地址!" });
199
+ }
200
+ //验证URL格式
201
+ if (itemInfo.type == "url") {
202
+ itemRules.push({ type: "url", message: "不是一个合正确的URL!" });
203
+ }
204
+ // 正则验证
205
+ if (itemInfo.pattern) {
206
+ itemRules.push({ pattern: itemInfo?.pattern, message: itemInfo?.message || "格式不正确!" });
207
+ }
208
+ // 自定义验证规则
209
+ if (itemInfo.validate) {
210
+ itemRules.push({
211
+ validator: (rule, value, callback) => itemInfo.validate(rule, value, callback)
212
+ });
213
+ }
214
+ }
215
+ return itemRules;
216
+ }
217
+
218
+ onMounted(() => {
219
+ load();
220
+ })
221
+
222
+ const load = () => {
223
+ if (!model.value.form.inline) {
224
+ model.value.form.columns = 1;
225
+ }
226
+ const width = getComputedStyle(document.querySelector(".g-form-container")).width;
227
+ console.log(width);
228
+ if (width === "600px") {
229
+ columnsWidth.value = 300;
230
+ model.value.form.style.width = columns.value * 300 + 'px';
231
+ } else {
232
+ columnsWidth.value = removePx(width) / model.value.form.columns;
233
+ model.value.form.style.width = columns.value * columnsWidth.value + 'px';
234
+ }
235
+ for (const [key, value] of Object.entries(items.value)) {
236
+ model.value[key].formItem = { ...model.value[key].formItem, ...value.formItem }
237
+ model.value[key].formItem.style = { ...model.value[key].formItem.style, ...value.formItem.style };
238
+ if (value.columns && value.columns > 1) {
239
+ if (model.value.form.inline) {
240
+ let column = columnsWidth.value * value.columns - (value.columns - 1) * marginRight.value;
241
+ model.value[key].formItem.style.width = `calc(${column}px)`;
242
+ } else {
243
+ model.value[key].formItem.style.width = `calc(${columnsWidth.value - marginRight.value}px)`;
244
+ }
245
+ } else {
246
+ model.value[key].formItem.style.width = `calc(${columnsWidth.value - marginRight.value}px)`;
247
+ }
248
+ }
249
+ }
250
+
251
+ watch(() => model.value.form.columns, () => load());
252
+ watch(() => model.value.form.inline, () => load());
253
+
254
+ const removePx = (el) => parseFloat(el.replace("px", ""));
255
+
256
+ //表单项
257
+ const items = computed(() => Object.fromEntries(Object.entries(model.value).filter(a => a[1].type != "hidden").filter(a => (a[1].edit !== false)).map(key => [key[0], key[1]])));
258
+ //表单提交对象
259
+ const formInfo = computed(() => Object.fromEntries(Object.entries(model.value).filter(a => a[1].type != "hidden").map(key => [key[0], key[1].value])));
260
+ //表单列数
261
+ const columns = computed(() => model.value.form.columns);
262
+ //表单列的宽度减去右边距
263
+ const formItemsWidth = computed(() => columnsWidth.value - marginRight.value);
264
+ //表单宽度
265
+ const formWidth = computed(() => columns.value * columnsWidth.value);
266
+ </script>
@@ -0,0 +1,143 @@
1
+ <template>
2
+ <el-table class="g-table-container" v-bind="{ ...$attrs, ...model.table }">
3
+ <slot>
4
+ <el-table-column :prop="key" v-for="(value, key) of tableColumns" :key="key"
5
+ v-bind="{ ...itemValue, ...value }" header-align="center">
6
+ <template #default="{ row, column, $index }"
7
+ v-if="value.type != 'selection' && value.type != 'index' && value.type != 'expand'">
8
+ <slot :name="`${key}`" :row :column :$index>
9
+ <div v-html="formatterExtends(value, column.formatter(row, column, row[key], $index))"></div>
10
+ </slot>
11
+ </template>
12
+ <template #header="{ column, $index }">
13
+ <slot :name="`${key}-header`" :column :$index></slot>
14
+ </template>
15
+ <template #filter-icon="data">
16
+ <slot :name="`${key}-filter-icon`" :data></slot>
17
+ </template>
18
+ </el-table-column>
19
+ </slot>
20
+ <template #append>
21
+ <slot name="append"></slot>
22
+ </template>
23
+ <template #empty>
24
+ <slot name="empty"></slot>
25
+ </template>
26
+ </el-table>
27
+ <slot name="page">
28
+ <el-pagination v-model:page-size="model.table.page.pageSize" v-model:current-page="model.table.page.currentPage"
29
+ v-bind="model.table.page">
30
+ <slot name="table-page"></slot>
31
+ </el-pagination>
32
+ </slot>
33
+ </template>
34
+
35
+ <script setup>
36
+ import dayjs from 'dayjs';
37
+ import { computed, onMounted, reactive, watchEffect } from 'vue';
38
+
39
+ defineOptions({
40
+ name: "g-table",
41
+ inheritAttrs: false
42
+ })
43
+
44
+ const emits = defineEmits(['load']);
45
+
46
+ const model = defineModel({ required: true });
47
+
48
+ //table default attrs
49
+ model.value.table = {
50
+ data: [],
51
+ border: true,
52
+ stripe: true,
53
+ emptyText: '暂无数据',
54
+ fit: false,
55
+ type: "hidden",
56
+ height: "calc(100vh - 55px)",
57
+
58
+ ...model.value.table,
59
+ load: () => {
60
+ let { currentPage, pageSize } = model.value.table.page;
61
+ emits('load', { currentPage, pageSize }, (data) => {
62
+ model.value.table.data = data;
63
+ });
64
+ },
65
+ page: {
66
+ background: true,
67
+ total: 0,
68
+ pageSize: 10,
69
+ currentPage: 1,
70
+ pageSizes: [5, 10, 20, 30, 40, 50],
71
+ layout: 'total, sizes, prev, pager, next, jumper',
72
+ ...model.value.table.page,
73
+ style: {
74
+ display: 'flex',
75
+ justifyContent: 'flex-end',
76
+ padding: "10px",
77
+ ...model.value.table?.page?.style
78
+ },
79
+ onChange: (a, b) => {
80
+ console.log(a, b);
81
+ }
82
+ }
83
+ }
84
+
85
+ //table column default attrs
86
+ const itemValue = reactive({
87
+ width: 100, align: "center", formatter: (row, column, cellValue, index) => {
88
+ return cellValue;
89
+ }
90
+ });
91
+
92
+ //扩展formatter方法
93
+ const formatterExtends = (item, str) => {
94
+ let trueValue = str;
95
+ if (item.decimals && !isNaN(str)) {
96
+ if (typeof item.decimals == 'number') {
97
+ trueValue = parseFloat(trueValue).toFixed(item.decimals);
98
+ }
99
+ else if (typeof item.decimals == 'object') {
100
+ if (item.decimals.num) {
101
+ if (item.decimals.pad) {
102
+ trueValue = parseFloat(trueValue).toFixed(item.decimals.num);
103
+ } else {
104
+ trueValue = parseFloat(parseFloat(trueValue).toFixed(item.decimals.num));
105
+ }
106
+ }
107
+ }
108
+ }
109
+ if (item.dateFormat && dayjs(str).isValid()) {
110
+ if (item.dateFormat == 'date') {
111
+ trueValue = dayjs(trueValue).format('YYYY-MM-DD');
112
+ } else if (item.dateFormat == 'time') {
113
+ trueValue = dayjs(trueValue).format('HH:mm:ss');
114
+ }
115
+ else if (item.dateFormat == 'datetime') {
116
+ trueValue = dayjs(trueValue).format('YYYY-MM-DD HH:mm:ss');
117
+ }
118
+ else {
119
+ trueValue = dayjs(trueValue).format(item.dateFormat)
120
+ }
121
+ }
122
+ if (item.prefix && trueValue) {
123
+ trueValue = `<span>${item.prefix}${trueValue}</span>`;
124
+ }
125
+ if (item.suffix && trueValue) {
126
+ trueValue += `<span>${item.suffix}</span>`
127
+ }
128
+ return trueValue
129
+ }
130
+ onMounted(() => {
131
+
132
+ });
133
+
134
+ watchEffect(() => {
135
+ model.value.table.load();
136
+ });
137
+
138
+ //表单项
139
+ const tableColumns = computed(() => Object.fromEntries(Object.entries(model.value).filter(a => a[1].type != "hidden").filter(a => a[1].visible !== false).map(key => [key[0], key[1]])));
140
+ //const formInfo = computed(() => Object.fromEntries(Object.entries(model.value).filter(a => a[1].type != "hidden").map(key => [key[0], key[1].value])));
141
+ </script>
142
+
143
+ <style lang="scss" scoped></style>
@@ -0,0 +1,10 @@
1
+ import gTable from "./g-table.vue";
2
+ import gForm from "./g-form.vue";
3
+
4
+
5
+ export default {
6
+ install(app, options) {
7
+ app.component("g-table", gTable);
8
+ app.component("g-form", gForm);
9
+ }
10
+ }