实现搜索

main
lizhong 2 years ago
parent ac0dafba61
commit 56a17cb6a2

@ -0,0 +1,9 @@
# port
VITE_PORT = 3100
# spa-title
VITE_GLOB_APP_TITLE=湛江水产品技术性贸易措施研究评议基地
VITE_GLOB_API_URL=/api
VITE_GLOB_ORIGIN=http://research.mcnetmart.com
# spa shortname
VITE_GLOB_APP_SHORT_NAME=

1
.gitignore vendored

@ -4,7 +4,6 @@ node_modules
.nitro
.cache
.output
.env
.env.local
.env.development
dist

@ -5,12 +5,16 @@
</component>
<component name="ChangeListManager">
<list default="true" id="dc5c5f4b-3a26-4616-b023-f4f048553ff8" name="Changes" comment="socket">
<change afterPath="$PROJECT_DIR$/assets/socketio.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/middleware/isSearch.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/pages/search/[id].vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/nuxt.config.ts" beforeDir="false" afterPath="$PROJECT_DIR$/nuxt.config.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/Common.ts" beforeDir="false" afterPath="$PROJECT_DIR$/api/Common.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/components/Banner/Search.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/Banner/Search.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/components/Header/Index.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/Header/Index.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/composables/useAppStore.ts" beforeDir="false" afterPath="$PROJECT_DIR$/composables/useAppStore.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/layouts/tabLayout.vue" beforeDir="false" afterPath="$PROJECT_DIR$/layouts/tabLayout.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pages/translate.vue" beforeDir="false" afterPath="$PROJECT_DIR$/pages/translate.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/yarn.lock" beforeDir="false" afterPath="$PROJECT_DIR$/yarn.lock" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -22,8 +26,8 @@
<list>
<option value="vue3" />
<option value="Vue Single File Component" />
<option value="TypeScript File" />
<option value="JavaScript File" />
<option value="TypeScript File" />
</list>
</option>
</component>
@ -138,7 +142,7 @@
<workItem from="1679887069532" duration="713000" />
<workItem from="1679913811172" duration="1597000" />
<workItem from="1680008447811" duration="223000" />
<workItem from="1680009330616" duration="16248000" />
<workItem from="1680009330616" duration="25078000" />
</task>
<task id="LOCAL-00001" summary="socket">
<created>1680082088939</created>

