提交 | 用户 | 时间
|
820397
|
1 |
<script lang="ts" setup> |
H |
2 |
import { PropType } from 'vue' |
|
3 |
import { propTypes } from '@/utils/propTypes' |
|
4 |
|
|
5 |
import { useForm } from '@/hooks/web/useForm' |
|
6 |
import { findIndex } from '@/utils' |
|
7 |
import { cloneDeep } from 'lodash-es' |
|
8 |
import { FormSchema } from '@/types/form' |
|
9 |
|
|
10 |
defineOptions({ name: 'Search' }) |
|
11 |
|
|
12 |
const { t } = useI18n() |
|
13 |
|
|
14 |
const props = defineProps({ |
|
15 |
// 生成Form的布局结构数组 |
|
16 |
schema: { |
|
17 |
type: Array as PropType<FormSchema[]>, |
|
18 |
default: () => [] |
|
19 |
}, |
|
20 |
// 是否需要栅格布局 |
|
21 |
isCol: propTypes.bool.def(false), |
|
22 |
// 表单label宽度 |
|
23 |
labelWidth: propTypes.oneOfType([String, Number]).def('auto'), |
|
24 |
// 操作按钮风格位置 |
|
25 |
layout: propTypes.string.validate((v: string) => ['inline', 'bottom'].includes(v)).def('inline'), |
|
26 |
// 底部按钮的对齐方式 |
|
27 |
buttomPosition: propTypes.string |
|
28 |
.validate((v: string) => ['left', 'center', 'right'].includes(v)) |
|
29 |
.def('center'), |
|
30 |
showSearch: propTypes.bool.def(true), |
|
31 |
showReset: propTypes.bool.def(true), |
|
32 |
// 是否显示伸缩 |
|
33 |
expand: propTypes.bool.def(false), |
|
34 |
// 伸缩的界限字段 |
|
35 |
expandField: propTypes.string.def(''), |
|
36 |
inline: propTypes.bool.def(true), |
|
37 |
model: { |
|
38 |
type: Object as PropType<Recordable>, |
|
39 |
default: () => ({}) |
|
40 |
} |
|
41 |
}) |
|
42 |
|
|
43 |
const emit = defineEmits(['search', 'reset']) |
|
44 |
|
|
45 |
const visible = ref(true) |
|
46 |
|
|
47 |
const newSchema = computed(() => { |
|
48 |
let schema: FormSchema[] = cloneDeep(props.schema) |
|
49 |
if (props.expand && props.expandField && !unref(visible)) { |
|
50 |
const index = findIndex(schema, (v: FormSchema) => v.field === props.expandField) |
|
51 |
if (index > -1) { |
|
52 |
const length = schema.length |
|
53 |
schema.splice(index + 1, length) |
|
54 |
} |
|
55 |
} |
|
56 |
if (props.layout === 'inline') { |
|
57 |
schema = schema.concat([ |
|
58 |
{ |
|
59 |
field: 'action', |
|
60 |
formItemProps: { |
|
61 |
labelWidth: '0px' |
|
62 |
} |
|
63 |
} |
|
64 |
]) |
|
65 |
} |
|
66 |
return schema |
|
67 |
}) |
|
68 |
|
|
69 |
const { register, elFormRef, methods } = useForm({ |
|
70 |
model: props.model || {} |
|
71 |
}) |
|
72 |
|
|
73 |
const search = async () => { |
|
74 |
await unref(elFormRef)?.validate(async (isValid) => { |
|
75 |
if (isValid) { |
|
76 |
const { getFormData } = methods |
|
77 |
const model = await getFormData() |
|
78 |
emit('search', model) |
|
79 |
} |
|
80 |
}) |
|
81 |
} |
|
82 |
|
|
83 |
const reset = async () => { |
|
84 |
unref(elFormRef)?.resetFields() |
|
85 |
const { getFormData } = methods |
|
86 |
const model = await getFormData() |
|
87 |
emit('reset', model) |
|
88 |
} |
|
89 |
|
|
90 |
const bottonButtonStyle = computed(() => { |
|
91 |
return { |
|
92 |
textAlign: props.buttomPosition as unknown as 'left' | 'center' | 'right' |
|
93 |
} |
|
94 |
}) |
|
95 |
|
|
96 |
const setVisible = () => { |
|
97 |
unref(elFormRef)?.resetFields() |
|
98 |
visible.value = !unref(visible) |
|
99 |
} |
|
100 |
</script> |
|
101 |
|
|
102 |
<template> |
|
103 |
<!-- update by 芋艿:class="-mb-15px" 用于降低和 ContentWrap 组件的底部距离,避免空隙过大 --> |
|
104 |
<Form |
|
105 |
:inline="inline" |
|
106 |
:is-col="isCol" |
|
107 |
:is-custom="false" |
|
108 |
:label-width="labelWidth" |
|
109 |
:schema="newSchema" |
|
110 |
class="-mb-15px" |
|
111 |
hide-required-asterisk |
|
112 |
@register="register" |
|
113 |
> |
|
114 |
<template #action> |
|
115 |
<div v-if="layout === 'inline'"> |
|
116 |
<!-- update by 芋艿:去除搜索的 type="primary",颜色变淡一点 --> |
|
117 |
<ElButton v-if="showSearch" @click="search"> |
|
118 |
<Icon class="mr-5px" icon="ep:search" /> |
|
119 |
{{ t('common.query') }} |
|
120 |
</ElButton> |
|
121 |
<!-- update by 芋艿:将 icon="ep:refresh-right" 修改成 icon="ep:refresh",和 ruoyi-vue 搜索保持一致 --> |
|
122 |
<ElButton v-if="showReset" @click="reset"> |
|
123 |
<Icon class="mr-5px" icon="ep:refresh" /> |
|
124 |
{{ t('common.reset') }} |
|
125 |
</ElButton> |
|
126 |
<ElButton v-if="expand" text @click="setVisible"> |
|
127 |
{{ t(visible ? 'common.shrink' : 'common.expand') }} |
|
128 |
<Icon :icon="visible ? 'ep:arrow-up' : 'ep:arrow-down'" /> |
|
129 |
</ElButton> |
|
130 |
<!-- add by 芋艿:补充在搜索后的按钮 --> |
|
131 |
<slot name="actionMore"></slot> |
|
132 |
</div> |
|
133 |
</template> |
|
134 |
<template v-for="name in Object.keys($slots)" :key="name" #[name]> |
|
135 |
<slot :name="name"></slot> |
|
136 |
</template> |
|
137 |
</Form> |
|
138 |
|
|
139 |
<template v-if="layout === 'bottom'"> |
|
140 |
<div :style="bottonButtonStyle"> |
|
141 |
<ElButton v-if="showSearch" type="primary" @click="search"> |
|
142 |
<Icon class="mr-5px" icon="ep:search" /> |
|
143 |
{{ t('common.query') }} |
|
144 |
</ElButton> |
|
145 |
<ElButton v-if="showReset" @click="reset"> |
|
146 |
<Icon class="mr-5px" icon="ep:refresh-right" /> |
|
147 |
{{ t('common.reset') }} |
|
148 |
</ElButton> |
|
149 |
<ElButton v-if="expand" text @click="setVisible"> |
|
150 |
{{ t(visible ? 'common.shrink' : 'common.expand') }} |
|
151 |
<Icon :icon="visible ? 'ep:arrow-up' : 'ep:arrow-down'" /> |
|
152 |
</ElButton> |
|
153 |
<!-- add by 芋艿:补充在搜索后的按钮 --> |
|
154 |
<slot name="actionMore"></slot> |
|
155 |
</div> |
|
156 |
</template> |
|
157 |
</template> |