You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
397 lines
12 KiB
397 lines
12 KiB
<script lang="ts" setup>
|
|
import { PropType } from 'vue'
|
|
import { propTypes } from '@/utils/propTypes'
|
|
|
|
import { useForm } from '@/hooks/web/useForm'
|
|
import { findIndex } from '@/utils'
|
|
import { cloneDeep } from 'lodash-es'
|
|
import { FormSchema } from '@/types/form'
|
|
|
|
import { useCache } from '@/hooks/web/useCache'
|
|
const { wsCache } = useCache()
|
|
const message = useMessage() // 消息弹窗
|
|
|
|
defineOptions({ name: 'Search' })
|
|
|
|
const { t } = useI18n()
|
|
|
|
const props = defineProps({
|
|
// 生成Form的布局结构数组
|
|
schema: {
|
|
type: Array as PropType<FormSchema[]>,
|
|
default: () => []
|
|
},
|
|
// 是否需要栅格布局
|
|
isCol: propTypes.bool.def(false),
|
|
// 表单label宽度
|
|
labelWidth: propTypes.oneOfType([String, Number]).def('auto'),
|
|
// 操作按钮风格位置
|
|
layout: propTypes.string.validate((v: string) => ['inline', 'bottom'].includes(v)).def('inline'),
|
|
// 底部按钮的对齐方式
|
|
buttomPosition: propTypes.string
|
|
.validate((v: string) => ['left', 'center', 'right'].includes(v))
|
|
.def('center'),
|
|
showSearch: propTypes.bool.def(true),
|
|
showReset: propTypes.bool.def(true),
|
|
// 是否显示伸缩
|
|
expand: propTypes.bool.def(false),
|
|
// 伸缩的界限字段
|
|
expandField: propTypes.string.def(''),
|
|
inline: propTypes.bool.def(true),
|
|
model: {
|
|
type: Object as PropType<Recordable>,
|
|
default: () => ({})
|
|
},
|
|
// 详情数据
|
|
detailData: {
|
|
type: Object,
|
|
required: true,
|
|
default: null
|
|
},
|
|
hiddenFilterBtnFields:{
|
|
type: Array,
|
|
required: false,
|
|
default: []
|
|
},
|
|
showSearchTableQueryFields:{
|
|
type: Array,
|
|
required: false,
|
|
default: []
|
|
},
|
|
formClassNames:{
|
|
type: Array,
|
|
required: false,
|
|
default: []
|
|
},
|
|
//回车触发搜索。默认true
|
|
enterSearch:{
|
|
type: Boolean,
|
|
required: false,
|
|
default: true
|
|
},
|
|
})
|
|
|
|
const emit = defineEmits(['search', 'reset','onInput','onChange','onEnter','searchTableSuccess','onBlur'])
|
|
|
|
const visible = ref(true)
|
|
|
|
const newSchema = computed(() => {
|
|
let schema: FormSchema[] = cloneDeep(props.schema)
|
|
if (!wsCache.get('ShowPackingNumber')) {
|
|
if (schema) {
|
|
schema = schema.filter(item => item.field != 'packingNumber')
|
|
}
|
|
}
|
|
if (props.expand && props.expandField && !unref(visible)) {
|
|
const index = findIndex(schema, (v: FormSchema) => v.field === props.expandField)
|
|
if (index > -1) {
|
|
const length = schema.length
|
|
schema.splice(index + 1, length)
|
|
}
|
|
}
|
|
if (props.layout === 'inline') {
|
|
schema = schema.concat([
|
|
{
|
|
field: 'action',
|
|
formItemProps: {
|
|
labelWidth: '0px'
|
|
}
|
|
}
|
|
])
|
|
}
|
|
updateSort(schema)
|
|
return schema
|
|
})
|
|
const updateSort= (val)=>{
|
|
val.forEach(item=>{
|
|
if(!item.sortSearchDefault){
|
|
if(item.field=="action"){
|
|
item.sortSearchDefault = 9999 // 查询重置等操作按钮
|
|
}else{
|
|
item.sortSearchDefault = 999 // 默认999
|
|
}
|
|
}
|
|
})
|
|
val.sort((column1,column2)=>{
|
|
return column1.sortSearchDefault - column2.sortSearchDefault
|
|
})
|
|
}
|
|
|
|
const { register, elFormRef, methods } = useForm({
|
|
model: props.model || {}
|
|
})
|
|
|
|
const onInput = (field,value) => {
|
|
emit('onInput', field,value)
|
|
}
|
|
const onChange = (field, value)=>{
|
|
emit('onChange', field,value)
|
|
}
|
|
|
|
const onSubmit = (e) => {
|
|
e.preventDefault();
|
|
}
|
|
const onEnter = async (field, value, e) => {
|
|
|
|
if(props.enterSearch){
|
|
search()
|
|
}else{
|
|
emit('onEnter', field, value, e)
|
|
}
|
|
}
|
|
const searchTableRef = ref()
|
|
const opensearchTable = (
|
|
formField,
|
|
searchField,
|
|
searchTitle,
|
|
searchAllSchemas,
|
|
searchPage,
|
|
searchCondition,
|
|
multiple,
|
|
type,
|
|
row,
|
|
isConcatDetailSchemas=false,
|
|
searchDetailSchemas: any
|
|
) => {
|
|
const _searchCondition = {}
|
|
// 判断查询条件中,是否存在指向主表的数据
|
|
if (searchCondition && searchCondition.length > 0) {
|
|
// 转换筛选条件所需
|
|
let filters: any[] = []
|
|
for (var i=0; i< searchCondition.length; i++ ) {
|
|
// searchCondition.forEach((item) => {
|
|
// 查询条件为主表某字段,需要赋值主表数据,数据来源是详情的,赋值需要从row中获取
|
|
if (searchCondition[i].isMainValue) {
|
|
let keyValue = formRef.value.formModel[searchCondition[i].value]
|
|
? formRef.value.formModel[searchCondition[i].value]
|
|
: props.detailData
|
|
? props.detailData[searchCondition[i].value]
|
|
: row
|
|
? row[searchCondition[i].value]
|
|
: ''
|
|
|
|
if(searchCondition[i].isCSV&&keyValue){
|
|
//用逗号分隔取参数
|
|
if(Array.isArray(keyValue)){
|
|
keyValue = keyValue.join(',')
|
|
}else{
|
|
keyValue = keyValue.split(' ')
|
|
keyValue.forEach(item=>{item = item.trim()})
|
|
keyValue = keyValue.join(',')
|
|
}
|
|
console.log('keyValue',keyValue)
|
|
}
|
|
_searchCondition[searchCondition[i].key] = keyValue
|
|
if(searchCondition[i].required){
|
|
// 是否含有空参数情况
|
|
let isNull = false
|
|
if (_searchCondition[searchCondition[i].key] == '' || _searchCondition[searchCondition[i].key] == undefined) {
|
|
isNull = true
|
|
}
|
|
if (isNull) {
|
|
message.warning(searchCondition[i].message?searchCondition[i].message:'前置条件未选择!')
|
|
return
|
|
}
|
|
}
|
|
|
|
}else if(searchCondition[i].isTableRowValue){
|
|
if(searchCondition[i].required){
|
|
if (row[searchCondition[i].value] == '' ||row[searchCondition[i].value] == undefined) {
|
|
message.warning(searchCondition[i].message?searchCondition[i].message:'前置条件未选择!')
|
|
return
|
|
}
|
|
}
|
|
row[searchCondition[i].value]
|
|
//查询当前table表数据的值
|
|
_searchCondition[searchCondition[i].key] = row[searchCondition[i].value]
|
|
} else {
|
|
// 扩展 转换为筛选条件进行查询
|
|
if (searchCondition[i].isSearch) {
|
|
if (searchCondition[i].isFormModel) {
|
|
//用formModel中的值
|
|
if(searchCondition[i].required){
|
|
if (formRef.value.formModel[searchCondition[i].value] == '' ||formRef.value.formModel[searchCondition[i].value] == undefined) {
|
|
message.warning(searchCondition[i].message?searchCondition[i].message:'前置条件未选择!')
|
|
return
|
|
}
|
|
}
|
|
filters.push({
|
|
action: searchCondition[i].action,
|
|
column: searchCondition[i].key,
|
|
value: formRef.value.formModel[searchCondition[i].value]
|
|
})
|
|
}else{
|
|
filters.push({
|
|
action: searchCondition[i].action,
|
|
column: searchCondition[i].key,
|
|
value: searchCondition[i].value
|
|
})
|
|
}
|
|
|
|
} else {
|
|
_searchCondition[searchCondition[i].key] = searchCondition[i].value
|
|
}
|
|
}
|
|
}
|
|
if (filters.length > 0) {
|
|
_searchCondition.isSearch = true
|
|
_searchCondition.filters = filters
|
|
}
|
|
}
|
|
const _searchTableTitle = searchTitle
|
|
const _searchTableAllSchemas = searchAllSchemas
|
|
const _searchTablePage = searchPage
|
|
searchTableRef.value.open(
|
|
_searchTableTitle,
|
|
_searchTableAllSchemas,
|
|
_searchTablePage,
|
|
formField,
|
|
searchField,
|
|
multiple,
|
|
type,
|
|
row,
|
|
_searchCondition,
|
|
undefined,
|
|
isConcatDetailSchemas,
|
|
searchDetailSchemas
|
|
)
|
|
}
|
|
const formRef = ref()
|
|
const setFormValues = (formData)=>{
|
|
formRef.value.setValues(formData)
|
|
}
|
|
const search = async () => {
|
|
await unref(elFormRef)?.validate(async (isValid) => {
|
|
if (isValid) {
|
|
const { getFormData } = methods
|
|
const model = await getFormData()
|
|
console.log(model)
|
|
emit('search', model)
|
|
}
|
|
})
|
|
}
|
|
|
|
const reset = async () => {
|
|
unref(elFormRef)?.resetFields()
|
|
const { getFormData } = methods
|
|
const model = await getFormData()
|
|
emit('reset', model)
|
|
}
|
|
|
|
const bottonButtonStyle = computed(() => {
|
|
return {
|
|
textAlign: props.buttomPosition as unknown as 'left' | 'center' | 'right'
|
|
}
|
|
})
|
|
|
|
const setVisible = () => {
|
|
unref(elFormRef)?.resetFields()
|
|
visible.value = !unref(visible)
|
|
}
|
|
// 弹层确定返回所选数据
|
|
// val : 弹层列表row 数据
|
|
const searchTableSuccess = (formField, searchField, val, type, row) => {
|
|
emit('searchTableSuccess', formField, searchField, val, formRef.value, type, row)
|
|
}
|
|
const onBlur = async (field, e) => {
|
|
emit('onBlur', field, e)
|
|
}
|
|
const Search = ref()
|
|
onMounted(() => {})
|
|
defineExpose({setFormValues,search}) // 提供 open 方法,用于打开弹窗
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<!-- update by 芋艿:class="-mb-15px" 用于降低和 ContentWrap 组件的底部距离,避免空隙过大 -->
|
|
<div ref="Search">
|
|
<Form ref="formRef"
|
|
:inline="inline"
|
|
:is-col="isCol"
|
|
:is-custom="false"
|
|
:label-width="labelWidth"
|
|
:schema="newSchema"
|
|
class="-mb-15px search"
|
|
:class="formClassNames"
|
|
hide-required-asterisk
|
|
@register="register"
|
|
@onInput="onInput"
|
|
@opensearchTable="opensearchTable"
|
|
@onChange="onChange"
|
|
@onEnter="onEnter"
|
|
@onSubmit="onSubmit"
|
|
@onBlur="onBlur"
|
|
>
|
|
<template #action>
|
|
<div v-if="layout === 'inline'">
|
|
<!-- update by 芋艿:去除搜索的 type="primary",颜色变淡一点 -->
|
|
<ElButton type="info" plain v-if="showSearch" @click="search">
|
|
<Icon class="mr-5px" icon="ep:search" />
|
|
{{ t('common.query') }}
|
|
</ElButton>
|
|
<!-- update by 芋艿:将 icon="ep:refresh-right" 修改成 icon="ep:refresh",和 ruoyi-vue 搜索保持一致 -->
|
|
<ElButton type="info" plain v-if="showReset" @click="reset">
|
|
<Icon class="mr-5px" icon="ep:refresh" />
|
|
{{ t('common.reset') }}
|
|
</ElButton>
|
|
<ElButton type="info" plain v-if="expand" text @click="setVisible">
|
|
{{ t(visible ? 'common.shrink' : 'common.expand') }}
|
|
<Icon :icon="visible ? 'ep:arrow-up' : 'ep:arrow-down'" />
|
|
</ElButton>
|
|
<!-- add by 芋艿:补充在搜索后的按钮 -->
|
|
<slot name="actionMore"></slot>
|
|
</div>
|
|
</template>
|
|
<template v-for="name in Object.keys($slots)" :key="name" #[name]>
|
|
<slot :name="name"></slot>
|
|
</template>
|
|
</Form>
|
|
</div>
|
|
|
|
<template v-if="layout === 'bottom'">
|
|
<div :style="bottonButtonStyle">
|
|
<ElButton v-if="showSearch" type="primary" @click="search">
|
|
<Icon class="mr-5px" icon="ep:search" />
|
|
{{ t('common.query') }}
|
|
</ElButton>
|
|
<ElButton v-if="showReset" @click="reset">
|
|
<Icon class="mr-5px" icon="ep:refresh-right" />
|
|
{{ t('common.reset') }}
|
|
</ElButton>
|
|
<ElButton v-if="expand" text @click="setVisible">
|
|
{{ t(visible ? 'common.shrink' : 'common.expand') }}
|
|
<Icon :icon="visible ? 'ep:arrow-up' : 'ep:arrow-down'" />
|
|
</ElButton>
|
|
<!-- add by 芋艿:补充在搜索后的按钮 -->
|
|
<slot name="actionMore"></slot>
|
|
</div>
|
|
</template>
|
|
<SearchTable ref="searchTableRef" :hiddenFilterBtnFields="hiddenFilterBtnFields" :showSearchTableQueryFields="showSearchTableQueryFields" @searchTableSuccess="searchTableSuccess" />
|
|
|
|
</template>
|
|
<style lang="scss" scoped>
|
|
.search ::v-deep(.el-form-item) {
|
|
margin-right: 1%;
|
|
width: 24%;
|
|
}
|
|
.dateSearch ::v-deep(.el-form-item) {
|
|
margin-right: 1%;
|
|
min-width: 320px;
|
|
width:32%;
|
|
}
|
|
.search ::v-deep(.el-form-item:nth-last-child(1)) {
|
|
margin-right: 0px;
|
|
width: auto;
|
|
.el-form-item__content {
|
|
flex: 1;
|
|
>div{
|
|
flex: 1;
|
|
button {
|
|
width: 46%;
|
|
max-width: 80px;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
</style>
|
|
|