验证码、搜索、

main
lizhong 2 years ago
parent 56a17cb6a2
commit cd79642603

@ -5,16 +5,28 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="dc5c5f4b-3a26-4616-b023-f4f048553ff8" name="Changes" comment="socket"> <list default="true" id="dc5c5f4b-3a26-4616-b023-f4f048553ff8" name="Changes" comment="socket">
<change afterPath="$PROJECT_DIR$/middleware/isSearch.ts" afterDir="false" /> <change afterPath="$PROJECT_DIR$/pages/[tptsps_id].vue" 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$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/Common.ts" beforeDir="false" afterPath="$PROJECT_DIR$/api/Common.ts" afterDir="false" /> <change beforePath="$PROJECT_DIR$/api/Common.ts" beforeDir="false" afterPath="$PROJECT_DIR$/api/Common.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/assets/style/config.scss" beforeDir="false" afterPath="$PROJECT_DIR$/assets/style/config.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/assets/style/var/index.scss" beforeDir="false" afterPath="$PROJECT_DIR$/assets/style/var/index.scss" 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/Banner/Search.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/Banner/Search.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/components/Banner/homeBanner.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/Banner/homeBanner.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/components/Footer/Index.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/Footer/Index.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$/components/Header/Index.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/Header/Index.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/components/HtmlPreview/Index.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/HtmlPreview/Index.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/components/Login/Index.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/Login/Index.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/components/MoreBtn/Index.vue" beforeDir="false" afterPath="$PROJECT_DIR$/components/MoreBtn/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$/composables/useAppStore.ts" beforeDir="false" afterPath="$PROJECT_DIR$/composables/useAppStore.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/composables/useUserInfo.ts" beforeDir="false" afterPath="$PROJECT_DIR$/composables/useUserInfo.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/layouts/tabLayout.vue" beforeDir="false" afterPath="$PROJECT_DIR$/layouts/tabLayout.vue" 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$/nuxt.config.ts" beforeDir="false" afterPath="$PROJECT_DIR$/nuxt.config.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pages/index.vue" beforeDir="false" afterPath="$PROJECT_DIR$/pages/index.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pages/rules.vue" beforeDir="false" afterPath="$PROJECT_DIR$/pages/rules.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pages/search/[id].vue" beforeDir="false" afterPath="$PROJECT_DIR$/pages/search/[id].vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pages/tptsps.vue" beforeDir="false" afterPath="$PROJECT_DIR$/pages/tptsps.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pages/warning.vue" beforeDir="false" afterPath="$PROJECT_DIR$/pages/warning.vue" afterDir="false" />
<change beforePath="$PROJECT_DIR$/utils/http.ts" beforeDir="false" afterPath="$PROJECT_DIR$/utils/http.ts" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -45,31 +57,31 @@
<option name="showLibraryContents" value="true" /> <option name="showLibraryContents" value="true" />
<option name="sortByType" value="true" /> <option name="sortByType" value="true" />
</component> </component>
<component name="PropertiesComponent">{ <component name="PropertiesComponent"><![CDATA[{
&quot;keyToString&quot;: { "keyToString": {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;, "RunOnceActivity.OpenProjectViewOnStart": "true",
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, "RunOnceActivity.ShowReadmeOnStart": "true",
&quot;WebServerToolWindowFactoryState&quot;: &quot;true&quot;, "WebServerToolWindowFactoryState": "true",
&quot;WebServerToolWindowPanel.toolwindow.highlight.mappings&quot;: &quot;true&quot;, "WebServerToolWindowPanel.toolwindow.highlight.mappings": "true",
&quot;WebServerToolWindowPanel.toolwindow.highlight.symlinks&quot;: &quot;true&quot;, "WebServerToolWindowPanel.toolwindow.highlight.symlinks": "true",
&quot;WebServerToolWindowPanel.toolwindow.show.date&quot;: &quot;false&quot;, "WebServerToolWindowPanel.toolwindow.show.date": "false",
&quot;WebServerToolWindowPanel.toolwindow.show.permissions&quot;: &quot;false&quot;, "WebServerToolWindowPanel.toolwindow.show.permissions": "false",
&quot;WebServerToolWindowPanel.toolwindow.show.size&quot;: &quot;false&quot;, "WebServerToolWindowPanel.toolwindow.show.size": "false",
&quot;last_opened_file_path&quot;: &quot;/Users/lizhong/Desktop/workspace/ReptileFront/reptileFront_nuxt/assets/images&quot;, "last_opened_file_path": "/Users/lizhong/Desktop/workspace/ReptileFront/reptileFront_nuxt/pages",
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;, "node.js.detected.package.eslint": "true",
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;, "node.js.detected.package.tslint": "true",
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;, "node.js.selected.package.eslint": "(autodetect)",
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;, "node.js.selected.package.tslint": "(autodetect)",
&quot;nodejs_package_manager_path&quot;: &quot;yarn&quot;, "nodejs_package_manager_path": "yarn",
&quot;settings.editor.selected.configurable&quot;: &quot;reference.settings.ide.settings.file-colors&quot;, "settings.editor.selected.configurable": "reference.settings.ide.settings.file-colors",
&quot;ts.external.directory.path&quot;: &quot;/Applications/WebStorm.app/Contents/plugins/javascript-impl/jsLanguageServicesImpl/external&quot;, "ts.external.directory.path": "/Applications/WebStorm.app/Contents/plugins/javascript-impl/jsLanguageServicesImpl/external",
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot; "vue.rearranger.settings.migration": "true"
} }
}</component> }]]></component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS"> <key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/assets/images" />
<recent name="$PROJECT_DIR$/pages" /> <recent name="$PROJECT_DIR$/pages" />
<recent name="$PROJECT_DIR$/assets/images" />
<recent name="$PROJECT_DIR$/api" /> <recent name="$PROJECT_DIR$/api" />
<recent name="$PROJECT_DIR$" /> <recent name="$PROJECT_DIR$" />
<recent name="$PROJECT_DIR$/src/assets/images" /> <recent name="$PROJECT_DIR$/src/assets/images" />
@ -82,7 +94,7 @@
<recent name="$PROJECT_DIR$/src/assets" /> <recent name="$PROJECT_DIR$/src/assets" />
</key> </key>
</component> </component>
<component name="RunManager" selected="npm.dev"> <component name="RunManager" selected="npm.generate">
<configuration name="build" type="js.build_tools.npm" temporary="true" nameIsGenerated="true"> <configuration name="build" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" /> <package-json value="$PROJECT_DIR$/package.json" />
<command value="run" /> <command value="run" />
@ -115,8 +127,8 @@
</configuration> </configuration>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="npm.dev" />
<item itemvalue="npm.generate" /> <item itemvalue="npm.generate" />
<item itemvalue="npm.dev" />
<item itemvalue="npm.build" /> <item itemvalue="npm.build" />
</list> </list>
</recent_temporary> </recent_temporary>
@ -142,7 +154,8 @@
<workItem from="1679887069532" duration="713000" /> <workItem from="1679887069532" duration="713000" />
<workItem from="1679913811172" duration="1597000" /> <workItem from="1679913811172" duration="1597000" />
<workItem from="1680008447811" duration="223000" /> <workItem from="1680008447811" duration="223000" />
<workItem from="1680009330616" duration="25078000" /> <workItem from="1680009330616" duration="25356000" />
<workItem from="1680141026158" duration="22126000" />
</task> </task>
<task id="LOCAL-00001" summary="socket"> <task id="LOCAL-00001" summary="socket">
<created>1680082088939</created> <created>1680082088939</created>

