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.
- package/.env.development +4 -0
- package/.env.prod +1 -0
- package/.env.stage +3 -0
- package/.vscode/extensions.json +3 -0
- package/README.md +7 -0
- package/build/configure/package.json +11 -0
- package/index.html +13 -0
- package/index.js +4 -0
- package/package.json +33 -0
- package/src/App.vue +20 -0
- package/src/assets/table/empty-data.png +0 -0
- package/src/assets/table/magnifier.svg +7 -0
- package/src/assets/vue.svg +1 -0
- package/src/components/tableTest.vue +101 -0
- package/src/components/topSearch/search.vue +302 -0
- package/src/components/topSearch/searchItem.vue +80 -0
- package/src/components/topSign/topSign.vue +170 -0
- package/src/components/topTable/topTable.vue +854 -0
- package/src/docs/.vitepress/cache/deps/@theme_index.js +258 -0
- package/src/docs/.vitepress/cache/deps/@theme_index.js.map +7 -0
- package/src/docs/.vitepress/cache/deps/_metadata.json +40 -0
- package/src/docs/.vitepress/cache/deps/chunk-KGHB62SH.js +11434 -0
- package/src/docs/.vitepress/cache/deps/chunk-KGHB62SH.js.map +7 -0
- package/src/docs/.vitepress/cache/deps/chunk-TBELKJNH.js +9088 -0
- package/src/docs/.vitepress/cache/deps/chunk-TBELKJNH.js.map +7 -0
- package/src/docs/.vitepress/cache/deps/package.json +3 -0
- package/src/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +2588 -0
- package/src/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
- package/src/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +567 -0
- package/src/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
- package/src/docs/.vitepress/cache/deps/vue.js +323 -0
- package/src/docs/.vitepress/cache/deps/vue.js.map +7 -0
- package/src/docs/.vitepress/config.js +28 -0
- package/src/docs/api-examples.md +49 -0
- package/src/docs/combinedTable.md +158 -0
- package/src/docs/index.md +25 -0
- package/src/docs/markdown-examples.md +98 -0
- package/src/docs/unitTests/searchTest.vue +109 -0
- package/src/main.js +16 -0
- package/src/packages/index.js +3 -0
- package/src/router/index.js +24 -0
- package/src/store/index.js +35 -0
- package/src/style.css +73 -0
- package/src/utils/common.js +254 -0
- package/src/utils/currency.js +256 -0
- package/src/utils/errorCode.js +6 -0
- package/src/utils/request.js +220 -0
- package/src/utils/top.js +233 -0
- package/ui-ddy-pc/package.json +11 -0
- package/ui-ddy-pc/style.css +1 -0
- package/ui-ddy-pc/ui-ddy-pc.js +26436 -0
- package/ui-ddy-pc/ui-ddy-pc.umd.cjs +83 -0
- package/vite.config.js +54 -0
package/.env.development
ADDED
package/.env.prod
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VITE_BASE_API = '/prod-api'
|
package/.env.stage
ADDED
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
|
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
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>
|