@ -5,6 +5,7 @@ export default new class Common extends Http<ResOptions<any>> {
private readonly upload = '/common/upload'
private readonly caseList = '/cases/lists'
private readonly bottomMenu = '/index/bottomMenu'
private readonly search_url = '/index/search'
private readonly login_url = '/user/login'
handleUpload(file: any) {
const formData = new FormData();
@ -22,5 +23,9 @@ export default new class Common extends Http<ResOptions<any>> {
return this.post(this.login_url,this.toFormData(data))
}
searchApi(params: PaginationVo & {category_id?: number}){
return this.get(this.search_url, params)
}
}

@ -1,32 +1,6 @@
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { useDesign } from '~/composables/useDesign';
// import SvgIcon from '/@/components/Icon/src/SvgIcon.vue';
import banner from '~~/assets/images/homeBanner.png';
export default defineComponent({
// components: { SvgIcon },
emits: ['search'],
setup(_, ctx) {
const { prefixCls } = useDesign('banner');
const imgUrl = ref(banner);
const searchVal = ref('');
function onInput(ev: { target: { value: string; }; }) {
searchVal.value = ev.target.value;
ctx.emit('search', ev);
}
// const imgUrl = ()=
return {
prefixCls,
imgUrl,
onInput,
searchVal,
};
},
});
</script>
<template>
<div :class="[prefixCls, `${prefixCls}--host`]">
<img :src="imgUrl" alt="" />
<img src="@/assets/images/homeBanner.png" alt="" />
<div class="search-bar">
<el-icon :size="27" >
<svg width="27px" height="27px" viewBox="0 0 27 27" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
@ -47,10 +21,39 @@
class="mai-input"
type="text"
/>
<button class="mai-btn" type="button">搜索</button>
<button class="mai-btn" @click="handleGoSearch" type="button">搜索</button>
</div>
</div>
</template>
<script lang="ts" setup>
const emits = defineEmits(['search'])
const searchVal = ref('');
const route = useRoute();
const router = useRouter();
const { prefixCls } = useDesign('banner');
function onInput(ev: { target: { value: string; }; }) {
searchVal.value = ev.target.value;
emits('search', ev.target.value);
}
function handleGoSearch() {
if (route.path.includes('/search')) {
onInput({target: {value: searchVal.value}})
}else {
router.push({
path: '/search' + route.path,
query:{
keywords: searchVal.value
}
})
}
}
watchEffect(()=>{
if (route.path.includes('/search')) {
searchVal.value = route.query.keywords as string;
}
})
</script>
<style lang="scss" scoped>
@import 'banner';
</style>

@ -3,7 +3,7 @@
:class="[prefixCls, 'flex', 'justify-between', store.getMenuTheme === 'dark'? 'is-host' : 'is-white']">
<ApplicationAppLogo/>
<el-menu
:default-active="$route.meta.parentPath || $route.path"
:default-active="defaultActive"
mode="horizontal"
:ellipsis="false"
router
@ -14,6 +14,7 @@
</el-menu>
<div class="login-action-wrap flex items-center">
<!-- 首页展示搜索按钮 -->
<el-popover popper-class="search-popper" v-if="activeRoute === '/'" placement="bottom-end" :width="434" trigger="click">
<template #reference>
<el-icon>
@ -22,6 +23,7 @@
</template>
<div>
<el-input
@keydown.enter="handleSearch"
v-model="keyword"
placeholder="请输入关键字"
:suffix-icon="ElIconSearch"
@ -29,6 +31,7 @@
</div>
</el-popover>
<el-divider v-if="activeRoute === '/'" direction="vertical" style="border-left: 1px solid #000"/>
<div class="login-btn cursor-pointer" v-if="!token" @click="setLoginVisible(true)"></div>
<el-dropdown popper-class="login-popper" @command="handleCommand" v-else trigger="click">
<div class="el-dropdown-link text-xl" style="line-height: 100px;">
@ -67,6 +70,16 @@ const {setLoginVisible, setInfo, setToken} = useUserInfo()
const token = computed(() => useUserInfo().$state.token);
const userInfo = ref()
const keyword = ref('')
const defaultActive = computed((): string=>{
// const routes = ['index', 'inform', 'rules', 'warning', 'tptsps', 'case', 'comment', 'about']
if (!route.meta.parentPath && route.path.includes('search')) {
return ('/' + ( route.params.id === 'index' ? '' : route.params.id)) as unknown as string
}else {
return ( route.meta.parentPath || route.path ) as unknown as string
}
})
function handleCommand(command: string) {
if (command === '5') {
ElMessageBox.confirm(
@ -98,15 +111,8 @@ function handleCommand(command: string) {
})
}
}
watchEffect(() => {
console.log('useUserInfo().$state.info>>>>>>> header', useUserInfo().$state.info)
userInfo.value = useUserInfo().$state.info;
})
function handleChange(val: any) {
store.setSearchVal('')
activeRoute.value = val.path;
if (val.meta.hasOwnProperty('headerHost') && val.meta.headerHost) {
store.setMenuTheme('dark')
@ -121,6 +127,15 @@ function handleChange(val: any) {
}
}
function handleSearch() {
router.push({
path: '/search/index',
query:{
keywords: keyword.value
}
})
}
watch(() => route, (val) => {
activeRoute.value = val.path;
if (val.meta.hasOwnProperty('headerHost') && val.meta.headerHost) {
@ -136,6 +151,10 @@ watch(() => route, (val) => {
}
}, {deep: true})
watchEffect(() => {
console.log('useUserInfo().$state.info>>>>>>> header', useUserInfo().$state.info)
userInfo.value = useUserInfo().$state.info;
})
watchEffect(() => {
handleChange(route)
})

@ -5,18 +5,21 @@ export interface AppState {
menuTheme: menu;
homeBanner: boolean;
bannerTitle: string;
searchVal?: string
}
const useAppStore = defineStore('app', {
state: (): AppState => ({
menuTheme: 'light',
homeBanner: true,
bannerTitle: ''
bannerTitle: '',
searchVal: ''
}),
getters:{
getMenuTheme: (state)=> state.menuTheme,
getHomeBanner: (state)=> state.homeBanner,
getBannerTitle: (state)=> state.bannerTitle,
getSearchVal: (state)=> state.searchVal,
},
actions: {
@ -28,6 +31,9 @@ const useAppStore = defineStore('app', {
},
setBannerTitle(title: string): void{
this.bannerTitle = title;
},
setSearchVal(val: string): void{
this.searchVal = val;
}
}

@ -1,11 +1,12 @@
<template>
<Header />
<template v-if="!route.meta.hiddenBanner">
<BannerSearch v-if="store.getMenuTheme === 'dark'&&store.getHomeBanner == false" />
<BannerSimple :title="store.getBannerTitle" v-else-if="store.getMenuTheme === 'light'&&store.getHomeBanner == false" />
<BannerSearch @search="handleSearch" v-if="store.getMenuTheme === 'dark' && store.getHomeBanner === false" />
<BannerSimple :title="store.getBannerTitle" v-else-if="store.getMenuTheme === 'light'&&store.getHomeBanner === false" />
<BannerHomeBanner v-else></BannerHomeBanner>
</template>
<!-- <div :style="`transition:margin .2s;height: 500px;background-color: tan;margin-top: ${store.getMenuTheme === 'dark' ? '-100px': 0}`"></div>-->
<slot />
<Footer />
@ -17,10 +18,21 @@
const store = useAppStore()
const route = useRoute()
const loginStatus = ref(useUserInfo().getLoginVisible)
const searchVal = ref('')
function handleSearch(val) {
searchVal.value = val
}
watchEffect(()=>{
loginStatus.value = useUserInfo().getLoginVisible;
console.log('loginStatus>>>', loginStatus.value)
if (route.path.includes('/search')) {
searchVal.value = route.query.keywords
}
})
watchEffect(()=>{
store.setSearchVal(searchVal.value)
})
// console.log()
</script>

@ -0,0 +1,21 @@
import {
defineNuxtRouteMiddleware,
navigateTo,
} from "#app";
// import useUserStore from "@/store/user.store";
export default defineNuxtRouteMiddleware((to, form) => {
const routes = ['index', 'inform', 'rules', 'warning', 'tptsps']
console.log(routes.includes(<string>to.params.id))
if (!routes.includes(<string>to.params.id)) {
return navigateTo('/404')
}
// console.log(getToken, 'getToken')
// if (!getToken) {
// setLoginVisible(true)
// }else {
// setLoginVisible(false)
// }
});

@ -0,0 +1,129 @@
<template>
<section class="mai-wrap">
<div class="mai-container">
<div class="mai-article py-5" v-for="(item, index) in content" :key="index">
<div class="article mb-9">
<div class="title flex items-center mb-5">
<h3 class="text-2xl mr-4">{{ item.title }}</h3>
<span class="category text-md px-4 py-1">{{ categoryNames[item.category_id] }}</span>
</div>
<p class="text-gray-400 ">{{ item.description }}</p>
</div>
<div class="article-bottom flex justify-between">
<a target="_blank" class="article-link"
:href="item.fromLink ? item.fromLink: 'javascript:void(0);'">文章来源: {{
item.fromDesc
}}</a>
<span class="text-gray-400">{{ item.time }}</span>
</div>
</div>
</div>
<div class="mt-32">
<Pagination
:current="current"
:limit="limit"
:pages="pagesRef"
:total="total"
@change="onChangePage"
/>
</div>
</section>
</template>
<script setup lang="ts">
enum Category {
index,
inform,
warning,
rules,
tptsps,
}
const categoryNames = reactive({
"1": "动态资讯",
"2": "预警信息",
"3": "法律法规",
"4": "TBT/SPS通报"
})
definePageMeta({
hidden: true,
middleware: ['is-search'],
headerHost: true,
})
// const {searchVal} = props.searchVal
const route = useRoute()
const store = useAppStore()
const searchVal = computed(() => store.getSearchVal)
const {commonApi} = useApi()
const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePagination(1, 6, 0)
const content = ref([
{
title: '市场监管总局发布食品补充检验方法管理规定',
type: 1,
description: '12日记者从北京海关获悉今年前11个月北京地区含中央在京单位进出口总值3.3万亿元人民币超过去年全年水平较去年同期增长19.4%高于全国增速10.8个百分点。其中进口2.78万亿元增长26%出口5242.4亿元下降6.3%',
time: '2022-11-12 12:23',
fromLink: 'https://www.baidu.com',
fromDesc: 'TSC技术性贸易措施资讯网',
category_id: '1',
}
])
const searchType = ref(0)
function onChangePage(val: number) {
setCurrentPage(val)
getList()
}
async function getList() {
if (searchType.value === 0) {
const {data} = await commonApi.searchApi({keyword: searchVal.value, page: current.value, limit})
content.value = data.list;
setTotal(data.total);
if (data) {
// loading.value = false;
}
}else {
const {data} = await commonApi.searchApi({keyword: searchVal.value, page: current.value, limit, category_id: searchType.value})
content.value = data.list;
setTotal(data.total);
if (data) {
// loading.value = false;
}
}
}
watchEffect(() => {
searchType.value = Category[route.params.id as unknown as any] as unknown as number;
console.log(searchType.value )
onChangePage(1)
})
</script>
<style lang="scss" scoped>
.mai-wrap {
width: 1300px;
margin: 0 auto;
padding: 75px 0;
.mai-article {
border-bottom: 1px solid #F3F3F3;
}
.article-link {
color: #0055AB;
}
.category {
color: #022950;
border-radius: 8px;
border: 1px solid #022950;
}
}
</style>

@ -167,17 +167,22 @@
import dayjs from "dayjs";
import {onClickOutside} from "@vueuse/core"
// import socket from "@/utils/socket";
// import io from 'socket.io-client'
// import {process} from "unenv/runtime/node/process/_process";
definePageMeta({
name: '翻译',
hidden: true,
hiddenBanner: true,
middleware: ['auth']
})
useHead({
title: '翻译',
script: [
{
type: 'text/javascript',
src: 'https://cdn.bootcss.com/socket.io/1.3.7/socket.io.js'
}
]
})
const {prefixCls} = useDesign('mai-wrap');
const router = useRouter()
const route = useRoute()
@ -222,49 +227,31 @@ const fileUrl = ref('')
const uid = ref('')
const socket = ref(null)
watch(currentLangModalStatus,(val)=>{
allLanguage()
watch(currentLangModalStatus, (val) => {
allLanguage()
})
watch(targetLangModalStatus,(val)=>{
allLanguage()
watch(targetLangModalStatus, (val) => {
allLanguage()
})
watchEffect(() => {
radio1.value = route.query?.type ?? 1;
const user = useUserInfo()
// // @ts-ignore
// if(porce.client) {
// // @ts-ignore
// socket.on("disconnect", () => {
// console.log(socket.id); // undefined
// });
// if (user.$state.info.id) {
// socket.on("connect", () => {
// const transport = socket.io.engine.transport.name; // , "polling"
// socket.emit('login', user.$state.info.id);
// socket.io.engine.on("upgrade", () => {
// const upgradedTransport = socket.io.engine.transport.name; // , "websocket"
// });
// });
// }
// }
if(user.$state.info.id) {
window.io = null
if (user.$state.info.id) {
// window.io = null
// if (process.client) {
const socketio = document.createElement('script')
socketio.src = 'https://cdn.bootcss.com/socket.io/1.3.7/socket.io.js'
// const socketio = document.createElement('script')
// socketio.src = 'https://cdn.bootcss.com/socket.io/1.3.7/socket.io.js'
document.body.append(socketio)
// document.body.append(socketio)
let timer = setInterval(()=>{
// @ts-ignore
let timer = setInterval(() => {
// @ts-ignore
if (io) {
// @ts-ignore
socket.value = io('http://research.mcnetmart.com:2120');//socket
// @ts-ignore
// @ts-ignore
socket.value.on('connect', function () {
// @ts-ingore
console.log('dengll', user)
@ -285,6 +272,7 @@ async function inputChange() {
const {data: data} = await translateApi.getAllLanguage({keyword: searchLanguage.value})
language.value = data
}
async function inputChange2() {
const {data: data} = await translateApi.getAllLanguage({keyword: searchLanguage2.value})
language2.value = data
@ -397,14 +385,15 @@ async function translate() {
textarea2.value = data
}
}
async function translate3() {
const {data: data} = await translateApi.ocrTranslate({
file: fileUrl.value,
source: abbreviation1.value,
target: abbreviation2.value
})
textarea2.value = data
const {data: data} = await translateApi.ocrTranslate({
file: fileUrl.value,
source: abbreviation1.value,
target: abbreviation2.value
})
textarea2.value = data
}
async function translate2() {
@ -827,7 +816,8 @@ allLanguage()
box-shadow: none !important;
// padding: 0px; //
}
.HtmlPreview{
.HtmlPreview {
height: 239px !important;
margin: 17px;
border-radius: 16px;

Loading…
Cancel
Save