@ -7,6 +7,9 @@ export default new class Common extends Http<ResOptions<any>> {
private readonly bottomMenu = '/index/bottomMenu' private readonly bottomMenu = '/index/bottomMenu'
private readonly search_url = '/index/search' private readonly search_url = '/index/search'
private readonly login_url = '/user/login' private readonly login_url = '/user/login'
private readonly carousel_url = '/index/carousel'
private readonly index_url = '/index/index'
private readonly captcha_url = 'http://research.mcnetmart.com/index.php?s=/captcha'
handleUpload(file: any) { handleUpload(file: any) {
const formData = new FormData(); const formData = new FormData();
formData.append('file', file) formData.append('file', file)
@ -27,5 +30,15 @@ export default new class Common extends Http<ResOptions<any>> {
return this.get(this.search_url, params) return this.get(this.search_url, params)
} }
getCarousel(){
return this.get(this.carousel_url, {category: '首页'})
}
getIndexConfig(){
return this.get(this.index_url)
}
getCaptcha(){
return this.get(this.captcha_url)
}
} }

@ -1,3 +1,4 @@
@import "color"; @import "color";
@import "public"; @import "public";
@import 'var/index'; @import 'var/index';

@ -30,3 +30,13 @@ $layout-mix-sider-fixed-z-index: 550;
$preview-comp-z-index: 1000; $preview-comp-z-index: 1000;
$page-footer-z-index: 99; $page-footer-z-index: 99;
@mixin ellipsis-line($line){
word-break: break-word;
display: -webkit-box;
-webkit-line-clamp: $line;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}

