fix: 路由跳转
This commit is contained in:
commit
cccdf73d54
|
@ -25,7 +25,7 @@
|
|||
"event-source-polyfill": "^1.0.31",
|
||||
"global": "^4.4.0",
|
||||
"jetlinks-store": "^0.0.3",
|
||||
"jetlinks-ui-components": "^1.0.4",
|
||||
"jetlinks-ui-components": "^1.0.5",
|
||||
"js-cookie": "^3.0.1",
|
||||
"less": "^4.1.3",
|
||||
"less-loader": "^11.1.0",
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
<template>
|
||||
<a-dropdown-button
|
||||
type='primary'
|
||||
@click='click'
|
||||
placement='bottomLeft'
|
||||
:visible='historyVisible'
|
||||
@visibleChange='visibleChange'
|
||||
>
|
||||
搜索
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<template v-if='!showEmpty'>
|
||||
<a-menu-item v-for='item in historyList' :key='item.id'>
|
||||
<div class='history-item'>
|
||||
<span @click.stop='itemClick(item.content)'>{{ item.name }}</span>
|
||||
<a-popconfirm
|
||||
title='确认删除吗?'
|
||||
placement='top'
|
||||
@confirm.stop='deleteHistory(item.id)'
|
||||
:okButtonProps='{
|
||||
loading: deleteLoading
|
||||
}'
|
||||
>
|
||||
<span class='delete'>
|
||||
<DeleteOutlined />
|
||||
</span>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</a-menu-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class='history-empty'>
|
||||
<a-empty />
|
||||
</div>
|
||||
</template>
|
||||
</a-menu>
|
||||
</template>
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
</a-dropdown-button>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='SearchHistory'>
|
||||
import { SearchOutlined, DeleteOutlined } from '@ant-design/icons-vue'
|
||||
import { deleteSearchHistory, getSearchHistory } from '@/api/comm'
|
||||
import type { SearchHistoryList } from 'components/Search/types'
|
||||
|
||||
type Emit = {
|
||||
(event: 'click'): void
|
||||
(event: 'itemClick', data: string): void
|
||||
}
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const props = defineProps({
|
||||
target: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const historyList = ref<SearchHistoryList[]>([])
|
||||
const historyVisible = ref(false)
|
||||
const deleteLoading = ref(false)
|
||||
const showEmpty = ref(false)
|
||||
|
||||
const visibleChange = async (visible: boolean) => {
|
||||
historyVisible.value = visible
|
||||
if (visible) {
|
||||
const resp = await getSearchHistory(props.target)
|
||||
if (resp.success && resp.result.length) {
|
||||
historyList.value = resp.result.filter(item => item.content)
|
||||
showEmpty.value = false
|
||||
} else {
|
||||
showEmpty.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const click = () => {
|
||||
emit('click')
|
||||
}
|
||||
|
||||
const itemClick = (content: string) => {
|
||||
historyVisible.value = false
|
||||
emit('itemClick', content)
|
||||
}
|
||||
|
||||
const deleteHistory = async (id: string) => {
|
||||
deleteLoading.value = true
|
||||
const resp = await deleteSearchHistory(props.target, id)
|
||||
deleteLoading.value = false
|
||||
if (resp.success) {
|
||||
historyVisible.value = false
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.history-empty {
|
||||
width: 200px;
|
||||
background-color: #fff;
|
||||
box-shadow: @box-shadow-base;
|
||||
border-radius: 2px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
width: 200px;
|
||||
display: flex;
|
||||
|
||||
> span {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.delete {
|
||||
padding: 0 6px;
|
||||
flex: 0 0 28px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,349 +0,0 @@
|
|||
<template>
|
||||
<div class='JSearch-item'>
|
||||
<div class='JSearch-item--type' v-if='expand'>
|
||||
<a-select
|
||||
v-if='index !== 1 && index !== 4'
|
||||
:options='typeOptions'
|
||||
v-model:value='termsModel.type'
|
||||
style='width: 100%;'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<span v-else>
|
||||
{{
|
||||
index === 1 ? '第一组' : '第二组'
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<a-select
|
||||
class='JSearch-item--column'
|
||||
:options='columnOptions'
|
||||
v-model:value='termsModel.column'
|
||||
@change='columnChange'
|
||||
/>
|
||||
<a-select
|
||||
class='JSearch-item--termType'
|
||||
:options='termTypeOptions.option'
|
||||
v-model:value='termsModel.termType'
|
||||
@change='termTypeChange'
|
||||
/>
|
||||
<div class='JSearch-item--value'>
|
||||
<a-input
|
||||
v-if='component === componentType.input'
|
||||
v-model:value='termsModel.value'
|
||||
style='width: 100%'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-select
|
||||
v-else-if='component === componentType.select'
|
||||
showSearch
|
||||
:loading='optionLoading'
|
||||
v-model:value='termsModel.value'
|
||||
:options='options'
|
||||
style='width: 100%'
|
||||
:filterOption='(v, option) => filterTreeSelectNode(v, option, "label")'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-input-number
|
||||
v-else-if='component === componentType.inputNumber'
|
||||
v-model:value='termsModel.value'
|
||||
style='width: 100%'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-input-password
|
||||
v-else-if='component === componentType.password'
|
||||
v-model:value='termsModel.value'
|
||||
style='width: 100%'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-switch
|
||||
v-else-if='component === componentType.switch'
|
||||
v-model:checked='termsModel.value'
|
||||
style='width: 100%'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-radio-group
|
||||
v-else-if='component === componentType.radio'
|
||||
v-model:value='termsModel.value'
|
||||
style='width: 100%'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-checkbox-group
|
||||
v-else-if='component === componentType.checkbox'
|
||||
v-model:value='termsModel.value'
|
||||
:options='options'
|
||||
style='width: 100%'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-time-picker
|
||||
v-else-if='component === componentType.time'
|
||||
valueFormat='HH:mm:ss'
|
||||
v-model:value='termsModel.value'
|
||||
style='width: 100%'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-date-picker
|
||||
v-else-if='component === componentType.date'
|
||||
showTime
|
||||
v-model:value='termsModel.value'
|
||||
valueFormat='YYYY-MM-DD HH:mm:ss'
|
||||
style='width: 100%'
|
||||
@change='valueChange'
|
||||
/>
|
||||
<a-tree-select
|
||||
v-else-if='component === componentType.treeSelect'
|
||||
showSearch
|
||||
v-model:value='termsModel.value'
|
||||
:tree-data='options'
|
||||
style='width: 100%'
|
||||
:fieldNames='{ label: "name", value: "id" }'
|
||||
@change='valueChange'
|
||||
:filterTreeNode='(v, option) => filterSelectNode(v, option)'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='SearchItem'>
|
||||
import { componentType } from 'components/Form'
|
||||
import { typeOptions, termType } from './util'
|
||||
import { PropType } from 'vue'
|
||||
import type { SearchItemData, SearchProps, Terms } from './types'
|
||||
import { cloneDeep, get, isArray, isFunction } from 'lodash-es'
|
||||
import { filterTreeSelectNode, filterSelectNode } from '@/utils/comm'
|
||||
import { useUrlSearchParams } from '@vueuse/core'
|
||||
|
||||
type ItemType = SearchProps['type']
|
||||
|
||||
interface Emit {
|
||||
(e: 'change', data: SearchItemData): void
|
||||
}
|
||||
type UrlParam = {
|
||||
q: string | null
|
||||
target: string | null
|
||||
}
|
||||
|
||||
const urlParams = useUrlSearchParams<UrlParam>('hash')
|
||||
|
||||
const props = defineProps({
|
||||
columns: {
|
||||
type: Array as PropType<SearchProps[]>,
|
||||
default: () => [],
|
||||
required: true
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
expand: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
termsItem: {
|
||||
type: Object as PropType<Terms>,
|
||||
default: {}
|
||||
},
|
||||
reset: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const termsModel = reactive<SearchItemData>({
|
||||
type: 'or',
|
||||
value: '',
|
||||
termType: 'like',
|
||||
column: ''
|
||||
})
|
||||
|
||||
const component = ref(componentType.input)
|
||||
|
||||
const options = ref<any[]>([])
|
||||
|
||||
const columnOptions = ref<({ label: string, value: string})[]>([])
|
||||
const columnOptionMap = new Map()
|
||||
|
||||
const termTypeOptions = reactive({option: termType})
|
||||
|
||||
const optionLoading = ref(false)
|
||||
|
||||
/**
|
||||
* 根据类型切换默termType值
|
||||
* @param type
|
||||
*/
|
||||
const getTermType = (type?: ItemType) => {
|
||||
termTypeOptions.option = termType
|
||||
switch (type) {
|
||||
case 'select':
|
||||
case 'treeSelect':
|
||||
case 'number':
|
||||
return 'eq'
|
||||
case 'date':
|
||||
case 'time':
|
||||
// 时间只有大于或小于两个值
|
||||
termTypeOptions.option = termType.filter(item => ['gt','lt'].includes(item.value))
|
||||
return 'gt'
|
||||
default:
|
||||
return 'like'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型返回组件
|
||||
* @param type
|
||||
*/
|
||||
const getComponent = (type?: ItemType) => {
|
||||
switch (type) {
|
||||
case 'select':
|
||||
component.value = componentType.select
|
||||
break;
|
||||
case 'treeSelect':
|
||||
component.value = componentType.treeSelect
|
||||
break;
|
||||
case 'date':
|
||||
component.value = componentType.date
|
||||
break;
|
||||
case 'time':
|
||||
component.value = componentType.time
|
||||
break;
|
||||
case 'number':
|
||||
component.value = componentType.inputNumber
|
||||
break;
|
||||
default:
|
||||
component.value = componentType.input
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const handleItemOptions = (option?: any[] | Function) => {
|
||||
options.value = []
|
||||
if (isArray(option)) {
|
||||
options.value = option
|
||||
} else if (isFunction(option)) {
|
||||
optionLoading.value = true
|
||||
option().then((res: any[]) => {
|
||||
optionLoading.value = false
|
||||
options.value = res
|
||||
}).catch((_: any) => {
|
||||
optionLoading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const columnChange = (value: string, isChange: boolean) => {
|
||||
const item = columnOptionMap.get(value)
|
||||
optionLoading.value = false
|
||||
// 设置value为undefined
|
||||
termsModel.column = value
|
||||
termsModel.termType = item.defaultTermType || getTermType(item.type)
|
||||
|
||||
getComponent(item.type) // 处理Item的组件类型
|
||||
|
||||
// 处理options 以及 request
|
||||
if ('options' in item) {
|
||||
handleItemOptions(item.options)
|
||||
}
|
||||
|
||||
termsModel.value = undefined
|
||||
|
||||
if (isChange) {
|
||||
valueChange()
|
||||
}
|
||||
}
|
||||
|
||||
const handleItem = () => {
|
||||
columnOptionMap.clear()
|
||||
columnOptions.value = []
|
||||
if (!props.columns.length) return
|
||||
|
||||
columnOptions.value = props.columns.map(item => { // 对columns进行Map处理以及值处理
|
||||
columnOptionMap.set(item.column, item)
|
||||
return {
|
||||
label: item.title,
|
||||
value: item.column
|
||||
}
|
||||
})
|
||||
|
||||
// 获取第一个值
|
||||
const sortColumn = cloneDeep(props.columns)
|
||||
sortColumn?.sort((a, b) => a.sortIndex! - b.sortIndex!)
|
||||
|
||||
const _index = props.index > sortColumn.length ? sortColumn.length - 1 : props.index
|
||||
const _itemColumn = sortColumn[_index - 1]
|
||||
|
||||
columnChange(_itemColumn.column, false)
|
||||
}
|
||||
|
||||
const termTypeChange = () => {
|
||||
valueChange()
|
||||
}
|
||||
|
||||
const valueChange = () => {
|
||||
|
||||
emit('change', {
|
||||
type: termsModel.type,
|
||||
value: termsModel.value,
|
||||
termType: termsModel.termType,
|
||||
column: termsModel.column,
|
||||
})
|
||||
}
|
||||
|
||||
const handleQuery = (_params: UrlParam) => {
|
||||
if (_params.q) {
|
||||
const path = props.index < 4 ? [0, 'terms', props.index - 1] : [1, 'terms', props.index - 4]
|
||||
const itemData: SearchItemData = get(props.termsItem.terms, path)
|
||||
if (itemData) {
|
||||
termsModel.type = itemData.type
|
||||
termsModel.column = itemData.column
|
||||
termsModel.termType = itemData.termType
|
||||
termsModel.value = itemData.value
|
||||
const item = columnOptionMap.get(itemData.column)
|
||||
getComponent(item.type) // 处理Item的组件类型
|
||||
|
||||
// 处理options 以及 request
|
||||
if ('options' in item) {
|
||||
handleItemOptions(item.options)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleItem()
|
||||
|
||||
nextTick(() => {
|
||||
handleQuery(urlParams)
|
||||
})
|
||||
|
||||
watch(() => props.reset, () => {
|
||||
handleItem()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.JSearch-item {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
|
||||
.JSearch-item--type {
|
||||
min-width: 80px;
|
||||
> span {
|
||||
line-height: 34px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.JSearch-item--column {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.JSearch-item--termType {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.JSearch-item--value {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,100 +0,0 @@
|
|||
<template>
|
||||
<a-popover
|
||||
title='搜索名称'
|
||||
trigger='click'
|
||||
v-model:visible='visible'
|
||||
@visibleChange='visibleChange'
|
||||
>
|
||||
<template #content>
|
||||
<div style='width: 240px'>
|
||||
<a-form ref='formRef' :model='modelRef'>
|
||||
<a-form-item
|
||||
name='name'
|
||||
:rules='[
|
||||
{ required: true, message: "请输入名称"}
|
||||
]'
|
||||
>
|
||||
<a-textarea
|
||||
v-model:value='modelRef.name'
|
||||
:rows='3'
|
||||
:maxlength='200'
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<a-button
|
||||
:loading='saveHistoryLoading'
|
||||
type='primary'
|
||||
class='save-btn'
|
||||
@click='saveHistory'
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<SaveOutlined />
|
||||
</template>
|
||||
保存
|
||||
</a-button>
|
||||
</a-popover>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='SaveHistory'>
|
||||
import type { Terms } from './types'
|
||||
import { PropType } from 'vue'
|
||||
import { saveSearchHistory } from '@/api/comm'
|
||||
import { SaveOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
const props = defineProps({
|
||||
terms: {
|
||||
type: Object as PropType<Terms>,
|
||||
default: () => ({})
|
||||
},
|
||||
target: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const searchName = ref('')
|
||||
|
||||
const saveHistoryLoading = ref(false)
|
||||
|
||||
const visible = ref(false)
|
||||
|
||||
const formRef = ref()
|
||||
|
||||
const modelRef = reactive({
|
||||
name: undefined
|
||||
})
|
||||
|
||||
/**
|
||||
* 保存当前查询条件
|
||||
*/
|
||||
const saveHistory = async () => {
|
||||
// 获取当前查询条件并转化为字符串
|
||||
const formData = await formRef.value.validate()
|
||||
if (formData) {
|
||||
formData.content = JSON.stringify(props.terms)
|
||||
saveHistoryLoading.value = true
|
||||
const resp = await saveSearchHistory(formData, props.target)
|
||||
saveHistoryLoading.value = false
|
||||
if (resp.success) {
|
||||
visible.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const visibleChange = (e: boolean) => {
|
||||
visible.value = e
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.save-btn {
|
||||
width: 100%
|
||||
}
|
||||
</style>
|
|
@ -1,83 +1,21 @@
|
|||
<template>
|
||||
<div :class="['JSearch-warp', props.class]" ref='searchRef'>
|
||||
<!-- 高级模式 -->
|
||||
<div v-if='props.type === "advanced"' :class='["JSearch-content senior", expand ? "senior-expand" : "", screenSize ? "big" : "small"]'>
|
||||
<div :class='["JSearch-items", expand ? "items-expand" : "", layout]'>
|
||||
<div class='left'>
|
||||
<SearchItem :expand='expand' :index='1' :columns='searchItems' @change='(v) => itemValueChange(v, 1)' :termsItem='terms' :reset='resetNumber'/>
|
||||
<SearchItem v-if='expand' :expand='expand' :index='2' :columns='searchItems' @change='(v) => itemValueChange(v, 2)' :termsItem='terms' :reset='resetNumber'/>
|
||||
<SearchItem v-if='expand' :expand='expand' :index='3' :columns='searchItems' @change='(v) => itemValueChange(v, 3)' :termsItem='terms' :reset='resetNumber'/>
|
||||
</div>
|
||||
<div class='center' v-if='expand'>
|
||||
<a-select
|
||||
v-model:value='termType'
|
||||
class='center-select'
|
||||
:options='typeOptions'
|
||||
<j-advanced-search
|
||||
:target='target'
|
||||
:type='type'
|
||||
:request='saveSearchHistory'
|
||||
:historyRequest='getSearchHistory'
|
||||
:columns='columns'
|
||||
@search='searchSubmit'
|
||||
/>
|
||||
</div>
|
||||
<div class='right' v-if='expand'>
|
||||
<SearchItem :expand='expand' :index='4' :columns='searchItems' @change='(v) => itemValueChange(v, 4)' :termsItem='terms' :reset='resetNumber'/>
|
||||
<SearchItem :expand='expand' :index='5' :columns='searchItems' @change='(v) => itemValueChange(v, 5)' :termsItem='terms' :reset='resetNumber'/>
|
||||
<SearchItem :expand='expand' :index='6' :columns='searchItems' @change='(v) => itemValueChange(v, 6)' :termsItem='terms' :reset='resetNumber'/>
|
||||
</div>
|
||||
</div>
|
||||
<div :class='["JSearch-footer", expand ? "expand" : ""]'>
|
||||
<div class='JSearch-footer--btns'>
|
||||
<History :target='target' @click='searchSubmit' @itemClick='historyItemClick' />
|
||||
<SaveHistory :terms='terms' :target='target'/>
|
||||
<a-button @click='reset'>
|
||||
<template #icon><RedoOutlined /></template>
|
||||
重置
|
||||
</a-button>
|
||||
</div>
|
||||
<a-button type='link' class='more-btn' @click='expandChange'>
|
||||
更多筛选
|
||||
<DownOutlined :class='["more-icon",expand ? "more-up" : "more-down"]' />
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 简单模式 -->
|
||||
<div v-else class='JSearch-content simple big'>
|
||||
<div class='JSearch-items'>
|
||||
<div class='left'>
|
||||
<SearchItem :expand='false' :index='1' :columns='searchItems' @change='(v) => itemValueChange(v, 1)' :termsItem='terms' :reset='resetNumber'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class='JSearch-footer'>
|
||||
<div class='JSearch-footer--btns'>
|
||||
<a-button type="primary" @click='searchSubmit'>
|
||||
<template #icon><SearchOutlined /></template>
|
||||
搜索
|
||||
</a-button>
|
||||
<a-button @click='reset'>
|
||||
<template #icon><RedoOutlined /></template>
|
||||
重置
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name='Search'>
|
||||
import SearchItem from './Item.vue'
|
||||
import { typeOptions } from './util'
|
||||
import { useElementSize, useUrlSearchParams } from '@vueuse/core'
|
||||
import { cloneDeep, isFunction, isString, set } from 'lodash-es'
|
||||
import { SearchOutlined, DownOutlined, RedoOutlined } from '@ant-design/icons-vue';
|
||||
<script setup lang='ts' name='ProSearch'>
|
||||
import { PropType } from 'vue'
|
||||
import { JColumnsProps } from 'components/Table/types'
|
||||
import SaveHistory from './SaveHistory.vue'
|
||||
import History from './History.vue'
|
||||
import type { SearchItemData, SearchProps, Terms } from './types'
|
||||
|
||||
type UrlParam = {
|
||||
q: string | null
|
||||
target: string | null
|
||||
}
|
||||
import { saveSearchHistory, getSearchHistory } from '@/api/comm'
|
||||
|
||||
interface Emit {
|
||||
(e: 'search', data: Terms): void
|
||||
(e: 'search', data: any): void
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -98,299 +36,20 @@ const props = defineProps({
|
|||
class: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// defaultTerms: {
|
||||
// type: Object,
|
||||
// default: () => ({})
|
||||
// }
|
||||
}
|
||||
})
|
||||
|
||||
const searchRef = ref(null)
|
||||
const { width } = useElementSize(searchRef)
|
||||
|
||||
const urlParams = useUrlSearchParams<UrlParam>('hash')
|
||||
|
||||
// 是否展开更多筛选
|
||||
const expand = ref(false)
|
||||
|
||||
// 第一组,第二组的关系
|
||||
const termType = ref('and')
|
||||
// 搜索历史记录
|
||||
const historyList = ref([])
|
||||
|
||||
// 组件方向
|
||||
const layout = ref('horizontal')
|
||||
// 当前组件宽度 true 大于1000
|
||||
const screenSize = ref(true)
|
||||
const resetNumber = ref(1)
|
||||
|
||||
const searchItems = ref<SearchProps[]>([])
|
||||
|
||||
// 当前查询条件
|
||||
const terms = reactive<Terms>({ terms: [] })
|
||||
|
||||
const columnOptionMap = new Map()
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
const expandChange = () => {
|
||||
expand.value = !expand.value
|
||||
}
|
||||
|
||||
const searchParams = reactive({
|
||||
data: {}
|
||||
})
|
||||
|
||||
const handleItems = () => {
|
||||
searchItems.value = []
|
||||
columnOptionMap.clear()
|
||||
const cloneColumns = cloneDeep(props.columns)
|
||||
cloneColumns!.forEach((item, index) => {
|
||||
if (item.search && Object.keys(item.search).length) {
|
||||
columnOptionMap.set(item.dataIndex, item.search)
|
||||
searchItems.value.push({
|
||||
...item.search,
|
||||
sortIndex: item.search.first ? 0 : index + 1,
|
||||
title: item.title,
|
||||
column: item.dataIndex,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const itemValueChange = (value: SearchItemData, index: number) => {
|
||||
if (index < 4) { // 第一组数据
|
||||
set(terms.terms, [0, 'terms', index - 1], value)
|
||||
} else { // 第二组数据
|
||||
set(terms.terms, [1, 'terms', index - 4], value)
|
||||
}
|
||||
}
|
||||
|
||||
const addUrlParams = () => {
|
||||
urlParams.q = JSON.stringify(terms)
|
||||
urlParams.target = props.target
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理termType为like,nlike的值
|
||||
* @param v
|
||||
*/
|
||||
const handleLikeValue = (v: string) => {
|
||||
if (isString(v)) {
|
||||
return v.split('').reduce((pre: string, next: string) => {
|
||||
let _next = next
|
||||
if (next === '\\') {
|
||||
_next = '\\\\'
|
||||
} else if (next === '%') {
|
||||
_next = '\\%'
|
||||
}
|
||||
return pre + _next
|
||||
}, '')
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理为外部使用
|
||||
*/
|
||||
const handleParamsFormat = () => {
|
||||
// 过滤掉terms中value无效的item
|
||||
const cloneParams = cloneDeep(terms)
|
||||
return {
|
||||
terms: cloneParams.terms.map(item => {
|
||||
if (item.terms) {
|
||||
item.terms = item.terms.filter(iItem => iItem && iItem.value)
|
||||
.map(iItem => {
|
||||
// 处理handleValue和rename
|
||||
const _item = columnOptionMap.get(iItem.column)
|
||||
if (_item.rename) {
|
||||
iItem.column = _item.rename
|
||||
}
|
||||
|
||||
if (_item.handleValue && isFunction(_item.handleValue)) {
|
||||
iItem.value = _item.handleValue(iItem.value)
|
||||
}
|
||||
|
||||
if (['like','nlike'].includes(iItem.termType) && !!iItem.value) {
|
||||
iItem.value = `%${handleLikeValue(iItem.value)}%`
|
||||
}
|
||||
return iItem
|
||||
})
|
||||
}
|
||||
return item
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交
|
||||
*/
|
||||
const searchSubmit = () => {
|
||||
emit('search', handleParamsFormat())
|
||||
console.log('searchSubmit')
|
||||
if (props.type === 'advanced') {
|
||||
addUrlParams()
|
||||
const searchSubmit = (data: any) => {
|
||||
emit('search', data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置查询
|
||||
*/
|
||||
const reset = () => {
|
||||
terms.terms = []
|
||||
expand.value = false
|
||||
if (props.type === 'advanced') {
|
||||
urlParams.q = null
|
||||
urlParams.target = null
|
||||
}
|
||||
resetNumber.value += 1
|
||||
emit('search', { terms: []})
|
||||
}
|
||||
|
||||
watch(width, (value) => {
|
||||
if (value < 1000) {
|
||||
layout.value = 'vertical'
|
||||
screenSize.value = false
|
||||
} else {
|
||||
layout.value = 'horizontal'
|
||||
screenSize.value = true
|
||||
}
|
||||
})
|
||||
|
||||
const historyItemClick = (content: string) => {
|
||||
try {
|
||||
terms.terms = JSON.parse(content)?.terms || []
|
||||
if (terms.terms.length === 2) {
|
||||
expand.value = true
|
||||
}
|
||||
addUrlParams()
|
||||
} catch (e) {
|
||||
console.warn(`Search组件中handleUrlParams处理JSON时异常:【${e}】`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理URL中的查询参数
|
||||
* @param _params
|
||||
*/
|
||||
const handleUrlParams = (_params: UrlParam) => {
|
||||
// URL中的target和props的一致,则还原查询参数
|
||||
if (_params.target === props.target && _params.q) {
|
||||
try {
|
||||
terms.terms = JSON.parse(_params.q)?.terms || []
|
||||
if (terms.terms.length === 2) {
|
||||
expand.value = true
|
||||
}
|
||||
emit('search', handleParamsFormat())
|
||||
} catch (e) {
|
||||
console.warn(`Search组件中handleUrlParams处理JSON时异常:【${e}】`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
handleUrlParams(urlParams)
|
||||
})
|
||||
|
||||
handleItems()
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
.JSearch-warp {
|
||||
padding: 24px;
|
||||
background-color: #fff;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.JSearch-content {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
|
||||
.JSearch-items,& .JSearch-footer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.JSearch-items {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
|
||||
.left, & .right {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex-direction: column;
|
||||
width: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
flex-direction: column;
|
||||
.left,& .right,& .center {
|
||||
width: 100%;
|
||||
}
|
||||
.center {
|
||||
flex-direction: row;
|
||||
}
|
||||
.center-select {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.JSearch-footer {
|
||||
display: flex;
|
||||
gap: 64px;
|
||||
position: relative;
|
||||
|
||||
&.expand {
|
||||
margin-top: 12px;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
|
||||
.more-btn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.JSearch-footer--btns {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
&.senior-expand {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.more-up {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
|
||||
&.big {
|
||||
gap: 64px;
|
||||
}
|
||||
|
||||
&.small {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&.simple {
|
||||
.JSearch-items {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.JSearch-footer {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -5,7 +5,7 @@ import JTable from './Table/index'
|
|||
import TitleComponent from "./TitleComponent/index.vue";
|
||||
import Form from './Form';
|
||||
import CardBox from './CardBox/index.vue';
|
||||
// import Search from './Search'
|
||||
import Search from './Search'
|
||||
import NormalUpload from './NormalUpload/index.vue'
|
||||
import FileFormat from './FileFormat/index.vue'
|
||||
import JProUpload from './JUpload/index.vue'
|
||||
|
@ -25,7 +25,7 @@ export default {
|
|||
.component('TitleComponent', TitleComponent)
|
||||
.component('Form', Form)
|
||||
.component('CardBox', CardBox)
|
||||
// .component('Search', Search)
|
||||
.component('ProSearch', Search)
|
||||
.component('NormalUpload', NormalUpload)
|
||||
.component('FileFormat', FileFormat)
|
||||
.component('JProUpload', JProUpload)
|
||||
|
|
|
@ -8,7 +8,7 @@ export const AccountMenu = {
|
|||
meta: {
|
||||
title: '个人中心',
|
||||
icon: '',
|
||||
hideInMenu: false
|
||||
hideInMenu: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
|
|
@ -37,6 +37,10 @@ type MenuStateType = {
|
|||
}
|
||||
}
|
||||
siderMenus: MenuItem[]
|
||||
params: {
|
||||
key: string
|
||||
params: Record<string, any>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,6 +48,10 @@ export const useMenuStore = defineStore({
|
|||
id: 'menu',
|
||||
state: (): MenuStateType => ({
|
||||
menus: {},
|
||||
params: {
|
||||
key: '',
|
||||
params: {}
|
||||
},
|
||||
siderMenus: []
|
||||
}),
|
||||
getters: {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
@cancel="_vis = false"
|
||||
:confirmLoading="loading"
|
||||
>
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
target="media"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!-- 国标级联-通道列表 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
target="media"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
:columns="columns"
|
||||
target="media-cascade"
|
||||
@search="handleSearch"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
target="product"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
:columns="columns"
|
||||
target="notice-config"
|
||||
@search="handleSearch"
|
||||
|
|
|
@ -135,11 +135,14 @@
|
|||
v-model:value="
|
||||
formData.configuration.port
|
||||
"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
/>
|
||||
<j-checkbox
|
||||
v-model:value="
|
||||
v-model:checked="
|
||||
formData.configuration.ssl
|
||||
"
|
||||
@change="handleSslChange"
|
||||
>
|
||||
开启SSL
|
||||
</j-checkbox>
|
||||
|
@ -408,7 +411,6 @@ const { resetFields, validate, validateInfos, clearValidate } = useForm(
|
|||
);
|
||||
|
||||
const getDetail = async () => {
|
||||
console.log('getDetail', route)
|
||||
if (route.params.id === ':id') return;
|
||||
const res = await configApi.detail(route.params.id as string);
|
||||
// formData.value = res.result;
|
||||
|
@ -438,6 +440,12 @@ const handleProviderChange = () => {
|
|||
resetPublicFiles();
|
||||
};
|
||||
|
||||
const handleSslChange = () => {
|
||||
formData.value.configuration.port = formData.value.configuration.ssl
|
||||
? 465
|
||||
: 25;
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置字段值
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<j-modal v-model:visible="_vis" title="通知记录" :footer="null" width="70%">
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
@search="handleSearch"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
:columns="columns"
|
||||
target="notice-config"
|
||||
@search="handleSearch"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<j-modal v-model:visible="_vis" title="通知记录" :footer="null" width="70%">
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
@search="handleSearch"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<j-advanced-search
|
||||
<pro-search
|
||||
:columns="columns"
|
||||
target="notice-config"
|
||||
@search="handleSearch"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
:format='myFormat'
|
||||
:valueFormat='myFormat'
|
||||
:getPopupContainer='getPopupContainer'
|
||||
popupClassName='manual-time-picker-popup'
|
||||
@change='change'
|
||||
/>
|
||||
</div>
|
||||
|
@ -62,7 +63,7 @@ const change = (e: string) => {
|
|||
}
|
||||
</script>
|
||||
|
||||
<style lang='less' scoped>
|
||||
<style lang='less'>
|
||||
.dropdown-time-picker {
|
||||
>div{
|
||||
position: relative !important;
|
||||
|
@ -80,6 +81,9 @@ const change = (e: string) => {
|
|||
.ant-picker-panel {
|
||||
width: 100%
|
||||
}
|
||||
.ant-picker-footer {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-picker-panel-container {
|
||||
|
|
|
@ -20,6 +20,10 @@ export const getComponent = (type: string): string => {
|
|||
return 'date'
|
||||
case 'tree':
|
||||
return 'tree'
|
||||
case 'file':
|
||||
return 'file'
|
||||
case 'geoPoint':
|
||||
return 'geoPoint'
|
||||
default:
|
||||
return 'input'
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<j-advanced-search :columns="columns" target="scene" @search="handleSearch" />
|
||||
<pro-search :columns="columns" target="scene" @search="handleSearch" />
|
||||
<JProTable
|
||||
ref="sceneRef"
|
||||
:columns="columns"
|
||||
|
|
|
@ -3693,10 +3693,10 @@ jetlinks-store@^0.0.3:
|
|||
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
||||
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
||||
|
||||
jetlinks-ui-components@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.4.tgz#41d52892f0f4d38adc6df02a87290a3042eb5645"
|
||||
integrity sha512-aX+XiGigzxZnrG52xqipxd+WuFwBeZ6+dvLkcvOfLLBqSu8sgfvr/8NJ5hFgv5Eo2QFnUJq3Qf4HXLw9Ogv/yw==
|
||||
jetlinks-ui-components@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#de995a654e2613c988fac2e800b156285265c9be"
|
||||
integrity sha512-rZtqFmxhU9nplFqqp45bHJAoiH4zzLM8juMGQV6eCCkzquXLmDqATiAK2D/fquAcLMIY0fPgw/Dzc9odQDKmVg==
|
||||
dependencies:
|
||||
"@vueuse/core" "^9.12.0"
|
||||
ant-design-vue "^3.2.15"
|
||||
|
|
Loading…
Reference in New Issue