vue-2024-ui 0.0.24 → 0.0.26

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,24 +1,16 @@
1
1
  {
2
2
  "name": "vue-2024-ui",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "private": false,
5
5
  "type": "module",
6
- "main": "./dist/vue-2024-ui.cjs",
7
- "module": "./dist/vue-2024-ui.min.js",
8
- "types": "./dist/types/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/types/index.d.ts",
12
- "import": "./dist/vue-2024-ui.esm.js",
13
- "require": "./dist/vue-2024-ui.cjs"
14
- }
15
- },
6
+ "main": "./src/components/index.js",
7
+ "types": "./dist/types/index.d.ts",
16
8
  "author": {
17
9
  "name": "guoyuanchao",
18
10
  "email": "xg816620@163.com"
19
11
  },
20
12
  "files": [
21
- "dist",
13
+ "./src/components",
22
14
  "README.md"
23
15
  ],
24
16
  "scripts": {
@@ -34,18 +26,18 @@
34
26
  "sortablejs": "^1.15.6"
35
27
  },
36
28
  "peerDependencies": {
37
- "vue": "^3.4.29",
38
- "element-plus": "^2.8.4"
29
+ "element-plus": "^2.8.4",
30
+ "vue": "^3.4.29"
39
31
  },
40
32
  "license": "MIT",
41
33
  "devDependencies": {
34
+ "@rollup/plugin-commonjs": "^25.0.7",
42
35
  "@vitejs/plugin-vue": "^5.0.5",
43
36
  "@vitejs/plugin-vue-jsx": "^4.0.0",
44
- "vite": "^5.3.1",
45
- "vite-plugin-vue-devtools": "^7.3.1",
46
- "@rollup/plugin-commonjs": "^25.0.7",
47
- "rollup-plugin-visualizer": "^5.10.0",
48
37
  "@vue/compiler-sfc": "^3.4.29",
49
- "terser": "^5.27.0"
38
+ "rollup-plugin-visualizer": "^5.10.0",
39
+ "terser": "^5.27.0",
40
+ "vite": "^5.3.1",
41
+ "vite-plugin-vue-devtools": "^7.3.1"
50
42
  }