@ -15,9 +15,11 @@
</svg> </svg>
</el-icon> </el-icon>
<input <input
ref="inputData"
placeholder="按照关键词搜索" placeholder="按照关键词搜索"
:value="searchVal" :value="searchVal"
@input="onInput" @input="onInput"
@keydown.enter="handleSearch"
class="mai-input" class="mai-input"
type="text" type="text"
/> />
@ -27,25 +29,43 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const emits = defineEmits(['search']) const emits = defineEmits(['search'])
const store = useAppStore()
const inputData = ref()
const searchVal = ref(''); const searchVal = ref('');
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const { prefixCls } = useDesign('banner'); const { prefixCls } = useDesign('banner');
function onInput(ev: { target: { value: string; }; }) { function onInput(ev: { target: { value: string; }; }) {
searchVal.value = ev.target.value; searchVal.value = ev.target.value;
emits('search', ev.target.value); }
function handleSearch() {
emits('search', searchVal.value);
handleGoSearch()
} }
function handleGoSearch() { function handleGoSearch() {
if (route.path.includes('/search')) { store.setSearchVal(searchVal.value)
onInput({target: {value: searchVal.value}}) // if (route.path.includes('/search')) {
}else { // onInput({target: {value: searchVal.value}})
router.push({ // }else {
path: '/search' + route.path, if (searchVal.value) {
query:{ if (route.path.includes('/search')) {
keywords: searchVal.value router.replace({
path: route.path,
query:{
keywords: searchVal.value
}
})
}else {
router.push({
path: '/search' + route.path,
query:{
keywords: searchVal.value
}
})
} }
})
} }
// }
} }
watchEffect(()=>{ watchEffect(()=>{

@ -1,25 +1,28 @@
<script lang="ts" setup>
const props = defineProps(['title']);
const { prefixCls } = useDesign('banner');
const bannerList = reactive([
{id:1,img:'/_nuxt/assets/images/commonBanner.png'},
{id:2,img:'/_nuxt/assets/images/commonBanner.png'},
{id:3,img:'/_nuxt/assets/images/commonBanner.png'},
{id:4,img:'/_nuxt/assets/images/commonBanner.png'},
]);
</script>
<template> <template>
<div :class="[prefixCls, `${prefixCls}--white`]"> <div :class="[prefixCls, `${prefixCls}--white`]">
<el-carousel indicator-position="outside"> <el-carousel indicator-position="outside">
<el-carousel-item v-for="item in bannerList" :key="item.id"> <el-carousel-item v-for="item in bannerList" :key="item.id">
<img :src="item.img" alt="" /> <a class="block w-full h-full" :target="item.link ? '_blank' : 'javascript:void(0)'" :href="item.link" >
<el-image class="w-full h-full" fit="cover" :src="item.image" alt="" />
</a>
</el-carousel-item> </el-carousel-item>
</el-carousel> </el-carousel>
<!-- <img src="~/assets/images/commonBanner.png" alt="" /> --> <!-- <img src="~/assets/images/commonBanner.png" alt="" /> -->
<!-- <h2 class="title">{{ props.title }}</h2> --> <!-- <h2 class="title">{{ props.title }}</h2> -->
</div> </div>
</template> </template>
<script lang="ts" setup>
import commonApi from "~/api/Common";
const props = defineProps(['title']);
const { prefixCls } = useDesign('banner');
const bannerList = ref([]);
(async function getData() {
const {data} = await commonApi.getCarousel()
bannerList.value = data;
}())
</script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import 'banner'; @import 'banner';
</style> </style>

@ -7,7 +7,7 @@
</nuxt-link> </nuxt-link>
</div> </div>
<div :class="`${prefixCls}__copyright`" <div :class="`${prefixCls}__copyright`"
>Copyright © 2012-2025 北京中海通科技有限公司版权所有每ICP备xxxxxxxxxxxxxxx号 >{{ store.$state.otherConfig?.icp_record }}
</div </div
> >
</el-footer> </el-footer>
@ -17,10 +17,13 @@
const menuList = ref([]); const menuList = ref([]);
const {prefixCls} = useDesign('layout-footer'); const {prefixCls} = useDesign('layout-footer');
const {commonApi} = useApi(); const {commonApi} = useApi();
const store = useAppStore()
async function getData() { async function getData() {
const menus = await commonApi.getBottomMenu() const menus = await commonApi.getBottomMenu()
const config = await commonApi.getIndexConfig()
menuList.value = menus.data menuList.value = menus.data
store.setConfig(config.data)
} }
getData() getData()
</script> </script>

@ -15,10 +15,11 @@
<div class="login-action-wrap flex items-center"> <div class="login-action-wrap flex items-center">
<!-- 首页展示搜索按钮 --> <!-- 首页展示搜索按钮 -->
<el-popover popper-class="search-popper" v-if="activeRoute === '/'" placement="bottom-end" :width="434" trigger="click"> <el-popover popper-class="search-popper" v-if="activeRoute === '/'" placement="bottom-end"
:width="434" trigger="click">
<template #reference> <template #reference>
<el-icon> <el-icon>
<el-icon-search /> <el-icon-search/>
</el-icon> </el-icon>
</template> </template>
<div> <div>
@ -30,7 +31,8 @@
/> />
</div> </div>
</el-popover> </el-popover>
<el-divider v-if="activeRoute === '/'" direction="vertical" style="border-left: 1px solid #000"/> <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> <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"> <el-dropdown popper-class="login-popper" @command="handleCommand" v-else trigger="click">
@ -70,16 +72,17 @@ const {setLoginVisible, setInfo, setToken} = useUserInfo()
const token = computed(() => useUserInfo().$state.token); const token = computed(() => useUserInfo().$state.token);
const userInfo = ref() const userInfo = ref()
const keyword = ref('') const keyword = ref('')
const defaultActive = computed((): string=>{ const defaultActive = computed((): string => {
// const routes = ['index', 'inform', 'rules', 'warning', 'tptsps', 'case', 'comment', 'about'] // const routes = ['index', 'inform', 'rules', 'warning', 'tptsps', 'case', 'comment', 'about']
if (!route.meta.parentPath && route.path.includes('search')) { if (!route.meta.parentPath && route.path.includes('search')) {
return ('/' + ( route.params.id === 'index' ? '' : route.params.id)) as unknown as string return ('/' + (route.params.id === 'index' ? '' : route.params.id)) as unknown as string
}else { } else {
return ( route.meta.parentPath || route.path ) as unknown as string return (route.meta.parentPath || route.path) as unknown as string
} }
}) })
function handleCommand(command: string) { function handleCommand(command: string) {
if (command === '5') { if (command === '5') {
ElMessageBox.confirm( ElMessageBox.confirm(
@ -102,15 +105,16 @@ function handleCommand(command: string) {
message: '已取消退出登录', message: '已取消退出登录',
}) })
}) })
}else { } else {
router.push({ router.push({
path: '/translate', path: '/translate',
query:{ query: {
type: command type: command
} }
}) })
} }
} }
function handleChange(val: any) { function handleChange(val: any) {
store.setSearchVal('') store.setSearchVal('')
activeRoute.value = val.path; activeRoute.value = val.path;
@ -128,12 +132,16 @@ function handleChange(val: any) {
} }
function handleSearch() { function handleSearch() {
router.push({ store.setSearchVal(keyword.value)
path: '/search/index', if (keyword.value) {
query:{ router.push({
keywords: keyword.value path: '/search/index',
} query: {
}) keywords: keyword.value
}
})
}
} }
watch(() => route, (val) => { watch(() => route, (val) => {
@ -283,26 +291,31 @@ $prefix-cls: '#{$name-prefix}-header-wrap';
border-radius: 30px; border-radius: 30px;
height: 56px; height: 56px;
border: none; border: none;
.el-popper__arrow { .el-popper__arrow {
display: none; display: none;
} }
.el-input { .el-input {
height: 100%; height: 100%;
margin: 0; margin: 0;
border-radius: 30px; border-radius: 30px;
font-size: 20px; font-size: 20px;
} }
.el-input__wrapper { .el-input__wrapper {
padding: 0 30px; padding: 0 30px;
height: 56px; height: 56px;
border-radius: 30px; border-radius: 30px;
border: none; border: none;
box-shadow: unset; box-shadow: unset;
.el-input__inner { .el-input__inner {
height: 56px; height: 56px;
box-shadow: unset; box-shadow: unset;
line-height: 56px; line-height: 56px;
} }
.el-icon { .el-icon {
color: #134A9B; color: #134A9B;
} }

@ -33,7 +33,6 @@
import CssP1 from '/assets/tinymce/skins/ui/oxide/content.min.css?inline'; import CssP1 from '/assets/tinymce/skins/ui/oxide/content.min.css?inline';
//@ts-ignore //@ts-ignore
import CssP2 from '/assets/tinymce/skins/ui/oxide/content.min.css?inline'; import CssP2 from '/assets/tinymce/skins/ui/oxide/content.min.css?inline';
import { defineProps } from 'vue';
const props = defineProps(['content']); const props = defineProps(['content']);
</script> </script>

@ -19,7 +19,7 @@
:rules="formRules" :rules="formRules"
ref="formRef" ref="formRef"
> >
<el-form-item name="account" class="enter-x"> <el-form-item name="account" prop="account" class="enter-x">
<el-input <el-input
size="large" size="large"
v-model="formData.account" v-model="formData.account"
@ -27,7 +27,7 @@
class="fix-auto-fill" class="fix-auto-fill"
/> />
</el-form-item> </el-form-item>
<el-form-item name="password" class="enter-x"> <el-form-item name="password" prop="password" class="enter-x">
<el-input <el-input
type="password" type="password"
size="large" size="large"
@ -35,14 +35,14 @@
placeholder="请输入密码" placeholder="请输入密码"
/> />
</el-form-item> </el-form-item>
<el-form-item name="captcha" class="enter-x"> <el-form-item name="captcha" prop="captcha" class="enter-x">
<el-input <el-input
size="large" size="large"
v-model="formData.captcha" v-model="formData.captcha"
placeholder="请输入验证码" placeholder="请输入验证码"
> >
<template #append> <template #append>
<img src="~@/assets/images/testCode.jpg" alt="" /> <img class="cursor-pointer" @click="getCode($event)" src="http://research.mcnetmart.com/index.php?s=/captcha" alt="" />
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
@ -60,11 +60,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, reactive, ref, unref } from 'vue'; import { computed, reactive, ref, unref } from 'vue';
import {FormInstance} from "element-plus"; import {FormInstance} from "element-plus";
const captcha = ref('')
const userStore = useUserInfo(); const userStore = useUserInfo();
const title = computed(()=> import.meta.env.VITE_GLOB_APP_TITLE) const title = computed(()=> import.meta.env.VITE_GLOB_APP_TITLE)
const formRules = ref({ const formRules = ref({
account:{message:'请输入用户名', trigger:'blur', required: true},
password: {message:'请输入密码', trigger:'blur', required: true},
captcha: {message:'请输入验证码', trigger:'blur', required: true},
}) })
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
@ -73,10 +75,10 @@ const loading = ref(false);
const formData = reactive({ const formData = reactive({
account: 'test', account: 'test',
password: '123456', password: '123456',
// captcha: '123456', captcha: '',
}); });
const prefixCls = useDesign('login'); const prefixCls = useDesign('login');
const { commonApi } = useApi()
async function handleLogin(formEl: FormInstance | undefined) { async function handleLogin(formEl: FormInstance | undefined) {
if (!formEl) return; if (!formEl) return;
@ -102,6 +104,14 @@ async function handleLogin(formEl: FormInstance | undefined) {
}) })
} }
async function getCode(ev: any){
// this.src = ''
// this.src = ''
ev.target.setAttribute('src', 'http://research.mcnetmart.com/index.php?s=/captcha&u='+ new Date().getTime())
// captcha.value = await commonApi.getCaptcha() as unknown as string;
}
// getCode()
const loginVisible = ref(userStore.getLoginVisible); const loginVisible = ref(userStore.getLoginVisible);
watchEffect(()=>{ watchEffect(()=>{
loginVisible.value = userStore.getLoginVisible; loginVisible.value = userStore.getLoginVisible;

@ -3,7 +3,6 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps } from 'vue';
const props = defineProps(['url']); const props = defineProps(['url']);
const router = useRouter(); const router = useRouter();

@ -5,21 +5,23 @@ export interface AppState {
menuTheme: menu; menuTheme: menu;
homeBanner: boolean; homeBanner: boolean;
bannerTitle: string; bannerTitle: string;
searchVal?: string searchVal: string;
otherConfig?: any
} }
const useAppStore = defineStore('app', { const useAppStore = defineStore('app', {
state: (): AppState => ({ state: (): AppState => ({
menuTheme: 'light', menuTheme: 'light',
homeBanner: true, homeBanner: true,
bannerTitle: '', bannerTitle: '',
searchVal: '' searchVal: '',
otherConfig: {}
}), }),
getters:{ getters:{
getMenuTheme: (state)=> state.menuTheme, getMenuTheme: (state)=> state.menuTheme,
getHomeBanner: (state)=> state.homeBanner, getHomeBanner: (state)=> state.homeBanner,
getBannerTitle: (state)=> state.bannerTitle, getBannerTitle: (state)=> state.bannerTitle,
getSearchVal: (state)=> state.searchVal, getSearchVal: (state): string=> state.searchVal,
}, },
actions: { actions: {
@ -34,6 +36,9 @@ const useAppStore = defineStore('app', {
}, },
setSearchVal(val: string): void{ setSearchVal(val: string): void{
this.searchVal = val; this.searchVal = val;
},
setConfig(data:any){
this.otherConfig = data;
} }
} }

@ -51,6 +51,7 @@ const useUserInfo = defineStore('user', {
getLoginVisible:(state)=> state.loginVisible, getLoginVisible:(state)=> state.loginVisible,
getToken:(state)=> state.token, getToken:(state)=> state.token,
}, },
// @ts-ignore
persist: process.client && { persist: process.client && {
storage: localStorage, storage: localStorage,
paths: ['info', 'token'] paths: ['info', 'token']

@ -13,26 +13,38 @@
<Login v-if="loginStatus" /> <Login v-if="loginStatus" />
</template> </template>
<script setup> <script setup lang="ts">
console.log('tabLayout init........')
const store = useAppStore() const store = useAppStore()
const route = useRoute() const route = useRoute()
const loginStatus = ref(useUserInfo().getLoginVisible) const loginStatus = ref(useUserInfo().getLoginVisible)
const searchVal = ref('') const searchVal = ref('')
function handleSearch(val) { function handleSearch(val: string) {
searchVal.value = val searchVal.value = val
store.setSearchVal(val)
} }
watchEffect(()=>{ watchEffect(()=>{
loginStatus.value = useUserInfo().getLoginVisible; loginStatus.value = useUserInfo().getLoginVisible;
console.log('loginStatus>>>', loginStatus.value) })
onMounted(()=>{
if (route.path.includes('/search')) { if (route.path.includes('/search')) {
searchVal.value = route.query.keywords console.log('if? tabLayout search init........', route.path, route.query)
// searchVal.value = route.query.keywords as unknown as string;
store.setSearchVal(route.query.keywords as unknown as string)
} }
}) })
watchEffect(()=>{ watchEffect(()=>{
store.setSearchVal(searchVal.value) // searchVal.value = route.query.keywords
// console.log('route.query.keywords>>>', route.query.keywords)
// store.setSearchVal(route.query.keywords)
console.log('tabLayout search init........', route.path)
if (route.path.includes('/search')) {
store.setSearchVal(route.query.keywords as unknown as string)
}
}) })
// console.log() // console.log()
</script> </script>

@ -55,8 +55,12 @@ export default defineNuxtConfig({
target: 'http://research.mcnetmart.com/uploads', target: 'http://research.mcnetmart.com/uploads',
prependPath: true, prependPath: true,
changeOrigin: true, changeOrigin: true,
} },
"/index.php": {
target: 'http://research.mcnetmart.com/index.php?s=/captcha',
prependPath: true,
changeOrigin: true,
},
} }
} }
}) })

@ -0,0 +1,40 @@
<template>
<div :class="[prefixCls, 'flex full relative']">
<div :class="`${prefixCls}-content pt-24`">
<el-breadcrumb style="position: absolute; top: 80px;left: 120px" :separator-icon="ArrowRight">
<el-breadcrumb-item class="text-2xl" :to="{ path: '/tptsps' }">TBT/SPS通报</el-breadcrumb-item>
<el-breadcrumb-item class="text-2xl">TBT/SPS通报详情</el-breadcrumb-item>
</el-breadcrumb>
<HtmlPreview :content="content" />
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({
name: 'TBT/SPS通报详情',
hidden: true,
headerHost: false,
parentPath: '/tptsps',
// @ts-ignore
path: '/tptsps/:id'
})
useHead({
title:'TBT/SPS通报'
})
import { ArrowRight } from '@element-plus/icons-vue'
useAppStore().setBannerTitle("预警详情")
const {prefixCls} = useDesign('mai-wrap');
const route = useRoute()
const content = ref('')
async function getData() {
const data = await useApi().warningApi.getWarningDetail(route.params.id)
console.log('data.data.info')
content.value = data.data.info.content;
}
getData()
</script>
<style scoped></style>

@ -23,7 +23,7 @@
<div class="media-img"> <div class="media-img">
<img <img
style="object-fit: cover" style="object-fit: cover"
:src="newsHilight.image" alt="" :src="store.$state.otherConfig?.information_logo" alt=""
/> />
</div> </div>
<div class="newsList"> <div class="newsList">
@ -31,7 +31,6 @@
class="news-item flex items-center justify-between" class="news-item flex items-center justify-between"
v-for="item in newsList" v-for="item in newsList"
:key="item.id" :key="item.id"
@mouseenter="changeCurrentData(item)"
> >
<div class="flex items-center c-item"> <div class="flex items-center c-item">
<div class="date"> <div class="date">
@ -152,6 +151,7 @@ const {prefixCls: prefixNews} = useDesign('news-wrap');
const {prefixCls: prefixInform} = useDesign('inform-wrap'); const {prefixCls: prefixInform} = useDesign('inform-wrap');
const {prefixCls: prefixRule} = useDesign('rule-wrap'); const {prefixCls: prefixRule} = useDesign('rule-wrap');
const {prefixCls: prefixCase} = useDesign('case-wrap'); const {prefixCls: prefixCase} = useDesign('case-wrap');
const store = useAppStore()
const {getToken, setLoginVisible} = useUserInfo() const {getToken, setLoginVisible} = useUserInfo()
const classList = reactive({ const classList = reactive({
news: [`${prefixNews} mai-section`], news: [`${prefixNews} mai-section`],

@ -4,21 +4,45 @@
<mai-tab :active="currentTab.id" :data-source="tabs" @change="handleChange"/> <mai-tab :active="currentTab.id" :data-source="tabs" @change="handleChange"/>
</div> </div>
<div :class="`${prefixCls}-content dynamicInfo flex flex-col px-8`" style="border-left: 1px solid #d9d9d9;"> <div :class="`${prefixCls}-content dynamicInfo flex flex-col px-8`" style="border-left: 1px solid #d9d9d9;">
<div class="py-8 cursor-pointer select-none" style="border-bottom: 1px solid #d9d9d9;" v-for="item in content" :key="item.id"> <div class="flex flex-wrap" v-if="content.length">
<nuxt-link :to="`/rules/${item.id}`"> <div class="p-2 rule-item cursor-pointer flex " v-for="item in content" :key="item.id">
<h3 class="text-2xl mb-6 w-full overflow-hidden text-ellipsis">{{ item.title }}</h3> <nuxt-link :to="`/rules/${item.id}`" class="w-full">
<p class="text-xl text-zinc-500 mb-6">{{ item.description }}</p>
<p class="">{{ dayjs(item.createtime * 1000).format('YYYY-MM-DD hh:mm:ss') }}</p> <el-card :body-style="{ padding: '0px' }">
</nuxt-link> <div style="padding: 14px">
<p class="mb-6">{{ dayjs(item.createtime * 1000).format('YYYY-MM-DD') }}</p>
<h4 class="text-2xl mb-2 text-ellipsis overflow-hidden"
style=" line-height:30px;height: 30px;display:inline-block">{{
item.title
}}</h4>
<p style="color: #999" class="rule-desc">{{ item.description }}</p>
<div class="bottom">
<el-button round
style="font-size: 18px; color: #022950; border-color: #022950;"><nuxt-link :to="`/rules/${item.id}`">查看详情</nuxt-link>
</el-button>
</div>
</div>
</el-card>
<!-- <h3 class="text-2xl mb-6 w-full overflow-hidden text-ellipsis">{{ item.title }}</h3>-->
<!-- <p class="text-xl text-zinc-500 mb-6">{{ item.description }}</p>-->
<!-- <p class="">{{ dayjs(item.createtime * 1000).format('YYYY-MM-DD hh:mm:ss') }}</p>-->
</nuxt-link>
</div>
</div>
<div v-else>
<el-empty description="暂无数据" />
</div> </div>
<Pagination <div class="mt-6">
:current="current" <Pagination
:total="total" :current="current"
:limit="limit" :total="total"
:pages="pagesRef" :limit="limit"
@change="onChangePage" :pages="pagesRef"
/> @change="onChangePage"
/>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -35,7 +59,7 @@ useHead({
title:'法规标准' title:'法规标准'
}) })
import {randomUUID} from '~~/utils'; import {randomUUID} from '~~/utils';
const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePagination(1, 4, 0) const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePagination(1, 6, 0)
const { technicalApi } = useApi() const { technicalApi } = useApi()
const {prefixCls} = useDesign('mai-wrap'); const {prefixCls} = useDesign('mai-wrap');
@ -78,9 +102,16 @@ async function getData() {
getData() getData()
</script> </script>
<style scoped lang="less"> <style scoped lang="scss">
.dynamicInfo { .dynamicInfo {
margin-top: 0; margin-top: 0;
padding-bottom: 100px; padding-bottom: 100px;
} }
.rule-item {
width: calc((100% - 60px) / 3);
}
.rule-desc {
min-height: 76px;
@include ellipsis-line(3);
}
</style> </style>

@ -1,23 +1,57 @@
<template> <template>
<section class="mai-wrap"> <section class="mai-wrap">
<div class="mai-container"> <div class="mai-container">
<div class="mai-article py-5" v-for="(item, index) in content" :key="index"> <div class="mai-article py-5" v-if="content.length" v-for="(item, index) in content"
<div class="article mb-9"> :key="index">
<div class="title flex items-center mb-5"> <template v-if="searchType === 0">
<h3 class="text-2xl mr-4">{{ item.title }}</h3> <nuxt-link :to="categoryNames[item.category_id].path + '/' + item.id">
<span class="category text-md px-4 py-1">{{ categoryNames[item.category_id] }}</span> <div class="article mb-9">
</div> <div class="title flex items-center mb-5">
<h3 class="text-2xl mr-4">{{ item.title }}</h3>
<p class="text-gray-400 ">{{ item.description }}</p> <span class="category text-md px-4 py-1">{{
categoryNames[item.category_id].name
</div> }}</span>
<div class="article-bottom flex justify-between"> </div>
<a target="_blank" class="article-link"
:href="item.fromLink ? item.fromLink: 'javascript:void(0);'">文章来源: {{ <p class="text-gray-400 ">{{ item.desc }}</p>
item.fromDesc
}}</a> </div>
<span class="text-gray-400">{{ item.time }}</span> <div class="article-bottom flex justify-between">
</div> <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>
</nuxt-link>
</template>
<template v-else>
<nuxt-link :to="'/' + routes[route.path.split('/')[2]] + '/' + item.id">
<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">{{
routes[route.path.split('/')[2]]
}}</span>
</div>
<p class="text-gray-400 ">{{ item.description }}</p>
</div>
<div class="article-bottom flex justify-between">
<a :target="item.fromLink ? '_blank': ''" class="article-link"
:href="item.fromLink ? item.fromLink: 'javascript:void(0);'">文章来源: {{
item.fromDesc
}}</a>
<span class="text-gray-400">{{
dayjs(item.createtime * 1000).format('YYYY-MM-DD hh:mm:ss')
}}</span>
</div>
</nuxt-link>
</template>
</div>
<div v-else>
<el-empty description="暂无数据"/>
</div> </div>
</div> </div>
<div class="mt-32"> <div class="mt-32">
@ -33,6 +67,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import dayjs from "dayjs";
enum Category { enum Category {
index, index,
inform, inform,
@ -42,12 +78,33 @@ enum Category {
} }
const categoryNames = reactive({ const categoryNames = reactive({
"1": "动态资讯", "1": {
"2": "预警信息", name:"动态资讯",
"3": "法律法规", path: '/inform'
"4": "TBT/SPS通报" },
"2":{
name:"预警信息",
path: '/warning'
},
"3": {
name:"法律法规",
path: '/rules'
},
"4": {
name:"TBT/SPS通报",
path: '/tptsps'
},
"5":{
name:"案例",
path: '/case'
},
})
const routes = reactive({
"inform": "动态资讯",
"warning": "预警信息",
"rules": "法律法规",
"case": "案例"
}) })
definePageMeta({ definePageMeta({
hidden: true, hidden: true,
middleware: ['is-search'], middleware: ['is-search'],
@ -57,7 +114,7 @@ definePageMeta({
const route = useRoute() const route = useRoute()
const store = useAppStore() const store = useAppStore()
const searchVal = computed(() => store.getSearchVal) const searchVal = computed(() => store.getSearchVal)
const {commonApi} = useApi() const {commonApi, informationApi, warningApi, caseApi} = useApi()
const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePagination(1, 6, 0) const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePagination(1, 6, 0)
const content = ref([ const content = ref([
@ -80,31 +137,42 @@ function onChangePage(val: number) {
} }
async function getList() { async function getList() {
if (searchType.value === 0) { if (searchVal.value) {
const {data} = await commonApi.searchApi({keyword: searchVal.value, page: current.value, limit}) let params = {keyword: searchVal.value, page: current.value, limit}
if (searchType.value === 0) {
content.value = data.list; const {data} = await commonApi.searchApi(params)
setTotal(data.total); setData(data.data, data.total)
if (data) { } else if (route.path === '/search/inform') {
// loading.value = false; const {data} = await informationApi.getInformationList(params)
} setData(data.data, data.total)
}else { } else if (route.path === '/search/warning') {
const {data} = await commonApi.searchApi({keyword: searchVal.value, page: current.value, limit, category_id: searchType.value}) const {data} = await warningApi.getWarningList(params)
setData(data.data, data.total)
content.value = data.list; } else if (route.path === '/search/case') {
setTotal(data.total); const {data} = await caseApi.getCaseList(params)
if (data) { setData(data.data, data.total)
// loading.value = false;
} }
} }
} }
function setData(data: Array<any>, total: number) {
content.value = data;
setTotal(total);
}
// onMounted(()=>{
// getList()
// })
//
// watch(() => store.$state.searchVal, () => {
// })
watchEffect(() => { watchEffect(() => {
searchType.value = Category[route.params.id as unknown as any] as unknown as number; searchType.value = Category[route.params.id as unknown as any] as unknown as number;
console.log(searchType.value ) getList()
onChangePage(1)
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -120,6 +188,7 @@ watchEffect(() => {
.article-link { .article-link {
color: #0055AB; color: #0055AB;
} }
.category { .category {
color: #022950; color: #022950;
border-radius: 8px; border-radius: 8px;

@ -30,7 +30,7 @@
</el-row> </el-row>
</el-form> </el-form>
<el-table v-loading="loading" size="large" border :data="content" :empty-text="'暂无数据'" <el-table v-loading="loading" size="large" border :data="content" :empty-text="'暂无数据'"
:header-cell-style="{background: '#f5f5f5', color:'#333333'}"> :header-cell-style="{background: '#f5f5f5', color:'#333333'}" @cellClick="handleCellClick">
<el-table-column show-overflow-tooltip align="center" label="通报号" <el-table-column show-overflow-tooltip align="center" label="通报号"
prop="notification_number"></el-table-column> prop="notification_number"></el-table-column>
<el-table-column show-overflow-tooltip align="center" label="通报标题" <el-table-column show-overflow-tooltip align="center" label="通报标题"
@ -61,7 +61,6 @@
import {randomUUID} from '~~/utils'; import {randomUUID} from '~~/utils';
import dayjs from "dayjs"; import dayjs from "dayjs";
import {useThrottleFn} from "@vueuse/core";
definePageMeta({ definePageMeta({
name: 'TBT/SPS通报', name: 'TBT/SPS通报',
@ -91,7 +90,7 @@ const currentTab = ref({});
const content = ref([]); const content = ref([]);
const loading = ref(true); const loading = ref(true);
const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePagination(1, 6, 0) const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePagination(1, 6, 0)
const router = useRouter();
const searchData = ref({ const searchData = ref({
notifying_members: '', notifying_members: '',
notification_time: '', notification_time: '',
@ -99,6 +98,12 @@ const searchData = ref({
product: '', product: '',
}) })
function handleCellClick(data: any) {
router.push({
path: '/tptsps/'+ data.id
})
}
function resetData(flag: boolean = true) { function resetData(flag: boolean = true) {
searchData.value = { searchData.value = {
notifying_members: '', notifying_members: '',

@ -64,7 +64,7 @@ const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePaginatio
const tabs = ref([ const tabs = ref([
{ {
name: '动态资讯', name: '预警信息',
id: randomUUID(), id: randomUUID(),
children: [ children: [
{name: 'WTO资讯', id: randomUUID()}, {name: 'WTO资讯', id: randomUUID()},

@ -47,9 +47,13 @@ const fetch = $fetch.create({
// 响应拦截 // 响应拦截
onResponse(ctx) { onResponse(ctx) {
const {response} = ctx; const {response} = ctx;
console.log('response>>>>>', ctx)
let data = response._data; let data = response._data;
console.log('data.type>>>', data.type)
// 在这里判断错误 // 在这里判断错误
if (data.code != 1) { if (data.type && data.type.includes('image')) {
return data;
}else if (data.code != 1) {
transform(ctx) transform(ctx)
return Promise.reject(ctx) return Promise.reject(ctx)
} }

Loading…
Cancel
Save