ui-ddy-pc 0.0.1-beta

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.
Files changed (53) hide show
  1. package/.env.development +4 -0
  2. package/.env.prod +1 -0
  3. package/.env.stage +3 -0
  4. package/.vscode/extensions.json +3 -0
  5. package/README.md +7 -0
  6. package/build/configure/package.json +11 -0
  7. package/index.html +13 -0
  8. package/index.js +4 -0
  9. package/package.json +33 -0
  10. package/src/App.vue +20 -0
  11. package/src/assets/table/empty-data.png +0 -0
  12. package/src/assets/table/magnifier.svg +7 -0
  13. package/src/assets/vue.svg +1 -0
  14. package/src/components/tableTest.vue +101 -0
  15. package/src/components/topSearch/search.vue +302 -0
  16. package/src/components/topSearch/searchItem.vue +80 -0
  17. package/src/components/topSign/topSign.vue +170 -0
  18. package/src/components/topTable/topTable.vue +854 -0
  19. package/src/docs/.vitepress/cache/deps/@theme_index.js +258 -0
  20. package/src/docs/.vitepress/cache/deps/@theme_index.js.map +7 -0
  21. package/src/docs/.vitepress/cache/deps/_metadata.json +40 -0
  22. package/src/docs/.vitepress/cache/deps/chunk-KGHB62SH.js +11434 -0
  23. package/src/docs/.vitepress/cache/deps/chunk-KGHB62SH.js.map +7 -0
  24. package/src/docs/.vitepress/cache/deps/chunk-TBELKJNH.js +9088 -0
  25. package/src/docs/.vitepress/cache/deps/chunk-TBELKJNH.js.map +7 -0
  26. package/src/docs/.vitepress/cache/deps/package.json +3 -0
  27. package/src/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +2588 -0
  28. package/src/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
  29. package/src/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +567 -0
  30. package/src/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
  31. package/src/docs/.vitepress/cache/deps/vue.js +323 -0
  32. package/src/docs/.vitepress/cache/deps/vue.js.map +7 -0
  33. package/src/docs/.vitepress/config.js +28 -0
  34. package/src/docs/api-examples.md +49 -0
  35. package/src/docs/combinedTable.md +158 -0
  36. package/src/docs/index.md +25 -0
  37. package/src/docs/markdown-examples.md +98 -0
  38. package/src/docs/unitTests/searchTest.vue +109 -0
  39. package/src/main.js +16 -0
  40. package/src/packages/index.js +3 -0
  41. package/src/router/index.js +24 -0
  42. package/src/store/index.js +35 -0
  43. package/src/style.css +73 -0
  44. package/src/utils/common.js +254 -0
  45. package/src/utils/currency.js +256 -0
  46. package/src/utils/errorCode.js +6 -0
  47. package/src/utils/request.js +220 -0
  48. package/src/utils/top.js +233 -0
  49. package/ui-ddy-pc/package.json +11 -0
  50. package/ui-ddy-pc/style.css +1 -0
  51. package/ui-ddy-pc/ui-ddy-pc.js +26436 -0
  52. package/ui-ddy-pc/ui-ddy-pc.umd.cjs +83 -0
  53. package/vite.config.js +54 -0
