merge junjie_dev into master

update: 头部搜索能力补全

Created-by: user8949
Commit-by: @user8949
Merged-by: user8949
Description: update: 头部搜索功能补全
update: 头部搜索能力补全
update: 头部搜索能力补全

See merge request: hk_openRepo/OpenRepo_Portal!52
This commit is contained in:
user8949
2025-03-19 21:08:38 +08:00
6 changed files with 127 additions and 42 deletions

View File

@@ -5,7 +5,7 @@
<d-row :gutter="16"> <d-row :gutter="16">
<d-col :span="8"> <d-col :span="8">
<d-form-item field="name" label="软件名称"> <d-form-item field="name" label="软件名称">
<d-input placeholder="请输入软件名称" v-model="formData.searchWord"/> <d-input placeholder="请输入软件名称" v-model="formData.softwareName"/>
</d-form-item> </d-form-item>
</d-col> </d-col>
<d-col :span="8"> <d-col :span="8">
@@ -37,6 +37,18 @@
</d-form-item> </d-form-item>
</d-col> </d-col>
</d-row> </d-row>
<d-row :gutter="16">
<d-col :span="8">
<d-form-item field="interestTag" label="兴趣标签">
<d-input v-model="formData.interestTag"/>
</d-form-item>
</d-col>
<d-col :span="8">
<d-form-item field="industry" label="行业">
<d-input v-model="formData.industry"/>
</d-form-item>
</d-col>
</d-row>
<slot name="operation"> <slot name="operation">
<gc-form-operation style="display: flex; justify-content: center; gap: 8px;"> <gc-form-operation style="display: flex; justify-content: center; gap: 8px;">
<d-button style="width: 96px; height: 32px;" variant="solid" @click="submitForm">搜索</d-button> <d-button style="width: 96px; height: 32px;" variant="solid" @click="submitForm">搜索</d-button>
@@ -59,10 +71,12 @@ const props = defineProps({
type: Object, type: Object,
default: () => ({ default: () => ({
licenseName: '', licenseName: '',
searchWord: '', softwareName: '',
softwareVersion: '', softwareVersion: '',
dependentSoftware: '', dependentSoftware: '',
programmingLanguage: '', programmingLanguage: '',
interestTag: '',
industry: '',
dateRange: ['', ''] dateRange: ['', '']
}) })
} }
@@ -91,10 +105,12 @@ const submitForm = () => {
const cancel = () => { const cancel = () => {
formData.value = { formData.value = {
licenseName: '', licenseName: '',
searchWord: '', softwareName: '',
softwareVersion: '', softwareVersion: '',
dependentSoftware: '', dependentSoftware: '',
programmingLanguage: '', programmingLanguage: '',
interestTag: '',
industry: '',
dateRange: ['', ''] dateRange: ['', '']
} }
emit('cancel'); emit('cancel');

View File

@@ -1,9 +1,9 @@
<template> <template>
<d-input <d-input
:key="$route.path + $route.query?.val" id="golbalSearch" class="g-header-search" :key="$route.path + $route.query?.val" id="golbalSearch" class="g-header-search"
v-model.trim="searchStr" placeholder="输入搜索内容..." @keyup.enter="search" @clear="handleClear" clearable > v-model.trim="softwareName" placeholder="输入软件名称搜索" @clear="handleClear" clearable >
<template #prepend> <template #prepend>
<d-dropdown @toggle="onCateToggle($event)"> <d-dropdown>
<div class="flex items-center gap-1 cursor-pointer"> <div class="flex items-center gap-1 cursor-pointer">
{{ searchType }} {{ searchType }}
<d-icon :rotate="cateRotate" name="icon-chevron-down-2"></d-icon> <d-icon :rotate="cateRotate" name="icon-chevron-down-2"></d-icon>
@@ -37,12 +37,18 @@
<script setup> <script setup>
import { ref, onMounted, watch, onUnmounted, reactive } from 'vue'; import { ref, onMounted, watch, onUnmounted, reactive } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useGlobalInfoStore } from '@/stores/Global';
import microApp from '@micro-zoe/micro-app'; import microApp from '@micro-zoe/micro-app';
const emit = defineEmits('updateSearch');
const globalInfo = useGlobalInfoStore();
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const searchStr = ref(route?.query?.val || '');
const searchType = ref('软件'); const softwareName = ref(globalInfo.headerSearch.softwareName);
const searchType = ref(globalInfo.headerSearch.searchType);
const position = ref(['right-start', 'right-end']); const position = ref(['right-start', 'right-end']);
const industryOptions = ref(['通信', '军工', '金融', '能源']); const industryOptions = ref(['通信', '军工', '金融', '能源']);
@@ -50,17 +56,15 @@ const placeholder = ref('「开搜」一搜即达开发者的AI搜索');
const onCategoryChange = (event) => { const onCategoryChange = (event) => {
searchType.value = event; searchType.value = event;
globalInfo.updateHeaderSearch({ softwareName: softwareName.value, searchType: searchType.value });
} }
const search = () => { const search = () => {
if (!searchStr.value) { window.open(`/repoList?softwareName=${softwareName.value ? softwareName.value : ''}&searchType=${searchType.value}`, '_blank')
document.querySelector('#golbalSearch').blur();
return;
}
router.push({ name: 'Search', query: { searchWord: searchStr.value || '', type: route?.query?.type || 'software' }});
}; };
const handleClear = () => { const handleClear = () => {
router.push({ name: 'home' }); globalInfo.updateHeaderSearch({ softwareName: ''.value, searchType: searchType.value });
}; };
watch(() => route.query?.val, (newVal) => { watch(() => route.query?.val, (newVal) => {
@@ -70,7 +74,7 @@ watch(() => route.query?.val, (newVal) => {
const handleDataChange = ({ name, type, data }) => { const handleDataChange = ({ name, type, data }) => {
if (name === 'micoro-app-homeweb-app') { if (name === 'micoro-app-homeweb-app') {
if (type === 'keyword-change') { if (type === 'keyword-change') {
searchStr.value = data; softwareName.value = data;
} }
if (type === 'route-change') { if (type === 'route-change') {
// //
@@ -79,7 +83,9 @@ const handleDataChange = ({ name, type, data }) => {
}; };
onMounted(() => { onMounted(() => {
globalInfo.updateHeaderSearch({ softwareName: route.query.softwareName ? route.query.softwareName : '', searchType: route.query.searchType || '软件' });
softwareName.value = route.query.softwareName;
searchType.value = route.query.searchType || '软件';
}); });
onUnmounted(() => { onUnmounted(() => {

View File

@@ -14,6 +14,10 @@ export const useGlobalInfoStore = defineStore('globalInfo', () => {
const showTools = ref(true); // 是否展示工具栏 const showTools = ref(true); // 是否展示工具栏
const namespaceType = ref(-1); // 0 - 用户 1 - 组织 const namespaceType = ref(-1); // 0 - 用户 1 - 组织
const globalTheme = ref('light'); // 网站主题 const globalTheme = ref('light'); // 网站主题
const headerSearch = ref({
searchType: '软件',
softwareName: ''
})
const menuInfo = computed(() => { const menuInfo = computed(() => {
// 当前菜单 // 当前菜单
@@ -63,6 +67,11 @@ export const useGlobalInfoStore = defineStore('globalInfo', () => {
} }
}; };
const updateHeaderSearch = (data: any) => {
headerSearch.value = { ...data };
}
/** /**
* 设置菜单标题旁的数字mr数量成员数量 * 设置菜单标题旁的数字mr数量成员数量
* @param id 菜单id * @param id 菜单id
@@ -107,6 +116,7 @@ export const useGlobalInfoStore = defineStore('globalInfo', () => {
showTools, showTools,
namespaceType, namespaceType,
globalTheme, globalTheme,
headerSearch,
setMenuType, setMenuType,
updateMenuNum, updateMenuNum,
setMenuInfo, setMenuInfo,
@@ -114,6 +124,7 @@ export const useGlobalInfoStore = defineStore('globalInfo', () => {
setIsNotFound, setIsNotFound,
setShowTools, setShowTools,
setNamespaceType, setNamespaceType,
setGlobalTheme setGlobalTheme,
updateHeaderSearch
}; };
}); });

View File

@@ -87,11 +87,11 @@
@click="openWarningDetail(item, index)" @click="openWarningDetail(item, index)"
> >
<span>{{ item.subject }}</span> <span>{{ item.subject }}</span>
<d-tag :color="tagMap[item.importance]" size="sm">{{ item.importance }}</d-tag> <d-tag v-if="item.importance" :color="tagMap[item.importance].color" size="sm">{{ tagMap[item.importance].text }}</d-tag>
</div> </div>
<div class="time-container"> <div class="time-container">
<d-icon name="icon-time"></d-icon> <d-icon name="icon-time"></d-icon>
{{ item.pulishTime }} {{ item.publishTime }}
</div> </div>
</div> </div>
</template> </template>
@@ -117,7 +117,8 @@ import { useAccount } from '@/utils/hooks/useAccount';
import AdvanceSearch from '@/components/AdvanceSearch/index.vue'; import AdvanceSearch from '@/components/AdvanceSearch/index.vue';
import { getHomeNoticeList } from '@/api/jyh'; import { getHomeNoticeList } from '@/api/jyh';
import EarlyWarningDetail from '@/views/Jyh/PersonalCenter/Detail/EarlyWarningDetail.vue'; import EarlyWarningDetail from '@/views/Jyh/PersonalCenter/Detail/EarlyWarningDetail.vue';
import { useGlobalInfoStore } from '@/stores/Global';
const { updateHeaderSearch } = useGlobalInfoStore();
const { accountInfo } = useAccount(); const { accountInfo } = useAccount();
const route = useRoute(); const route = useRoute();
@@ -141,10 +142,23 @@ const homeSearch = ref(null);
const dropdownWidth = ref(0); const dropdownWidth = ref(0);
const selectedCate = ref('软件'); const selectedCate = ref('软件');
const tagMap = { const tagMap = {
: '#f66f6a', 'Critical': {
: '#fac20a', text: '致命',
: '#5e7ce0' color: '#c7000b'
}; },
'High': {
text: '高',
color: '#f66f6a'
},
'Medium': {
text: '中',
color: '#fac20a'
},
'Low': {
text: '低',
color: '#5e7ce0'
}
}
const searchInput = ref(null); const searchInput = ref(null);
const openAdvancedSearch = () => { const openAdvancedSearch = () => {
@@ -184,7 +198,8 @@ const updateDropdownWidth = () => {
}; };
const search = () => { const search = () => {
router.push({ name: 'Search', query: { searchWord: searchStr.value, searchType: selectedCate.value } }); updateHeaderSearch({ searchWord: searchStr.value, searchType: selectedCate.value })
router.push({ name: 'Search' });
}; };
const onCategoryChange = (cate) => { const onCategoryChange = (cate) => {
@@ -431,7 +446,7 @@ getNoticeList();
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
width: 120px; width: 140px;
flex-shrink: 0; flex-shrink: 0;
} }

View File

@@ -5,7 +5,7 @@
<div class="sub-title mt-3"> <div class="sub-title mt-3">
<div> <div>
<span>重要性</span> <span>重要性</span>
<d-tag type="danger" size="sm">{{warningData.importance}}</d-tag> <d-tag size="sm" :color="tagMap[warningData.importance].color">{{tagMap[warningData.importance].text}}</d-tag>
</div> </div>
<div v-if="propsData.type === 'system'"> <div v-if="propsData.type === 'system'">
<d-button v-show="mode === 'readonly'" class="edit-btn" icon="icon-edit" variant="text" title="编辑" @click="handleModeChange"/> <d-button v-show="mode === 'readonly'" class="edit-btn" icon="icon-edit" variant="text" title="编辑" @click="handleModeChange"/>
@@ -39,6 +39,24 @@ const toolbarConfig = [
['h1', 'h2', 'bold', 'italic', 'strike', 'underline', 'color', 'font'], ['h1', 'h2', 'bold', 'italic', 'strike', 'underline', 'color', 'font'],
['ul', 'ol', 'checklist', 'code', 'link', 'image', 'table'], ['ul', 'ol', 'checklist', 'code', 'link', 'image', 'table'],
]; ];
const tagMap = {
'Critical': {
text: '致命',
color: '#c7000b'
},
'High': {
text: '高',
color: '#f66f6a'
},
'Medium': {
text: '中',
color: '#fac20a'
},
'Low': {
text: '低',
color: '#5e7ce0'
}
}
const mode = ref('readonly'); const mode = ref('readonly');
console.log(propsData.warningData) console.log(propsData.warningData)
warningData.value = propsData.warningData ?? { warningData.value = propsData.warningData ?? {

View File

@@ -6,7 +6,7 @@
</AdvanceSearch> </AdvanceSearch>
<div class="jyh-form-operation"> <div class="jyh-form-operation">
<d-button @click="getReleaseList" class="mr-2" variant="solid">搜索</d-button> <d-button @click="getReleaseList" class="mr-2" variant="solid">搜索</d-button>
<d-button variant="solid" color="secondary">清空</d-button> <d-button variant="solid" color="secondary" @click="clear">清空</d-button>
</div> </div>
<div class="left-btn"> <div class="left-btn">
<d-button v-if="isLogin" class="output-btn" icon="icon-share" variant="text">导出</d-button> <d-button v-if="isLogin" class="output-btn" icon="icon-share" variant="text">导出</d-button>
@@ -124,6 +124,7 @@ import { useAccountStore } from '@/stores/user';
const { formatTime } = useTimeFormat(); const { formatTime } = useTimeFormat();
import { releasePage } from '@/api/jyh'; import { releasePage } from '@/api/jyh';
import { useTimeFormat } from '@/utils/hooks/useTimeFormat'; import { useTimeFormat } from '@/utils/hooks/useTimeFormat';
import { useGlobalInfoStore } from '@/stores/Global';
const { namespace } = getOrgInfo(); const { namespace } = getOrgInfo();
const userInfo = useAccountStore(); const userInfo = useAccountStore();
const { isLogin } = storeToRefs(userInfo); const { isLogin } = storeToRefs(userInfo);
@@ -138,16 +139,28 @@ const typeOptions = reactive(['主软件', '依赖软件']);
const riskOptions = reactive(['低', '中', '高']); const riskOptions = reactive(['低', '中', '高']);
const useTypeOptions = reactive(['软件', '文档', '文档+软件']); const useTypeOptions = reactive(['软件', '文档', '文档+软件']);
const isUseOptions = reactive(['是', '否']); const isUseOptions = reactive(['是', '否']);
const globalInfo = useGlobalInfoStore();
const headerSearch = ref(globalInfo.headerSearch)
const newFormData = ref({ const newFormData = ref({
licenseName: '', licenseName: '',
searchType: 'software', searchType: headerSearch.value.searchType ? headerSearch.value.searchType : 'software',
searchWord: '', softwareName: '',
softwareVersion: '', softwareVersion: '',
dependentSoftware: '', dependentSoftware: '',
programmingLanguage: '', programmingLanguage: '',
interestTag: '',
industry: '',
dateRange: ['', ''] dateRange: ['', '']
}) })
watch(() => globalInfo.headerSearch, (newVal: any) => {
headerSearch.value = newVal;
console.log(newVal)
newFormData.value.searchType = newVal.searchType;
newFormData.value.softwareName = newVal.softwareName;
getReleaseList();
}, { deep: true })
const pager = ref({ const pager = ref({
total: 10, total: 10,
pageIndex: 1, pageIndex: 1,
@@ -195,6 +208,22 @@ const showColumnList = ref(false);
const countryModalRef = ref(null); const countryModalRef = ref(null);
const orgModalRef = ref(null); const orgModalRef = ref(null);
// 清空高级搜索
const clear = () => {
newFormData.value = {
licenseName: '',
searchType: headerSearch.value.searchType ? headerSearch.value.searchType : 'software',
softwareName: '',
softwareVersion: '',
dependentSoftware: '',
programmingLanguage: '',
interestTag: '',
industry: '',
dateRange: ['', '']
}
getReleaseList();
}
// 打开模态框的方法 // 打开模态框的方法
const openCountryModal = () => { const openCountryModal = () => {
if (countryModalRef.value) { if (countryModalRef.value) {
@@ -304,11 +333,13 @@ const getReleaseList = async() => {
if (!error && data) { if (!error && data) {
tableData.value = data.data.records; tableData.value = data.data.records;
pager.value.total = data.data.total; pager.value.total = data.data.total;
console.log(tableData.value)
} }
}; };
onMounted(async() => { onMounted(async() => {
getReleaseList(); // getReleaseList();
}); });
onMounted(() => { onMounted(() => {
@@ -317,18 +348,6 @@ onMounted(() => {
...query ...query
}; };
}); });
// 监听路由变化,更新 searchWord
watch(
() => route.query.searchWord, // 监听路由的 searchWord 参数
(newSearchWord) => {
if (newSearchWord) {
newFormData.value.searchWord = newSearchWord; // 更新组件的 searchWord
getReleaseList(); // 重新调用接口
}
},
{ immediate: true } // 立即执行一次
);
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">