html
<template>
<div class="search-panel-container">
<div class="panel-header">
<el-popover placement="bottom-start" width="200" trigger="click">
<template #reference>
<el-button link>
当前模板: {{ searchStore.currentTemplateName || '自定义' }}
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</el-button>
</template>
<ul class="template-dropdown-list">
<li v-for="t in searchStore.templates" :key="t.id" @click="searchStore.applyTemplate(t)">
{{ t.name }}
</li>
<li class="manage-btn" @click="showManager = true">
<el-icon><Setting /></el-icon> 搜索模板管理
</li>
</ul>
</el-popover>
</div>
<div class="search-form-wrapper">
<el-form :inline="true" :model="searchStore.searchForm" class="demo-form-inline">
<template v-for="field in searchStore.activeFieldsConfig" :key="field.key">
<el-form-item :label="field.label">
<el-input
v-if="field.type === 'input'"
v-model="searchStore.searchForm[field.key]"
:placeholder="'Enter ' + field.label"
clearable
/>
<el-select
v-else-if="field.type === 'select'"
v-model="searchStore.searchForm[field.key]"
:placeholder="'Select ' + field.label"
clearable
style="width: 180px"
>
<el-option
v-for="opt in field.options"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<el-date-picker
v-else-if="field.type === 'date-picker'"
v-model="searchStore.searchForm[field.key]"
type="datetimerange"
start-placeholder="Start"
end-placeholder="End"
/>
</el-form-item>
</template>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
<el-button
v-if="canUpdateCurrentTemplate"
type="warning"
plain
@click="handleUpdateTemplate"
>
更新模板
</el-button>
<el-button @click="showSaveDialog">存为模板</el-button>
<el-button link type="primary" @click="showConfig = true"> 搜索项配置 </el-button>
</el-form-item>
</el-form>
</div>
<SearchConfigDialog v-model="showConfig" />
<TemplateManagerDialog v-model="showManager" />
</div>
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { ArrowDown, Setting } from '@element-plus/icons-vue'
import { useSearchStore } from '../../stores/searchStore'
import { ElMessageBox, ElMessage } from 'element-plus'
// import SearchConfigDialog from './SearchConfigDialog.vue'
import SearchConfigDialog from './DiySearchConfigDialog.vue'
import TemplateManagerDialog from './TemplateManagerDialog.vue'
const searchStore = useSearchStore()
const showConfig = ref(false)
const showManager = ref(false)
onMounted(() => {
searchStore.initData()
})
const handleSearch = () => {
console.log('发起查询,参数:', JSON.parse(JSON.stringify(searchStore.searchForm)))
ElMessage.info('查询请求已发出,请查看控制台')
}
const handleReset = () => {
searchStore.searchForm = {}
}
const showSaveDialog = () => {
ElMessageBox.prompt('请输入模板名称', '存为模板', {
confirmButtonText: '保存',
cancelButtonText: '取消',
})
.then(({ value }) => {
if (value) {
searchStore.saveAsTemplate(value)
}
})
.catch(() => {})
}
const canUpdateCurrentTemplate = computed(() => {
const tplId = searchStore.currentTemplateId
if (!tplId) return false
const tpl = searchStore.templates.find((t) => t.id === tplId)
// 核心判断:存在且允许更新
return tpl && tpl.permission && tpl.permission.canUpdate
})
const handleUpdateTemplate = async () => {
try {
await searchStore.updateCurrentTemplate()
ElMessage.success('当前模板已更新')
} catch (e) {
ElMessage.error('更新失败')
}
}
</script>
<style scoped>
.search-panel-container {
background: #fff;
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.panel-header {
margin-bottom: 12px;
border-bottom: 1px solid #eee;
padding-bottom: 8px;
}
.template-dropdown-list {
list-style: none;
padding: 0;
margin: 0;
}
.template-dropdown-list li {
padding: 8px 12px;
cursor: pointer;
border-bottom: 1px solid #f5f5f5;
}
.template-dropdown-list li:hover {
background-color: #f0f9eb;
color: #409eff;
}
.template-dropdown-list li.manage-btn {
color: #409eff;
border-top: 1px solid #eee;
margin-top: 4px;
}
</style>