@@ -0,0 +1,4 @@
1
+ # 测试环境
2
+ VITE_NODE_ENV = 'env'
3
+
4
+ VITE_BASE_API = '/stage-api'
package/.env.prod ADDED
@@ -0,0 +1 @@
1
+ VITE_BASE_API = '/prod-api'
package/.env.stage ADDED
@@ -0,0 +1,3 @@
1
+ VITE_BASE_API = '/stage-api'
2
+
3
+ VITE_NODE_ENV = 'uat'
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["Vue.volar"]
3
+ }
package/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # Vue 3 + Vite
2
+
3
+ This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
4
+
5
+ ## Recommended IDE Setup
6
+
7
+ - [VS Code](https://code.visualstudio.com/) + [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously Volar) and disable Vetur
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "ui-ddy-pc",
3
+ "version": "1.0.0",
4
+ "description": "pc端 表格组件",
5
+ "main": "ui-ddy-pc.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "",
10
+ "license": "ISC"
11
+ }
package/index.html ADDED
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Vite + Vue</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.js"></script>
12
+ </body>
13
+ </html>
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // import TopTable from "./src/components/topTable/topTable.vue";
2
+ import TopSign from "./src/components/topSign/topSign.vue";
3
+
4
+ export { TopSign };
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "ui-ddy-pc",
3
+ "version": "0.0.1-beta",
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite",
7
+ "build": "vite build",
8
+ "preview": "vite preview",
9
+ "build:stage": "vite build --mode stage",
10
+ "build:prod": "vite build --mode prod",
11
+ "docs:dev": "vitepress dev src/docs",
12
+ "docs:build": "vitepress build src/docs",
13
+ "docs:preview": "vitepress preview src/docs"
14
+ },
15
+ "dependencies": {
16
+ "@element-plus/icons-vue": "^2.3.1",
17
+ "axios": "^1.6.8",
18
+ "element-plus": "^2.7.0",
19
+ "pinia": "^2.1.7",
20
+ "qs": "^6.12.1",
21
+ "rollup-plugin-copy": "^3.5.0",
22
+ "sass": "^1.75.0",
23
+ "vue": "^3.4.21",
24
+ "vue-router": "^4.3.0"
25
+ },
26
+ "devDependencies": {
27
+ "@vitejs/plugin-vue": "^5.0.4",
28
+ "unplugin-auto-import": "^0.17.5",
29
+ "unplugin-vue-components": "^0.26.0",
30
+ "vite": "^5.2.0",
31
+ "vitepress": "^1.1.4"
32
+ }
33
+ }
package/src/App.vue ADDED
@@ -0,0 +1,20 @@
1
+ <script setup>
2
+ import { userStore } from '@/store'
3
+ import qs from 'qs';
4
+
5
+ // 代办之类获取token
6
+ let urlParams = qs.parse(window.location.href.split("?")[1]);
7
+ const store = userStore()
8
+ const props = window.$wujie?.props;
9
+ store.setToken(props?.token || urlParams?.token)
10
+ store.setOrign(props?.origin)
11
+ store.setUsers(props?.users)
12
+
13
+ </script>
14
+
15
+ <template>
16
+ <RouterView></RouterView>
17
+ </template>
18
+
19
+ <style scoped>
20
+ </style>
Binary file
@@ -0,0 +1,7 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="Frame">
3
+ <path id="Vector" d="M6.9987 12.6668C10.1283 12.6668 12.6654 10.1298 12.6654 7.00016C12.6654 3.87056 10.1283 1.3335 6.9987 1.3335C3.8691 1.3335 1.33203 3.87056 1.33203 7.00016C1.33203 10.1298 3.8691 12.6668 6.9987 12.6668Z" stroke="white" stroke-linejoin="round"/>
4
+ <path id="Vector_2" d="M8.88647 4.78103C8.4039 4.29847 7.73723 4 7.00083 4C6.26447 4 5.5978 4.29847 5.11523 4.78103" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path id="Vector_3" d="M11.0742 11.0737L13.9027 13.9022" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
6
+ </g>
7
+ </svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
@@ -0,0 +1,101 @@
1
+ <template>
2
+ <topTable v-bind="{ ...enity }"></topTable>
3
+ </template>
4
+ <script setup>
5
+ import topTable from './topTable/topTable.vue'
6
+ import { ref, reactive } from 'vue'
7
+ import { TableHead } from '@/utils/common.js'
8
+
9
+ const enity = reactive({
10
+ tableApi: {
11
+ url: `/material/send/pc/warehouseList`,
12
+ method: 'post',
13
+ // 接口需要的额外参数
14
+ params: {},
15
+ // 有前置条件
16
+ beforeCb: (params) => {
17
+ // 前置条件达成resolve reject不执行后续函数
18
+ return new Promise((resolve, reject) => {
19
+ setTimeout(() => {
20
+ resolve()
21
+ }, 3000);
22
+ })
23
+ },
24
+ },
25
+ column: [
26
+ {
27
+ ...TableHead('选择', '', 60),
28
+ align: "center",
29
+ type: 'selection',
30
+ reserveSelection: true,
31
+ selectable: (row) => {
32
+ return row.poundBillStatus != 4
33
+ }
34
+ },
35
+ {
36
+ title: '序号',
37
+ type: 'index',
38
+ width: 60,
39
+ },
40
+ { ...TableHead('仓库', 'warehouseName', 120) },
41
+ { ...TableHead('磅房', 'poundRoomName', 120) },
42
+ { ...TableHead('发料单号', 'code', 120), stress: true },
43
+ { ...TableHead('发料单来源', 'dataSource', 100), slot: 'dataSource' },
44
+ { ...TableHead('关联合同', 'contractInfoName'), },
45
+ { ...TableHead('收料单位', 'gysName') },
46
+ // { ...TableHead('材料类型', 'useType'), slot:'useType' },
47
+ { ...TableHead('材料编号', 'clCode'), },
48
+ { ...TableHead('材料名称', 'clName'), slot: 'clName' },
49
+ { ...TableHead('数量', 'intoCount', 70), slot: 'intoCount' },
50
+ { ...TableHead('单位', 'clUnit', 70) },
51
+ { ...TableHead('车牌', 'carNo'), },
52
+ { ...TableHead('签字状态', 'signatureStatus'), slot: 'signatureStatus' },
53
+ { ...TableHead('发料单位', 'subjectName') },
54
+ { ...TableHead('状态', 'status'), slot: 'status' },
55
+ { ...TableHead('发料时间', 'firstDate'), slot: 'firstDate' },
56
+ { ...TableHead('创建人', 'createByName') },
57
+ ],
58
+ searchConfig: {
59
+ data: {},
60
+ // 默认选中的搜索项的值 重置也保留此值
61
+ defaultData: { scope: 1 },
62
+ config: [
63
+ { label: '发料单号', field: 'code' },
64
+ { label: '材料名称', field: 'clName' },
65
+ {
66
+ label: '发料单来源', field: 'dataSourceList', type: 'select',
67
+ options: [
68
+ { value: "0", label: "磅房" },
69
+ { value: "1", label: "移动端" },
70
+ { value: "4", label: "拌合站" },
71
+ { value: "5", label: "盘点" }
72
+ ],
73
+ multiple: true
74
+ },
75
+ {
76
+ label: '是否关联', field: 'connStatus', type: 'select',
77
+ options: [
78
+ { value: "", label: "全部" },
79
+ { value: "0", label: "未关联" },
80
+ { value: "1", label: "已关联" }
81
+ ]
82
+ },
83
+ { label: '材料编号', field: 'clCode' },
84
+ { label: '仓库名称', field: 'warehouseName' },
85
+ { label: '磅房名称', field: 'poundRoomName' },
86
+ { label: '收料单位', field: 'gysName' },
87
+ { label: '合同名称', field: 'contractInfoName' },
88
+ {
89
+ label: '发料时间', field: 'time', type: 'daterange', startField: "createTimeBegin", endField: "createTimeEnd",
90
+ format: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'YYYY-MM-DD HH:mm:ss'
91
+ },
92
+ ]
93
+ }
94
+ })
95
+ </script>
96
+
97
+ <style scoped>
98
+ .read-the-docs {
99
+ color: #888;
100
+ }
101
+ </style>
@@ -0,0 +1,302 @@
1
+ <template>
2
+ <div ref="formObj" class="search-container" :style="searchStyle">
3
+ <el-form class="search-row" :inline="true" :label-width="refObjs.maxWidth">
4
+ <el-form-item v-for="(item, index) in obj.items" :label="item.label" class="">
5
+ <template #label>
6
+ <div :id='`label-${item.field}`' class="item-label">{{ item.label }}</div>
7
+ </template>
8
+ <div :id='`content-${item.field}`'>
9
+ <search-item :config="item" :data="searchConfig.data" @search="handleSubmit(false)"></search-item>
10
+ </div>
11
+ </el-form-item>
12
+ <div class="buttons row-item" v-if="remainWidth > 270">
13
+ <div class="btn" v-if="showMore && hasHide" @click="handleExpan">
14
+ <div class="icon">
15
+ <el-icon size="18" color="#ccc">
16
+ <CaretBottom v-if="obj.isShow" />
17
+ <CaretTop v-else />
18
+ </el-icon>
19
+ </div>
20
+ <div class="text">{{ obj.isShow ? '展开' : '收起' }}</div>
21
+ </div>
22
+ <el-button @click="handleSubmit(false)" color="#436EE6">查询
23
+ <template #icon>
24
+ <img src="@/assets/table/magnifier.svg">
25
+ </template>
26
+ </el-button>
27
+ <el-button @click="handleSubmit(true)" class="reset">
28
+ <template #icon>
29
+ <el-icon>
30
+ <Refresh :size="24" />
31
+ </el-icon>
32
+ </template>
33
+ 重置</el-button>
34
+ </div>
35
+ <div class="buttons individual" v-else>
36
+ <el-button @click="handleSubmit(true)" style="margin-left: 12px;" class="reset">
37
+ <template #icon>
38
+ <el-icon>
39
+ <Refresh :size="24" />
40
+ </el-icon>
41
+ </template>
42
+ 重置</el-button>
43
+ <el-button @click="handleSubmit(false)" color="#436EE6" style="margin-left: 0;">查询
44
+ <template #icon>
45
+ <img src="@/assets/table/magnifier.svg">
46
+ </template>
47
+ </el-button>
48
+ <div class="btn" v-if="showMore && hasHide" @click="handleExpan">
49
+ <div class="icon">
50
+ <el-icon size="18" color="#ccc">
51
+ <CaretBottom v-if="obj.isShow" />
52
+ <CaretTop v-else />
53
+ </el-icon>
54
+ </div>
55
+ <div class="text">{{ obj.isShow ? '展开' : '收起' }}</div>
56
+ </div>
57
+ </div>
58
+ </el-form>
59
+ </div>
60
+ </template>
61
+ <script setup>
62
+ import { ref, computed, onMounted, reactive, watch, nextTick, onUnmounted, toRefs } from 'vue';
63
+ import searchItem from './searchItem.vue'
64
+
65
+ const props = defineProps({
66
+ searchConfig: {
67
+ type: Object,
68
+ default: {}
69
+ },
70
+ showMore: {
71
+ type: Boolean,
72
+ default: true
73
+ },
74
+ searchStyle: {
75
+ type: Object,
76
+ default: () => ({
77
+ 'background-color': '#ebedf2',
78
+ 'margin': '10px',
79
+ 'border-radius': '10px',
80
+ 'padding': '20px 20px 0 20px',
81
+ 'box-sizing': 'border-box',
82
+ 'transition': '.3s linear',
83
+ })
84
+ }
85
+ })
86
+ const emit = defineEmits(['search', 'show', 'searchHeightChange'])
87
+ const handleSubmit = (isReset) => {
88
+ // 传入了默认查询条件 自动赋值
89
+ if (isReset) {
90
+ props.searchConfig.data = props.searchConfig.defaultData ? props.searchConfig.defaultData : {}
91
+ }
92
+ emit('search', isReset)
93
+ }
94
+ const obj = reactive({
95
+ items: toRefs(props.searchConfig.config),
96
+ isShow: true
97
+ })
98
+ const fixedNums = ref(0)
99
+ const getLastRowNums = (arr) => {
100
+ // 每行最多放下数量
101
+ let currentLength = 0
102
+ arr.forEach(item => {
103
+ // 换行清空
104
+ currentLength = currentLength + item + refObjs.maxWidth + 10 <= windowWidth.value ? currentLength + item + refObjs.maxWidth + 10 : item + refObjs.maxWidth + 10
105
+ })
106
+ remainWidth.value = windowWidth.value - currentLength
107
+ // console.log(remainWidth.value, '展开后最后一行剩余宽度');
108
+ }
109
+ const handleExpan = async () => {
110
+ isInit.value = false
111
+ const isExpan = obj.items.length < props.searchConfig.config.length
112
+ // 展示的内容小于配置时即展开
113
+ obj.items = isExpan ? props.searchConfig.config : props.searchConfig.config.slice(0, fixedNums.value)
114
+ await nextTick()
115
+ // 展开
116
+ if (isExpan) {
117
+ // 获取content所有宽度
118
+ getContent(props.searchConfig.config)
119
+ getLastRowNums(refObjs.widthArray)
120
+ }
121
+ // 收起
122
+ else {
123
+ remainWidth.value = 271
124
+ }
125
+ obj.isShow = !obj.isShow;
126
+ emit('show', obj.isShow)
127
+ emit('searchHeightChange', true)
128
+ }
129
+
130
+ const formObj = ref(null)
131
+ const windowWidth = ref(0)
132
+ const refObjs = reactive({
133
+ labelArray: [],
134
+ contentArray: [],
135
+ widthArray: [],
136
+ maxWidth: 40
137
+ })
138
+
139
+ const isInit = ref(true)
140
+ const remainWidth = ref(0)
141
+ // 暂定传入 预留空间
142
+ const getLabel = (arr) => {
143
+ refObjs.labelArray = arr.map(item => {
144
+ if (item) {
145
+ return document.getElementById('label-' + item.field)
146
+ }
147
+ }).filter(item2 => item2 !== undefined)
148
+ // console.log(refObjs.labelArray, 'label元素数组');
149
+ refObjs.maxWidth = refObjs.labelArray.reduce((maxWidth, item) => {
150
+ return Math.max(maxWidth, item.offsetWidth + 12)
151
+ }, 40)
152
+ // console.log(refObjs.maxWidth, 'label最大宽度');
153
+ }
154
+
155
+ // 暂定传入 预留空间
156
+ const getContent = (arr) => {
157
+ refObjs.contentArray = arr.map(item => {
158
+ if (item) {
159
+ return document.getElementById('content-' + item.field)
160
+ }
161
+ }).filter(item2 => item2 !== undefined)
162
+ // console.log(refObjs.contentArray, 'content元素数组');
163
+ refObjs.widthArray = refObjs.contentArray.map(item => {
164
+ return item.offsetWidth
165
+ })
166
+ // console.log(refObjs.widthArray, 'content所有元素的宽度');
167
+ }
168
+
169
+ // 递归计算一行可展示最大个数
170
+ const calcNum = (clientWidth, widthArray, val = '') => {
171
+ const sum = widthArray.reduce((sumVal, currentVal) => {
172
+ // 累加元素内容宽度 + 标签宽度 + margin
173
+ return sumVal + currentVal + refObjs.maxWidth + 10
174
+ }, 0)
175
+ // console.log(sum, '计算总长');
176
+ // 折叠状态为按钮组预留宽度
177
+ if (sum && sum + 270 > clientWidth) {
178
+ return calcNum(clientWidth, widthArray.slice(0, widthArray.length - 1), val)
179
+ }
180
+ else {
181
+ // console.log(sum, '当前可展示区域长度');
182
+ // 首行可显示个数
183
+ remainWidth.value = clientWidth - sum
184
+ val = widthArray.length
185
+ return val
186
+ }
187
+ }
188
+
189
+ // 设置当前宽度 仅该页面的宽度
190
+ const handleInit = async (changeTab = false) => {
191
+ isInit.value = true
192
+ // 全部渲染出 获取所有的labelWidth contentWidth
193
+ obj.items = props.searchConfig.config
194
+ await nextTick()
195
+ // 设置当前屏幕宽度
196
+ windowWidth.value = formObj.value.clientWidth
197
+ if (windowWidth.value == 0) {
198
+ setTimeout(handleInit(changeTab), 500)
199
+ return;
200
+ }
201
+ // console.log(windowWidth.value, '当前页面视口宽度');
202
+ // 获取label最大宽度 设置label宽
203
+ getLabel(props.searchConfig.config)
204
+ // 获取content所有宽度
205
+ getContent(props.searchConfig.config)
206
+ fixedNums.value = calcNum(windowWidth.value, refObjs.widthArray)
207
+ // console.log(fixedNums.value, 'fixedNums.value');
208
+ // 修正当前可显示值
209
+ obj.items = props.searchConfig.config.slice(0, fixedNums.value)
210
+ if (changeTab) {
211
+ emit('searchHeightChange', true)
212
+ }
213
+ }
214
+
215
+
216
+ const hasHide = computed(() => {
217
+ // 未点击过展开或收起
218
+ if (isInit.value) {
219
+ // 当前展示长度和传入值长度不一致即显示展开按钮
220
+ return obj.items.length !== props.searchConfig.config.length
221
+ }
222
+ else {
223
+ return true
224
+ }
225
+ })
226
+ const handleResize = () => {
227
+ // 重置展开
228
+ obj.isShow = true
229
+ handleInit()
230
+ }
231
+ // 监听屏幕改变
232
+ onMounted(() => {
233
+ window.addEventListener('resize', handleResize);
234
+ handleInit()
235
+ })
236
+ onUnmounted(() => {
237
+ window.removeEventListener('resize', handleResize); // 在组件销毁时移除事件监听器
238
+ });
239
+
240
+ window.onChangeEmit = () => {
241
+ obj.isShow = true
242
+ handleInit(true)
243
+ }
244
+ defineExpose({ handleInit })
245
+ </script>
246
+ <style lang="scss" scoped>
247
+ .search-container {
248
+ position: relative;
249
+ }
250
+
251
+ .buttons {
252
+ align-items: center;
253
+ margin-bottom: 18px;
254
+ display: inline-flex;
255
+ vertical-align: middle;
256
+
257
+ .btn {
258
+ display: flex;
259
+ align-items: center;
260
+ padding: 0px 20px;
261
+ cursor: pointer;
262
+ user-select: none;
263
+
264
+ .icon {
265
+ margin-top: 3px;
266
+ }
267
+
268
+ .text {
269
+ color: #303133;
270
+ font-size: 14px;
271
+ padding-left: 10px;
272
+ }
273
+ }
274
+ button:focus {
275
+ outline: none;
276
+ }
277
+ }
278
+
279
+ .row-item {
280
+ .el-col:nth-child(4n) {
281
+ .el-form-item {
282
+ margin-right: 0 !important;
283
+ }
284
+ }
285
+
286
+ position: absolute;
287
+ right: 0;
288
+ }
289
+
290
+ .el-form-item {
291
+ margin-right: 10px !important;
292
+ }
293
+
294
+ .item-label {
295
+ white-space: nowrap;
296
+ }
297
+
298
+ .individual {
299
+ display: flex;
300
+ flex-direction: row-reverse;
301
+ }
302
+ </style>
@@ -0,0 +1,80 @@
1
+ <template>
2
+ <el-select style="width: 100%;" v-if="config.type == 'select'" v-model="data[config.field]" placeholder="请选择"
3
+ no-data-text="暂无数据" clearable :multiple="config.multiple" :collapse-tags="true" :popper-class="props.isSpectacular? 'spectacular-select':''">
4
+ <el-option v-for="item in config.options" :key="item.value" :label="item.label" :value="item.value" />
5
+ </el-select>
6
+ <el-date-picker style="width: 240px;" v-else-if="config.type == 'date'" v-model="data[config.field]"
7
+ :format="config.format ? config.format : 'YYYY-MM-DD'"
8
+ :valueFormat="config.valueFormat ? config.valueFormat : 'YYYY-MM-DD'" placeholder="请选择"
9
+ :type="config.dateType ? config.dateType : 'date'">
10
+ </el-date-picker>
11
+ <el-date-picker v-else-if="config.type == 'daterange'" v-model="data[config.field]"
12
+ :format="config.format ? config.format : 'YYYY-MM-DD'" :type="config.dateType ? config.dateType : 'daterange'"
13
+ :valueFormat="config.valueFormat ? config.valueFormat : 'YYYY-MM-DD'" @change="handleDateRangeChange"
14
+ :default-time="defaultTime"
15
+ start-placeholder="请选择" end-placeholder="请选择" :style="`width: ${config.width}`" :teleported="false">
16
+ </el-date-picker>
17
+ <el-tree-select v-else-if="config.type == 'selectTree'" v-model="data[config.field]"
18
+ :data="config.selectTreeData" filterable :multiple="config.multiple"
19
+ :show-checkbox="config.multiple" node-key="id" :check-strictly="config.checkStrictly" clearable
20
+ :props="config?.props ? config.props : { children: 'children', label: 'label'}"
21
+ />
22
+
23
+ <el-input v-else v-model.trim="data[config.field]" :placeholder="config.placeholder || '请输入'" clearable :disabled="config.disabled" @keydown.enter.native.prevent="handleSearch">
24
+ </el-input>
25
+ </template>
26
+ <script setup>
27
+ import { reactive, ref } from 'vue';
28
+ const emits = defineEmits(['search'])
29
+ const defaultTime = reactive([
30
+ new Date(0, 0, 0, 0, 0, 0),
31
+ new Date(0, 0, 0, 23, 59, 59),
32
+ ])
33
+ const props = defineProps({
34
+ config: {
35
+ type: Object,
36
+ default: () => { }
37
+ },
38
+ data: {
39
+ type: Object,
40
+ default: () => { }
41
+ },
42
+ isSpectacular: {
43
+ type: Boolean,
44
+ default: false
45
+ }
46
+ })
47
+ const handleDateRangeChange = (val) => {
48
+ if (props.config.startField && props.config.endField &&val) {
49
+ props.data[props.config.startField] = val[0]
50
+ props.data[props.config.endField] = val[1]
51
+ } else {
52
+ props.data[props.config.startField] = ''
53
+ props.data[props.config.endField] = ''
54
+ }
55
+ }
56
+ const handleSearch = () => {
57
+ emits('search')
58
+ }
59
+ </script>
60
+ <style lang="scss" scoped>
61
+ .el-select,
62
+ .el-input {
63
+ width: 240px !important;
64
+ }
65
+ </style>
66
+ <style lang="scss">
67
+ .el-popper.is-pure.is-light.el-select__popper.spectacular-select {
68
+ border: 1px solid #1D96EB;
69
+ }
70
+ .spectacular-select {
71
+ background: #052b46;
72
+ .el-select-dropdown__item {
73
+ color: #fff;
74
+
75
+ }
76
+ .el-select-dropdown__item.is-hovering {
77
+ background: #074069;
78
+ }
79
+ }
80
+ </style>