|
|
@@ -12,6 +12,7 @@
|
|
|
>{{ t }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <!-- 发布日期(暂时注释,后面可能用到)
|
|
|
<div class="filter-row">
|
|
|
<span class="filter-label">发布日期</span>
|
|
|
<div class="filter-content">
|
|
|
@@ -28,6 +29,7 @@
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ -->
|
|
|
<div class="filter-row">
|
|
|
<span class="filter-label">发布单位</span>
|
|
|
<!-- 按钮模式 -->
|
|
|
@@ -46,11 +48,10 @@
|
|
|
@click="selectAuthority(d)"
|
|
|
>{{ d.shortName }}</span>
|
|
|
<span
|
|
|
- v-if="!loadingAuthorities"
|
|
|
+ v-if="!showSearch"
|
|
|
class="filter-tag more-tag"
|
|
|
@click="toggleSearch"
|
|
|
>更多</span>
|
|
|
- <span v-else class="filter-tag more-tag" style="cursor: default; opacity: 0.5;">加载中...</span>
|
|
|
</div>
|
|
|
<!-- 搜索模式 -->
|
|
|
<div v-else class="filter-content">
|
|
|
@@ -83,26 +84,11 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="filter-row">
|
|
|
- <span class="filter-label">关键词</span>
|
|
|
- <div class="filter-content">
|
|
|
- <el-input
|
|
|
- :model-value="keyword"
|
|
|
- placeholder="输入精准关键词进行检索"
|
|
|
- size="default"
|
|
|
- clearable
|
|
|
- class="keyword-input"
|
|
|
- @update:model-value="$emit('update:keyword', $event)"
|
|
|
- />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, onMounted, computed } from 'vue'
|
|
|
-import { getIssuingAuthorities } from '@/api/retrieval'
|
|
|
-import { ElMessage } from 'element-plus'
|
|
|
+import { ref, onMounted, computed, watch } from 'vue'
|
|
|
|
|
|
interface Authority {
|
|
|
shortName: string
|
|
|
@@ -110,70 +96,62 @@ interface Authority {
|
|
|
count: number
|
|
|
}
|
|
|
|
|
|
-const docTypes = ['全部', '法规制度', '技术标准', '操作指南', '通知公告', '工作报告']
|
|
|
+// 写死的发布单位列表
|
|
|
+const HARD_CODED_AUTHORITIES: string[] = [
|
|
|
|
|
|
-// 从数据库动态加载的发布单位列表(不含前5固定按钮)
|
|
|
-const allAuthorities = ref<Authority[]>([])
|
|
|
-const loadingAuthorities = ref(false)
|
|
|
+ '中华人民共和国住房和城乡建设部',
|
|
|
+ '中华人民共和国交通运输部',
|
|
|
+ '中华人民共和国建设部',
|
|
|
+ '中华人民共和国国家质量监督检验检疫总局',
|
|
|
+ '中国国家标准化管理委员会',
|
|
|
+]
|
|
|
|
|
|
-/** 生成简称:从全称中精简 */
|
|
|
-function makeShortName(fullName: string): string {
|
|
|
- // 去掉"中华人民共和国"前缀
|
|
|
- let name = fullName.replace(/^中华人民共和国/, '')
|
|
|
- // 常见精简规则
|
|
|
- name = name
|
|
|
- .replace('国家', '')
|
|
|
- .replace('委员会', '委')
|
|
|
- .replace('管理', '')
|
|
|
- return name
|
|
|
-}
|
|
|
+const docTypes = ['全部', '法规制度', '技术标准', '操作指南', '通知公告', '工作报告']
|
|
|
+
|
|
|
+// 初始化所有发布单位
|
|
|
+const allAuthorities = ref<Authority[]>(
|
|
|
+ HARD_CODED_AUTHORITIES.map((name) => ({ shortName: name, fullName: name, count: 0 }))
|
|
|
+)
|
|
|
|
|
|
-// 前5发布单位(用于按钮),取数量最多的
|
|
|
+// 前5发布单位(用于按钮展示)
|
|
|
const topAuthorities = computed(() => allAuthorities.value.slice(0, 5))
|
|
|
|
|
|
-async function loadAuthorities(keyword?: string) {
|
|
|
- if (loadingAuthorities.value) return
|
|
|
- loadingAuthorities.value = true
|
|
|
- try {
|
|
|
- const res: any = await getIssuingAuthorities(keyword)
|
|
|
- if (res.code === '1' && res.data?.authorities) {
|
|
|
- // 后端返回: { full_name, count }
|
|
|
- allAuthorities.value = res.data.authorities.map((a: any) => ({
|
|
|
- shortName: makeShortName(a.full_name),
|
|
|
- fullName: a.full_name,
|
|
|
- count: a.count,
|
|
|
- }))
|
|
|
- }
|
|
|
- } catch (e: any) {
|
|
|
- ElMessage.error('加载发布单位失败: ' + (e.message || '未知错误'))
|
|
|
- } finally {
|
|
|
- loadingAuthorities.value = false
|
|
|
+// 本地过滤发布单位(替代原来的 API 请求)
|
|
|
+function filterAuthorities(keyword: string) {
|
|
|
+ const kw = keyword.trim()
|
|
|
+ if (!kw) {
|
|
|
+ allAuthorities.value = HARD_CODED_AUTHORITIES.map((name) => ({
|
|
|
+ shortName: name,
|
|
|
+ fullName: name,
|
|
|
+ count: 0,
|
|
|
+ }))
|
|
|
+ return
|
|
|
}
|
|
|
+ allAuthorities.value = HARD_CODED_AUTHORITIES.filter((name) => name.includes(kw)).map(
|
|
|
+ (name) => ({ shortName: name, fullName: name, count: 0 })
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
-// 页面加载时预加载发布单位
|
|
|
+// 页面加载时初始化发布单位
|
|
|
onMounted(() => {
|
|
|
- loadAuthorities()
|
|
|
+ filterAuthorities('')
|
|
|
})
|
|
|
|
|
|
const props = defineProps<{
|
|
|
docType: string
|
|
|
department: string
|
|
|
dateRange: [string, string] | null
|
|
|
- keyword: string
|
|
|
}>()
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
'update:docType': [value: string]
|
|
|
'update:department': [value: string]
|
|
|
'update:dateRange': [value: [string, string] | null]
|
|
|
- 'update:keyword': [value: string]
|
|
|
change: [params: {
|
|
|
docType: string
|
|
|
department: string
|
|
|
publishDateFrom: string
|
|
|
publishDateTo: string
|
|
|
- keyword: string
|
|
|
}]
|
|
|
}>()
|
|
|
|
|
|
@@ -183,6 +161,14 @@ const showSearch = ref(false)
|
|
|
const searchInput = ref('')
|
|
|
const searchResults = ref<Authority[]>([])
|
|
|
const hasSearched = ref(false)
|
|
|
+// 同步父组件传入的 department(如从详情页返回时恢复筛选条件)
|
|
|
+watch(() => props.department, (newVal) => {
|
|
|
+ if (newVal && newVal !== issuingAuthority.value) {
|
|
|
+ issuingAuthority.value = newVal
|
|
|
+ searchInput.value = newVal
|
|
|
+ }
|
|
|
+}, { immediate: true })
|
|
|
+
|
|
|
let debounceTimer: ReturnType<typeof setTimeout> | null = null
|
|
|
let isSelectingFromList = false
|
|
|
|
|
|
@@ -211,11 +197,6 @@ function toggleSearch() {
|
|
|
searchInput.value = ''
|
|
|
searchResults.value = []
|
|
|
hasSearched.value = false
|
|
|
- } else {
|
|
|
- // 展开时如果没有数据,加载一次
|
|
|
- if (allAuthorities.value.length === 0) {
|
|
|
- loadAuthorities()
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -228,21 +209,10 @@ function onSearchInput(val: string) {
|
|
|
searchResults.value = []
|
|
|
return
|
|
|
}
|
|
|
- // 优先从已加载的列表中搜索
|
|
|
- let results = allAuthorities.value.filter(a =>
|
|
|
+ // 本地搜索
|
|
|
+ searchResults.value = allAuthorities.value.filter((a) =>
|
|
|
a.fullName.includes(val.trim()) || a.shortName.includes(val.trim())
|
|
|
)
|
|
|
- // 如果本地没搜到,调 API 搜索
|
|
|
- if (results.length === 0 && allAuthorities.value.length > 0) {
|
|
|
- loadAuthorities(val.trim()).then(() => {
|
|
|
- results = allAuthorities.value.filter(a =>
|
|
|
- a.fullName.includes(val.trim()) || a.shortName.includes(val.trim())
|
|
|
- )
|
|
|
- searchResults.value = results
|
|
|
- })
|
|
|
- } else {
|
|
|
- searchResults.value = results
|
|
|
- }
|
|
|
}, 300)
|
|
|
}
|
|
|
|
|
|
@@ -261,7 +231,6 @@ function emitChange(
|
|
|
department: department ?? props.department,
|
|
|
publishDateFrom: (dateRange ?? props.dateRange)?.[0] || '',
|
|
|
publishDateTo: (dateRange ?? props.dateRange)?.[1] || '',
|
|
|
- keyword: props.keyword,
|
|
|
})
|
|
|
}
|
|
|
</script>
|
|
|
@@ -416,12 +385,4 @@ function emitChange(
|
|
|
border-radius: 4px;
|
|
|
box-shadow: 0 0 0 1px #dcdfe6 inset;
|
|
|
}
|
|
|
-.keyword-input {
|
|
|
- width: 320px;
|
|
|
- max-width: 100%;
|
|
|
-}
|
|
|
-.keyword-input :deep(.el-input__wrapper) {
|
|
|
- border-radius: 4px;
|
|
|
- box-shadow: 0 0 0 1px #dcdfe6 inset;
|
|
|
-}
|
|
|
</style>
|