51
- }
43
+ }
@@ -0,0 +1,105 @@
1
+ <template>
2
+ <div style="padding:0;margin: 0;box-sizing: border-box;">
3
+ <div style="padding: 10px;box-sizing: border-box;">
4
+ <div style="margin: 10px">
5
+ <a @click="selectAll">全选</a>
6
+ <el-divider direction="vertical"></el-divider>
7
+ <a @click="clearAll">全不选</a>
8
+ </div>
9
+ <el-alert title="拖动列标题可以改变表格列的生成顺序 !" type="warning" show-icon :closable="false"
10
+ style="margin-bottom: 10px">
11
+ </el-alert>
12
+ <div style="margin: 1px 0;"></div>
13
+ <div style="display: flex;">
14
+ <el-checkbox-group id="excelSortEl" v-model="checkList" @change="handleCheckedCitiesChange" style="display: flex;flex-wrap: wrap;margin:0 !important;padding:0 !important;
15
+ ">
16
+ <el-checkbox class="check-box-hover"
17
+ style=" width: 120px !important; height: 30px !important; border: 1px solid #dfe6ec; margin: 5px !important; border-radius: 3px !important; padding-left: 5px !important; display:flex !important; align-items: center !important;"
18
+ :data-id="index" v-for="(item, index) in excelItems" :value="item.value" :key="'el-i-' + index"
19
+ :title="item.label">
20
+ <span v-text="item.label"
21
+ style="display: block; text-overflow: ellipsis;width:95px;overflow: hidden;"></span>
22
+ </el-checkbox>
23
+ </el-checkbox-group>
24
+ </div>
25
+ </div>
26
+ <div
27
+ style="width:100%;display: flex;padding: 10px; box-sizing:border-box; justify-content: center;border-top: 1px solid #dcdfe6;">
28
+ <el-button type="primary" @click="createExcel" :disabled="checkList.length <= 0">
29
+ <a href="" :download="returnUrl" style="text-decoration: none;"> {{ props.commitText }}</a>
30
+ </el-button>
31
+ </div>
32
+ </div>
33
+ </template>
34
+
35
+ <script setup>
36
+ import { ref, onMounted, onBeforeUnmount } from 'vue';
37
+ import Sortable from "sortablejs";
38
+
39
+ const props = defineProps({
40
+ items: Array,
41
+ commitText: String
42
+ });
43
+
44
+ const emits = defineEmits(['save']);
45
+ // 定义响应式数据
46
+ const checkAll = ref(false);
47
+ const checkList = ref([]);
48
+ const excelItems = ref(props.items);
49
+ const isIndeterminate = ref(true);
50
+ const afterDragData = ref([]);
51
+ const returnUrl= ref('');
52
+
53
+ // 定义方法
54
+ const createExcel = () => {
55
+ let arr = [];
56
+ (afterDragData.value.length === 0 ? excelItems.value : afterDragData.value).forEach(element => {
57
+ if (checkList.value.includes(element)) {
58
+ arr.push(element);
59
+ }
60
+ });
61
+ emits('save', arr);
62
+ console.log(arr);
63
+ };
64
+
65
+ const handleCheckAllChange = (val) => {
66
+ checkList.value = val ? props.items : [];
67
+ isIndeterminate.value = false;
68
+ };
69
+
70
+ const handleCheckedCitiesChange = (value) => {
71
+ let checkedCount = value.length;
72
+ checkAll.value = checkedCount === excelItems.value.length;
73
+ isIndeterminate.value = checkedCount > 0 && checkedCount < excelItems.value.length;
74
+ };
75
+
76
+ // 生命周期钩子
77
+ onMounted(() => {
78
+ checkAll.value = true;
79
+ isIndeterminate.value = false;
80
+ checkList.value = props.items || [];
81
+ const sortable = new Sortable(document.getElementById('excelSortEl'), {
82
+ animation: 150,
83
+ onEnd: () => {
84
+ afterDragData.value = [];
85
+ let indexArr = sortable.toArray();
86
+ console.log(indexArr);
87
+ indexArr.forEach(element => {
88
+ afterDragData.value.push(excelItems.value[parseInt(element)]);
89
+ });
90
+ },
91
+ });
92
+ // 保存 sortable 实例以便在组件销毁时销毁它
93
+ const sortableInstance = sortable;
94
+ onBeforeUnmount(() => {
95
+ if (sortableInstance) {
96
+ sortableInstance.destroy();
97
+ }
98
+ });
99
+ });
100
+ </script>
101
+ <style scoped>
102
+ .check-box-hover:hover {
103
+ background: #f5f1f1;
104
+ }
105
+ </style>
@@ -0,0 +1,168 @@
1
+ <template>
2
+ <div>
3
+ <div style="margin: 10px" class="allcheck">
4
+ <a @click="selectAll">全选</a>
5
+ <el-divider direction="vertical"></el-divider>
6
+ <a @click="clearAll">全不选</a>
7
+ <el-divider direction="vertical"></el-divider>
8
+ <a @click="rowReset">复位</a>
9
+ </div>
10
+ <el-alert title="拖动表格列标题可以改变表格列显示顺序 !" type="warning" show-icon :closable="false" style="margin-bottom: 10px">
11
+ </el-alert>
12
+ <div>
13
+ <div id="cols" style="display: flex;flex-wrap: wrap;margin:0 !important;padding:0 !important; ">
14
+ <el-checkbox v-model="check.showCol" :data-id="check.value" class="check-box-hover"
15
+ :class="check.value == 'control' ? 'filtered' : ''" @change="(v) => change(v, check.value)" style=" width: 125px !important; height: 30px !important; border: 1px solid #dfe6ec; margin: 5px !important; border-radius: 2px !important;
16
+ padding-left: 5px !important; display: flex !important; align-items: center !important;" :value="check.value"
17
+ :title="check.label" :disabled="check.alwaysShow" v-for="(check) in cols" :key="check.value">
18
+ <span v-text="check.label"
19
+ style="display: block; text-overflow: ellipsis;width:95px;overflow: hidden;"></span>
20
+ </el-checkbox>
21
+ </div>
22
+ </div>
23
+
24
+ </div>
25
+ </template>
26
+
27
+ <script setup>
28
+ import { ref, onMounted } from 'vue';
29
+ import Sortable from "sortablejs";
30
+ import { deleteTableInfo, saveTableInfo } from './db';
31
+ import { ElMessage, ElMessageBox } from 'element-plus';
32
+ // 定义 props
33
+ const props = defineProps({
34
+ name: {
35
+ type: String,
36
+ required: true,
37
+ },
38
+ });
39
+
40
+ const cols = ref([]);
41
+ // 定义响应式数据
42
+ const arrKeys = defineModel({ required: true });
43
+
44
+ const change = async (val, key) => {
45
+ if (val) {
46
+ arrKeys.value[key].showCol = true;
47
+ } else {
48
+ arrKeys.value[key].showCol = false;
49
+ }
50
+ saveTableInfo(arrKeys.value.table.user, props.name, key, { showCol: val }).then((res) => {
51
+ console.log(res);
52
+ })
53
+ }
54
+
55
+ // 拖拽列
56
+ const rowDrop = () => {
57
+ const c = document.getElementById("cols");
58
+ if (c) {
59
+ let arr = Sortable.create(c, {
60
+ animation: 150,
61
+ filter: '.filtered', //
62
+ sort: true,
63
+ onEnd: () => {
64
+ let indexArr = arr.toArray();
65
+ indexArr.forEach((element, index) => {
66
+ arrKeys.value[element].sort = index;
67
+ let w = arrKeys.value[element].width || "auto";
68
+ saveTableInfo(arrKeys.value.table.user, props.name, element, { sort: index, width: w }).then((res) => {
69
+ console.log(res);
70
+ })
71
+ })
72
+ },
73
+ });
74
+ }
75
+ };
76
+
77
+
78
+ // 全选列
79
+ const selectAll = async () => {
80
+ try {
81
+ for (const element of cols.value) {
82
+ element.showCol = true;
83
+ arrKeys.value[element.value].showCol = true;
84
+ const res = await saveTableInfo(arrKeys.value.table.user, props.name, element.value, {
85
+ showCol: true, width: element.width, sort: element.sort
86
+ });
87
+ console.log(res);
88
+ }
89
+ } catch (error) {
90
+ console.error('全选列保存信息时出错:', error);
91
+ ElMessage({
92
+ type: 'error',
93
+ message: '全选列保存信息失败!',
94
+ });
95
+ }
96
+ };
97
+
98
+ // 清除列
99
+ const clearAll = async () => {
100
+ try {
101
+ const filteredCols = cols.value.filter(a => !a.alwaysShow);
102
+ for (const element of filteredCols) {
103
+ element.showCol = false;
104
+ arrKeys.value[element.value].showCol = false;
105
+ const res = await saveTableInfo(arrKeys.value.table.user, props.name, element.value, {
106
+ showCol: false, width: element.width, sort: element.sort
107
+ });
108
+ console.log(res);
109
+ }
110
+ } catch (error) {
111
+ console.error('清除列保存信息时出错:', error);
112
+ ElMessage({
113
+ type: 'error',
114
+ message: '清除列保存信息失败!',
115
+ });
116
+ }
117
+ };
118
+ // 复位
119
+ const rowReset = () => {
120
+ ElMessageBox.confirm('确定要复位吗?', '提示', {
121
+ confirmButtonText: '确定',
122
+ cancelButtonText: '取消',
123
+ type: 'warning',
124
+ }).then(() => {
125
+ deleteTableInfo(arrKeys.value.table.user, props.name).then((res) => {
126
+ console.log(res);
127
+ window.location.reload();
128
+ }).catch(() => {
129
+ ElMessage({
130
+ type: 'info',
131
+ message: '复位失败!',
132
+ });
133
+ })
134
+ })
135
+ };
136
+ onMounted(async () => {
137
+ cols.value = Object.entries(arrKeys.value)
138
+ .filter(([key, value]) => value.visible !== false)
139
+ .filter(([key, value]) => value.type != "hidden").map(([key, value]) => {
140
+ return {
141
+ label: value.label,
142
+ value: key,
143
+ alwaysShow: value.alwaysShow,
144
+ showCol: value.showCol === false ? false : true,
145
+ sort: value.sort || 0,
146
+ width: value.width || "auto",
147
+ };
148
+ }).sort((a, b) => a.sort - b.sort);
149
+ rowDrop();
150
+
151
+
152
+
153
+ });
154
+ </script>
155
+
156
+ <style scoped>
157
+ .check-box-hover:hover {
158
+ background: #f5f1f1;
159
+ }
160
+
161
+ .allcheck a {
162
+ cursor: pointer;
163
+ }
164
+
165
+ .filtered {
166
+ pointer-events: none;
167
+ }
168
+ </style>
@@ -0,0 +1,39 @@
1
+ // db.js
2
+ import {Dexie} from 'dexie';
3
+
4
+ const db = new Dexie('gyc');
5
+ //删除数据库
6
+ //db.delete();
7
+ db.version(1).stores({
8
+ tableInfo: '++id,user,page,key,showCol,width,sort',
9
+ tableList: "++id,name"
10
+ });
11
+
12
+ export async function saveTableInfo(user, page, key, options = {}) {
13
+ let count = await db.tableInfo.where({ user, page, key }).count();
14
+ if (count > 0) {
15
+ let m = await db.tableInfo.where({ user, page, key }).first();
16
+ await db.tableInfo.put({ ...m, ...options });
17
+ return 'update success'
18
+ } else {
19
+ let d = { showCol: true, width: 'auto', sort: 0, ...options }
20
+ await db.tableInfo.add({ user, page, key, ...d });
21
+ return 'add success'
22
+ }
23
+ }
24
+
25
+ export async function getTableInfo(user, page) {
26
+ return await db.tableInfo.where({ user, page }).toArray();
27
+ }
28
+
29
+ export async function deleteTableInfo(user, page) {
30
+ db.tableInfo.where({ user, page }).delete((deleteCount) => {
31
+ console.log("删除了" + deleteCount + "条数据");
32
+ });
33
+ }
34
+
35
+ export async function existsTableName(page) {
36
+ let count = await db.tableInfo.where({ page }).count();
37
+ return count > 0;
38
+ }
39
+
@@ -0,0 +1,231 @@
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="`${props.t}-${ctrlKey}`" :data="itemInfo">
6
+ <el-radio v-bind="option" v-for="option in model[ctrlKey].options">
7
+ <slot :name="`${props.t}-${ctrlKey}-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="`${props.t}-${ctrlKey}`" :data="itemInfo">
14
+ <el-radio-button v-bind="option" v-for="option in model[ctrlKey].options">
15
+ <slot :name="`${props.t}-${ctrlKey}-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="`${props.t}-${ctrlKey}`" :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="`${props.t}-${ctrlKey}`" :data="itemInfo">
26
+ <el-checkbox v-bind="option" v-for="option in model[ctrlKey].options">
27
+ <slot :name="`${props.t}-${ctrlKey}-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="`${props.t}-${ctrlKey}`" :data="itemInfo">
34
+ <el-checkbox-button v-bind="option" v-for="option in model[ctrlKey].options">
35
+ <slot :name="`${props.t}-${ctrlKey}-options`" :option></slot>
36
+ </el-checkbox-button>
37
+ </slot>
38
+ </el-checkbox-group>
39
+ <!--select-->
40
+ <el-select v-model="ctrlValue" :placeholder="model[ctrlKey].label" v-bind="selectModel"
41
+ v-else-if="ctrlType === 'select'">
42
+ <template #default>
43
+ <slot :name="`${props.t}-${ctrlKey}`" :options="model[ctrlKey].options">
44
+ <!-- 根据是否存在子选项渲染不同结构 -->
45
+ <template v-if="model[ctrlKey]?.options?.some(a => a.options)">
46
+ <el-option-group v-for="group in model[ctrlKey].options" :key="group.label"
47
+ :label="group.label">
48
+ <el-option v-bind="option" v-for="option in group.options" :key="option.value"
49
+ @click.native="selectModel.change && selectModel.change(option)">
50
+ <slot :name="`${props.t}-${ctrlKey}-options`" :option></slot>
51
+ </el-option>
52
+ </el-option-group>
53
+ </template>
54
+ <template v-else>
55
+ <el-option v-bind="option" v-for="option in model[ctrlKey].options" :key="option.value"
56
+ @click.native="selectModel.change && selectModel.change(option)">
57
+ <slot :name="`${props.t}-${ctrlKey}-options`" :option></slot>
58
+ </el-option>
59
+ </template>
60
+ </slot>
61
+ </template>
62
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
63
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
64
+ </template>
65
+ </el-select>
66
+ <!--tree-select-->
67
+ <el-tree-select v-model="ctrlValue" :placeholder="model[ctrlKey].label" v-bind="itemInfo" :data="treeSelectData"
68
+ v-else-if="ctrlType == 'tree-select'">
69
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
70
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
71
+ </template>
72
+ </el-tree-select>
73
+ <!--time-->
74
+ <el-time-picker v-model="ctrlValue" arrow-control v-bind="itemInfo" :placeholder="model[ctrlKey].label"
75
+ v-else-if="ctrlType == 'time'" />
76
+ <!--time-select-->
77
+ <el-time-select v-model="ctrlValue" start="06:30" step="00:15" end="23:30" :placeholder="model[ctrlKey].label"
78
+ v-bind="itemInfo" v-else-if="ctrlType == 'time-select'" />
79
+ <!--date-->
80
+ <el-date-picker v-model="ctrlValue" type="date" :placeholder="model[ctrlKey].label" v-bind="itemInfo"
81
+ v-else-if="ctrlType == 'date'">
82
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
83
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
84
+ </template>
85
+ </el-date-picker>
86
+ <!--datetime-->
87
+ <el-date-picker v-model="ctrlValue" type="datetime" :placeholder="model[ctrlKey].label" v-bind="itemInfo"
88
+ v-else-if="ctrlType == 'datetime'">
89
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
90
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
91
+ </template>
92
+ </el-date-picker>
93
+ <!--color-->
94
+ <el-color-picker v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'color'" />
95
+ <!--rate-->
96
+ <el-rate v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'rate'" />
97
+ <!--slider-->
98
+ <el-slider v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'slider'" />
99
+ <!--switch-->
100
+ <el-switch v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'switch'">
101
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
102
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
103
+ </template>
104
+ </el-switch>
105
+ <!--transfer-->
106
+ <el-transfer v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'transfer'">
107
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
108
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
109
+ </template>
110
+ </el-transfer>
111
+ <!--cascader-->
112
+ <el-cascader v-model="ctrlValue" v-bind="itemInfo" :options="model[ctrlKey].options"
113
+ v-else-if="ctrlType == 'cascader'">
114
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
115
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
116
+ </template>
117
+ </el-cascader>
118
+ <!--upload-->
119
+ <el-upload v-model="ctrlValue" v-bind="itemInfo" v-else-if="ctrlType == 'upload'">
120
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
121
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
122
+ </template>
123
+ </el-upload>
124
+ <!--autocomplete-->
125
+ <el-autocomplete v-model="ctrlValue" v-bind="itemInfo" :placeholder="model[ctrlKey].label"
126
+ v-else-if="ctrlType == 'autocomplete'">
127
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
128
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
129
+ </template>
130
+ </el-autocomplete>
131
+ <!--input-number-->
132
+ <el-input-number v-model="ctrlValue" :min="0" :max="100000000" :placeholder="model[ctrlKey].label"
133
+ v-bind="itemInfo" v-else-if="ctrlType == 'input-number'">
134
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
135
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
136
+ </template>
137
+ </el-input-number>
138
+ <!--input-->
139
+ <el-input v-model="ctrlValue" :placeholder="model[ctrlKey].label" :maxlength="itemInfo?.max || 25"
140
+ :clearable="true" v-bind="{ ...itemInfo, type: ctrlType }" v-else>
141
+ <template v-for="(slot, index) in slots()" :key="index" #[slot]="data">
142
+ <slot :name="`${props.t}-${ctrlKey}-${slot}`" :data> </slot>
143
+ </template>
144
+ </el-input>
145
+ </div>
146
+ </template>
147
+
148
+ <script setup>
149
+ defineOptions({ inheritAttrs: false });
150
+ import { onMounted, useSlots, ref } from "vue";
151
+ const ctrlValue = defineModel({ required: true });
152
+ const props = defineProps(["t", "ctrlKey", "item", "model", 'ctrlType'])
153
+ const itemInfo = props.item;
154
+ const ctrlKey = props.ctrlKey;
155
+ const ctrlType = props.ctrlType;
156
+ const model = props.model;
157
+ const treeSelectData = ref([]);
158
+ const slots = () => Object.keys(useSlots()).filter(a => a.startsWith(`${props.t}-${ctrlKey}-`)).map(a => a.replace(`${props.t}-${ctrlKey}-`, ''));
159
+
160
+ //select 默认属性
161
+ const selectModel = {
162
+ filterable: true,
163
+ remote: itemInfo && itemInfo["remote-method"] ? true : false,
164
+ ...itemInfo
165
+ };
166
+ const selectRemoteMethod = (query) => {
167
+ itemInfo["remote-method"](query, (a) => {
168
+ model[ctrlKey].options = a;
169
+ })
170
+ }
171
+
172
+ // 新增:标记数据是否加载完成
173
+ const isOptionsLoaded = ref(false);
174
+
175
+ // 模拟异步获取数据的函数
176
+ const options = async (keyValue = 'options') => {
177
+ try {
178
+ // 这里替换为实际的异步请求
179
+ const response = await itemInfo?.options(model);
180
+ model[ctrlKey][keyValue] = response;
181
+ isOptionsLoaded.value = true;
182
+ } catch (error) {
183
+ console.error('Failed to fetch options:', error);
184
+ }
185
+ };
186
+
187
+ onMounted(async () => {
188
+ if (itemInfo && itemInfo["remote-method"]) {
189
+ selectModel['remote-method'] = selectRemoteMethod;
190
+ }
191
+ // 新增:在组件挂载时调用异步获取数据的函数
192
+ // 提取公共逻辑到一个函数中
193
+ const loadOptions = (key, keyValue = 'options', targetRef = model[ctrlKey]) => {
194
+ if (typeof itemInfo.options === 'function') {
195
+ options(keyValue).catch(error => {
196
+ console.error(`Failed to load ${keyValue} for ${key}:`, error);
197
+ });
198
+ } else if (Array.isArray(itemInfo.options)) {
199
+ targetRef[keyValue] = itemInfo.options;
200
+ // 更新数据加载状态
201
+ isOptionsLoaded.value = true;
202
+ }
203
+ };
204
+
205
+ // 处理不同的 ctrlType
206
+ const typesWithOptions = ['radio', 'radio-button', 'checkbox-group', 'checkbox-group-button', 'select', 'cascader'];
207
+ if (typesWithOptions.includes(ctrlType)) {
208
+ loadOptions(ctrlType);
209
+ }
210
+
211
+ if (ctrlType === 'tree-select') {
212
+ const loadTreeSelectOptions = async () => {
213
+ try {
214
+ if (typeof itemInfo.options === 'function') {
215
+ treeSelectData.value = await itemInfo.options(model);
216
+ } else if (Array.isArray(itemInfo?.data)) {
217
+ treeSelectData.value = itemInfo.data;
218
+ } else if (itemInfo?.options && Array.isArray(itemInfo?.options)) {
219
+ treeSelectData.value = itemInfo.options;
220
+ }
221
+ // 更新数据加载状态
222
+ isOptionsLoaded.value = true;
223
+ } catch (error) {
224
+ console.error(`Failed to load data for tree-select:`, error);
225
+ }
226
+ };
227
+ await loadTreeSelectOptions();
228
+ }
229
+
230
+ })
231
+ </script>