@ -0,0 +1,24 @@ |
|||
# Nuxt dev/build outputs |
|||
.output |
|||
.data |
|||
.nuxt |
|||
.nitro |
|||
.cache |
|||
dist |
|||
|
|||
# Node dependencies |
|||
node_modules |
|||
|
|||
# Logs |
|||
logs |
|||
*.log |
|||
|
|||
# Misc |
|||
.DS_Store |
|||
.fleet |
|||
.idea |
|||
|
|||
# Local env files |
|||
.env |
|||
.env.* |
|||
!.env.example |
@ -0,0 +1,2 @@ |
|||
shamefully-hoist=true |
|||
strict-peer-dependencies=false |
@ -0,0 +1,63 @@ |
|||
# Nuxt 3 Minimal Starter |
|||
|
|||
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more. |
|||
|
|||
## Setup |
|||
|
|||
Make sure to install the dependencies: |
|||
|
|||
```bash |
|||
# npm |
|||
npm install |
|||
|
|||
# pnpm |
|||
pnpm install |
|||
|
|||
# yarn |
|||
yarn install |
|||
``` |
|||
|
|||
## Development Server |
|||
|
|||
Start the development server on `http://localhost:3000`: |
|||
|
|||
```bash |
|||
# npm |
|||
npm run dev |
|||
|
|||
# pnpm |
|||
pnpm run dev |
|||
|
|||
# yarn |
|||
yarn dev |
|||
``` |
|||
|
|||
## Production |
|||
|
|||
Build the application for production: |
|||
|
|||
```bash |
|||
# npm |
|||
npm run build |
|||
|
|||
# pnpm |
|||
pnpm run build |
|||
|
|||
# yarn |
|||
yarn build |
|||
``` |
|||
|
|||
Locally preview production build: |
|||
|
|||
```bash |
|||
# npm |
|||
npm run preview |
|||
|
|||
# pnpm |
|||
pnpm run preview |
|||
|
|||
# yarn |
|||
yarn preview |
|||
``` |
|||
|
|||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. |
@ -0,0 +1,21 @@ |
|||
import http from './request' |
|||
|
|||
export const getArticleList = (params: any) => { |
|||
return new Promise((resolve,reject)=>{ |
|||
http.get('/cms/article/page',params).then((res)=> { |
|||
resolve(res) |
|||
}).catch((err)=>{ |
|||
reject(err.message) |
|||
}) |
|||
}) |
|||
} |
|||
|
|||
export const getArticle = (params: any) => { |
|||
return new Promise((resolve,reject)=>{ |
|||
http.get('/cms/article/get',params).then((res)=> { |
|||
resolve(res) |
|||
}).catch((err)=>{ |
|||
reject(err.message) |
|||
}) |
|||
}) |
|||
} |
@ -0,0 +1,66 @@ |
|||
const appConfig = { |
|||
// BASE_URL: 'http://127.0.0.1:48080/app-api',
|
|||
BASE_URL: 'http://119.23.220.80:16801/app-api', |
|||
TENANT_ID: 151 |
|||
} |
|||
|
|||
let clientId: any |
|||
|
|||
|
|||
const fetch = async (url: string, options: any) => { |
|||
if (!url) { |
|||
console.warn('url is must be string!') |
|||
return |
|||
} |
|||
const $config = useRuntimeConfig() |
|||
const reqUrl = url.indexOf('http') > -1 ? url : appConfig.BASE_URL + url |
|||
|
|||
if (!options.headers) { |
|||
options.credentials = 'include' // 跨域携带cookie
|
|||
options.headers = { |
|||
'tenant-id': appConfig.TENANT_ID |
|||
} |
|||
} |
|||
|
|||
return new Promise((resolve, reject) => { |
|||
console.log(reqUrl) |
|||
useFetch(reqUrl, { ...options }).then(({ data, error }) => { |
|||
if (error && error.value) { |
|||
reject(error.value) |
|||
return |
|||
} |
|||
const res: any = data.value |
|||
if (res && res.code === 0) { |
|||
// return res 正确应该返回
|
|||
resolve(res.data) |
|||
} else if (res && (res.msg || res.errMsg || res.message)) { |
|||
console.error(res.msg) |
|||
|
|||
if (res.code === 401) { // 会话过期跳登录
|
|||
setTimeout(()=>{ |
|||
navigateTo('/login') |
|||
}, 1000) |
|||
return |
|||
} |
|||
reject(res.message) |
|||
} |
|||
}).catch(err => { |
|||
reject(err) |
|||
}) |
|||
}) |
|||
} |
|||
|
|||
export default new class Http { |
|||
|
|||
get(url: string, params: any) { |
|||
return fetch(url, { method: 'GET', params }) |
|||
} |
|||
|
|||
post(url: string, body: any) { |
|||
return fetch(url, { method: 'POST', body }) |
|||
} |
|||
|
|||
reqData(url: string, body: any) { |
|||
return fetch(url, { method: 'POST', body, headers: {} }) |
|||
} |
|||
} |
@ -0,0 +1,23 @@ |
|||
import http from './request' |
|||
|
|||
|
|||
export const getSiteInfo = () => { |
|||
return new Promise((resolve,reject)=>{ |
|||
http.get('/cms/site-info/get',{}).then((res)=> { |
|||
resolve(res) |
|||
}).catch((err)=>{ |
|||
reject(err.message) |
|||
}) |
|||
}) |
|||
} |
|||
|
|||
|
|||
export const getBanner = (params: any) => { |
|||
return new Promise((resolve,reject)=>{ |
|||
http.get('/cms/banner/list',params).then((res)=> { |
|||
resolve(res) |
|||
}).catch((err)=>{ |
|||
reject(err.message) |
|||
}) |
|||
}) |
|||
} |
@ -0,0 +1,22 @@ |
|||
import http from './request' |
|||
|
|||
export const getVideoList = (params: any) => { |
|||
return new Promise((resolve,reject)=>{ |
|||
http.get('/cms/video/page',params).then((res)=> { |
|||
resolve(res) |
|||
}).catch((err)=>{ |
|||
reject(err.message) |
|||
}) |
|||
}) |
|||
} |
|||
|
|||
|
|||
export const getVideo = (params: any) => { |
|||
return new Promise((resolve,reject)=>{ |
|||
http.get('/cms/video/get',params).then((res)=> { |
|||
resolve(res) |
|||
}).catch((err)=>{ |
|||
reject(err.message) |
|||
}) |
|||
}) |
|||
} |
@ -0,0 +1,4 @@ |
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|||
export default defineAppConfig({ |
|||
BASE_URL: 'http://127.0.0.1:48080/app-api' |
|||
}) |
@ -0,0 +1,54 @@ |
|||
<template> |
|||
<div class=""> |
|||
<NuxtLayout name="default"> |
|||
<NuxtLoadingIndicator color="red" /> |
|||
<NuxtPage /> |
|||
</NuxtLayout> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {getSiteInfo} from "~/api/site"; |
|||
const siteInfo = useSiteInfo() |
|||
useHead({ |
|||
title: '金梦网' |
|||
}) |
|||
const themeOverrides = { |
|||
common: { |
|||
primaryColor: "#FC8952", |
|||
primaryColorHover: "#FC8952", |
|||
primaryColorPressed: "#FC8952", |
|||
primaryColorSuppl: "#FC8952", |
|||
}, |
|||
Button: { |
|||
textColor: "#FC8952", |
|||
border: "1px solid #FF763B", |
|||
} |
|||
}; |
|||
|
|||
getSiteInfo().then((res: any) => { |
|||
const data = res |
|||
siteInfo.value = data |
|||
}).catch(err=>{ |
|||
console.log(err) |
|||
}) |
|||
|
|||
</script> |
|||
|
|||
<style> |
|||
body{ |
|||
background-color: rgba(249, 249, 249, 1); |
|||
} |
|||
.w-1200 { |
|||
width: 1200px; |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
} |
|||
.w-1440{ |
|||
width: 1440px; |
|||
margin: 0 auto; |
|||
} |
|||
.header-height{ height: 80px} |
|||
.nav { |
|||
border-bottom: 1px solid rgba(137, 107, 52, 0.15); |
|||
} |
|||
</style> |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 762 B |
After Width: | Height: | Size: 4.7 MiB |
After Width: | Height: | Size: 139 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 629 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 757 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 1002 KiB |
@ -0,0 +1,124 @@ |
|||
export const particlesJson = { |
|||
background: { |
|||
// color: "#eef3f7",
|
|||
image: '~/assets/images/zixun-bg.png' |
|||
}, |
|||
fullScreen: { |
|||
zIndex: -1, |
|||
enable: false |
|||
}, |
|||
particles: { |
|||
number: { |
|||
value: 200, |
|||
density: { |
|||
enable: !0, |
|||
value_area: 800 |
|||
} |
|||
}, |
|||
color: { |
|||
value: "#EAF0F6" |
|||
}, |
|||
shape: { |
|||
type: "circle", |
|||
stroke: { |
|||
width: 0, |
|||
color: "#ff0000" |
|||
}, |
|||
polygon: { |
|||
nb_sides: 5 |
|||
}, |
|||
image: { |
|||
src: "", |
|||
width: 100, |
|||
height: 100 |
|||
} |
|||
}, |
|||
opacity: { |
|||
value: 1, |
|||
random: !1, |
|||
anim: { |
|||
enable: !1, |
|||
speed: 2, |
|||
opacity_min: 0, |
|||
sync: !1 |
|||
} |
|||
}, |
|||
size: { |
|||
value: 3, |
|||
random: !1, |
|||
anim: { |
|||
enable: !1, |
|||
speed: 20, |
|||
size_min: 0, |
|||
sync: !1 |
|||
} |
|||
}, |
|||
line_linked: { |
|||
enable: !0, |
|||
distance: 100, |
|||
color: "#EAF0F6", |
|||
opacity: 1, |
|||
width: 1 |
|||
}, |
|||
move: { |
|||
enable: !0, |
|||
speed: 2, |
|||
direction: "none", |
|||
random: !1, |
|||
straight: !1, |
|||
out_mode: "out", |
|||
bounce: !1, |
|||
attract: { |
|||
enable: !1, |
|||
rotateX: 3e3, |
|||
rotateY: 3e3 |
|||
} |
|||
}, |
|||
array: [] |
|||
}, |
|||
interactivity: { |
|||
detect_on: "canvas", |
|||
events: { |
|||
onhover: { |
|||
enable: !0, |
|||
mode: "grab" |
|||
}, |
|||
onclick: { |
|||
enable: !0, |
|||
mode: "push" |
|||
}, |
|||
resize: !0 |
|||
}, |
|||
modes: { |
|||
grab: { |
|||
distance: 100, |
|||
line_linked: { |
|||
opacity: 1 |
|||
} |
|||
}, |
|||
bubble: { |
|||
distance: 200, |
|||
size: 80, |
|||
duration: .4 |
|||
}, |
|||
repulse: { |
|||
distance: 200, |
|||
duration: .4 |
|||
}, |
|||
push: { |
|||
particles_nb: 4 |
|||
}, |
|||
remove: { |
|||
particles_nb: 2 |
|||
} |
|||
}, |
|||
mouse: {} |
|||
}, |
|||
retina_detect: !1, |
|||
fn: { |
|||
interact: {}, |
|||
modes: {}, |
|||
vendors: {} |
|||
}, |
|||
tmp: {} |
|||
} |
@ -0,0 +1,30 @@ |
|||
|
|||
<template> |
|||
<video ref="video" :id="id" :src="src" @mouseleave="mouseleave" @mouseover="mouseover"></video> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
const props = defineProps({ |
|||
id: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
src: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
}) |
|||
|
|||
const mouseover = () => { |
|||
|
|||
} |
|||
|
|||
const mouseleave = () => { |
|||
|
|||
} |
|||
|
|||
|
|||
</script> |
|||
|
|||
<style scoped> |
|||
|
|||
</style> |
@ -0,0 +1,41 @@ |
|||
interface SiteInfo{ |
|||
siteName: string; |
|||
siteNameEn: string; |
|||
siteDesc: string; |
|||
siteDescEn: string; |
|||
logo: string; |
|||
wechatImage?: string; |
|||
wecomImage?: string; |
|||
wxmpImage?: string; |
|||
wechat?: string; |
|||
wxgzhImage?: string; |
|||
linkedin?: string; |
|||
linkedinImage?: string; |
|||
whatsapp?: string; |
|||
whatsappImage?: string; |
|||
email?: string; |
|||
emailImage?: string; |
|||
address?: string; |
|||
addressEn?: string; |
|||
pov?: string; |
|||
} |
|||
|
|||
|
|||
export const useSiteInfo = () => { |
|||
const siteInfo = useState<SiteInfo>('siteInfo', () => { |
|||
return { |
|||
siteName: '', |
|||
siteNameEn: '', |
|||
siteDesc: '', |
|||
siteDescEn: '', |
|||
logo: '', |
|||
} |
|||
}) |
|||
return siteInfo; |
|||
} |
|||
|
|||
export const useLang = () => useState<string>('lang', () => 'zh') |
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,72 @@ |
|||
|
|||
export default defineI18nConfig(() => ({ |
|||
legacy: false, |
|||
locale: 'zh', |
|||
warnHtmlMessage: false, |
|||
messages: { |
|||
zh: { |
|||
language: 'English', |
|||
homePage: '首页', |
|||
aboutUs: '关于金梦网', |
|||
news: '最新资讯', |
|||
africanVideo: '走进非洲视频', |
|||
serviceAndProduct: '服务与产品', |
|||
service: '服务', |
|||
product: '产品', |
|||
link: '跳转链接', |
|||
readMord: '查看更多', |
|||
viewsCount: '浏览次数', |
|||
email: '邮箱', |
|||
wechat: '微信', |
|||
LinkedIn: 'LinkedIn', |
|||
WhatsAPp: 'WhatsAPp', |
|||
detail: '查看', |
|||
search: '搜索', |
|||
searchResult: '搜索结果', |
|||
wxOfficialAccounts: '公众号', |
|||
weCom: '企业微信', |
|||
wxMP: '微信小程序', |
|||
address: '地址', |
|||
icp: '备案号', |
|||
contactUs: '联系我们', |
|||
source: '来源', |
|||
article: '文章', |
|||
video: '视频', |
|||
noArticle: '未找到相关文章', |
|||
noVideo: '未找到相关视频', |
|||
|
|||
}, |
|||
en: { |
|||
language: '中文', |
|||
homePage: 'Home', |
|||
aboutUs: 'About', |
|||
news: 'News', |
|||
africanVideo: 'African Video', |
|||
serviceAndProduct: 'Service&Product', |
|||
service: 'Service', |
|||
product: 'Product', |
|||
readMord: 'More', |
|||
viewsCount: 'views', |
|||
email: 'Email', |
|||
wechat: 'Wechat', |
|||
LinkedIn: 'LinkedIn', |
|||
WhatsAPp: 'WhatsAPp', |
|||
detail: 'Detail', |
|||
search: 'Search', |
|||
searchResult: 'Search Result', |
|||
wxOfficialAccounts: 'Official Accounts', |
|||
weCom: 'WeCom', |
|||
wxMP: 'Mini Program', |
|||
address: 'Address', |
|||
icp: 'ICP', |
|||
contactUs: 'Contact Us', |
|||
source: 'Source', |
|||
article: 'Article', |
|||
video: 'Video', |
|||
noArticle: 'No related articles found', |
|||
noVideo: 'No related videos found', |
|||
|
|||
|
|||
} |
|||
} |
|||
})) |
@ -0,0 +1,231 @@ |
|||
<template> |
|||
<div class="footer-box"> |
|||
<div class="footer w-1200"> |
|||
<div class="flex justify-between items-center footer-item1"> |
|||
<div class="flex items-center"> |
|||
<img class="w-[45px]" src="~/assets/image/logo.png"/> |
|||
<p class="logo-name">{{ locale == 'zh' ? siteInfo.siteName : siteInfo.siteNameEn }}</p> |
|||
</div> |
|||
|
|||
<div class="tr"> |
|||
<!-- 邮箱 --> |
|||
|
|||
<NPopover :z-index="100" |
|||
arrow-style="background: linear-gradient(180deg, rgba(137,107,52,1) 1%,rgba(250,235,201,1) 100%);" |
|||
:raw="true" trigger="hover" placement="bottom"> |
|||
<template #trigger> |
|||
<div class="ml-6"> |
|||
|
|||
<div class="flex items-center cursor-pointer"> |
|||
<img class="w-[24px]" src="~/assets/image/mail.png"/> |
|||
<p class="ml-[10px]">{{ $t('email') }}</p> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<template #default> |
|||
<div class="lxfs flex flex-col justify-center items-center"> |
|||
<p>{{ siteInfo.email }}</p> |
|||
<template v-if="siteInfo.emailImage"> |
|||
<img :src="siteInfo.emailImage" class="cover-fill w-[100px] h-[100px] code mt-2"/> |
|||
<p class="py-1"></p> |
|||
</template> |
|||
</div> |
|||
</template> |
|||
|
|||
</NPopover> |
|||
<!-- WhatsApp --> |
|||
|
|||
<NPopover :z-index="100" |
|||
arrow-style="background: linear-gradient(180deg, rgba(137,107,52,1) 1%,rgba(250,235,201,1) 100%);" |
|||
:raw="true" trigger="hover" placement="bottom"> |
|||
<template #trigger> |
|||
<div class="ml-6"> |
|||
|
|||
<div class="flex items-center cursor-pointer"> |
|||
<img class="w-[24px]" src="~/assets/image/phone2.png"/> |
|||
<p class="ml-[10px]">{{ $t('WhatsApp') }}</p> |
|||
</div> |
|||
</div> |
|||
|
|||
</template> |
|||
<template #default> |
|||
<div class="lxfs flex flex-col justify-center items-center"> |
|||
<p>{{ siteInfo.whatsapp }}</p> |
|||
<img v-if="siteInfo.whatsappImage" :src="siteInfo.whatsappImage" |
|||
class="cover-fill w-[100px] h-[100px] code mt-2 /"> |
|||
<p v-if="siteInfo.whatsappImage" class="py-1"></p> |
|||
</div> |
|||
</template> |
|||
</NPopover> |
|||
<!-- LinkedIn--> |
|||
<NPopover :z-index="100" |
|||
arrow-style="background: linear-gradient(180deg, rgba(137,107,52,1) 1%,rgba(250,235,201,1) 100%);" |
|||
:raw="true" trigger="hover" placement="bottom"> |
|||
<template #trigger> |
|||
<div class="ml-6"> |
|||
<div class="flex items-center cursor-pointer"> |
|||
<img class="w-[24px]" src="~/assets/image/in.png"/> |
|||
<p class="ml-[10px]">{{ $t('LinkedIn') }}</p> |
|||
</div> |
|||
</div> |
|||
|
|||
</template> |
|||
<template #default> |
|||
<div class="lxfs flex flex-col justify-center items-center"> |
|||
<p>{{ siteInfo.linkedin }}</p> |
|||
<img v-if="siteInfo.linkedinImage" :src="siteInfo.linkedinImage" |
|||
class="cover-fill w-[100px] h-[100px] code mt-2 /"> |
|||
<p v-if="siteInfo.linkedinImage" class="py-1"></p> |
|||
</div> |
|||
</template> |
|||
</NPopover> |
|||
<!-- 微信 --> |
|||
|
|||
<NPopover :z-index="100" |
|||
arrow-style="background: linear-gradient(180deg, rgba(137,107,52,1) 1%,rgba(250,235,201,1) 100%);" |
|||
:raw="true" trigger="hover" placement="bottom"> |
|||
<template #trigger> |
|||
<div class="ml-6"> |
|||
|
|||
<div class="flex items-center cursor-pointer"> |
|||
<img class="w-[24px]" src="~/assets/image/weixin.png"/> |
|||
<p class="ml-[10px]">{{ $t('wechat') }}</p> |
|||
</div> |
|||
</div> |
|||
|
|||
</template> |
|||
<template #default> |
|||
<div class="lxfs flex flex-col justify-center items-center"> |
|||
<p>{{ siteInfo.wechat }}</p> |
|||
<img v-if="siteInfo.wechatImage" :src="siteInfo.wechatImage" |
|||
class="cover-fill w-[100px] h-[100px] code mt-2 /"> |
|||
<p v-if="siteInfo.wechatImage" class="py-1"></p> |
|||
</div> |
|||
</template> |
|||
</NPopover> |
|||
|
|||
|
|||
</div> |
|||
</div> |
|||
<div class="footer-item2 flex justify-between items-center"> |
|||
<div class="flex"> |
|||
<div class=" wow animate__fadeInUp mr-[50px]"> |
|||
<p style="color: #FFFFFF;font-size: 17px">{{ $t('link') }}</p> |
|||
<NuxtLink class="mt-[13px]" :to="localePath('/about')" |
|||
style="color: rgba(255,255,255,.6);font-size: 14px ;display: block">{{ $t('aboutUs') }} |
|||
</NuxtLink> |
|||
<NuxtLink class="mt-[7px]" :to="localePath('/service')" |
|||
style="color: rgba(255,255,255,.6);font-size: 14px; display: block">{{ $t('service') }} |
|||
</NuxtLink> |
|||
<NuxtLink class="mt-[7px]" :to="localePath('/product')" |
|||
style="color: rgba(255,255,255,.6);font-size: 14px; display: block">{{ $t('product') }} |
|||
</NuxtLink> |
|||
<NuxtLink class="mt-[7px]" :to="localePath('/african-video')" |
|||
style="color: rgba(255,255,255,.6);font-size: 14px ;display: block">{{ $t('africanVideo') }} |
|||
</NuxtLink> |
|||
<NuxtLink class="mt-[7px]" :to="localePath('/news')" |
|||
style="color: rgba(255,255,255,.6);font-size: 14px; display: block">{{ $t('news') }} |
|||
</NuxtLink> |
|||
</div> |
|||
<div class="wow animate__fadeInUp mr-[50px]"> |
|||
<div> |
|||
<p style="color: #FFFFFF ;font-size: 17px;margin-bottom: 12px;text-align: center;"> |
|||
{{ $t('wxOfficialAccounts') }}</p> |
|||
<img :src="siteInfo.wxgzhImage" class="cover-fill w-[100px] h-[100px] code"> |
|||
</div> |
|||
</div> |
|||
<div class="wow animate__fadeInUp mr-[50px]"> |
|||
<div> |
|||
<p style="color: #FFFFFF ;font-size: 17px;margin-bottom: 12px;text-align: center;">{{ $t('wxMP') }}</p> |
|||
<img :src="siteInfo.wxmpImage" class="cover-fill w-[100px] h-[100px] code"> |
|||
</div> |
|||
</div> |
|||
<div class="wow animate__fadeInUp mr-[50px]"> |
|||
<div> |
|||
<p style="color: #FFFFFF ;font-size: 17px;margin-bottom: 12px;text-align: center;">{{ $t('weCom') }}</p> |
|||
<img :src="siteInfo.wecomImage" class="cover-fill w-[100px] h-[100px] code"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div> |
|||
<p class="flex items-center wow animate__backInRight" style="flex-direction: row-reverse;"> |
|||
<span style="color: #896B34;font-size: 35px;font-weight: bold;">{{ siteInfo.phone }}</span> |
|||
<img class="w-[30px] mr-[8px] h-[30px]" src="~/assets/image/phone.png"/> |
|||
</p> |
|||
<!-- <p style="font-size: 14px;color: rgba(255,255,255,.4);margin-top: 20px" class="text-right">{{siteInfo.siteDesc}}</p>--> |
|||
<p style="font-size: 14px;color: rgba(255,255,255,.6)" class="text-right"> |
|||
{{ $t('address') }}:{{ locale == 'zh' ? siteInfo.address : siteInfo.addressEn }}</p> |
|||
</div> |
|||
|
|||
</div> |
|||
<div class="flex justify-between"> |
|||
<p class="" style="font-size: 14px;color: rgba(255,255,255,.4);margin-top: 20px;"> |
|||
{{ locale == 'zh' ? siteInfo.companyName : siteInfo.companyNameEn }} {{ $t('icp') }}: |
|||
{{ locale == 'zh' ? siteInfo.pov : siteInfo.pov }}</p> |
|||
<p class="" style="font-size: 14px;color: rgba(255,255,255,.4);margin-top: 20px;">{{ $t('contactUs') }}</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NPopover} from 'naive-ui' |
|||
|
|||
const {locale} = useI18n() |
|||
const siteInfo = useSiteInfo() |
|||
const localePath = useLocalePath() |
|||
</script> |
|||
<style scoped> |
|||
.footer-box { |
|||
//background: #363636; background-image: url("~/assets/image/footer-bg.png"); background-size: contain; |
|||
} |
|||
|
|||
.footer { |
|||
height: 480px; |
|||
} |
|||
|
|||
.footer-place { |
|||
height: 400px; |
|||
} |
|||
|
|||
.logo-name { |
|||
font-size: 20px; |
|||
color: rgba(255, 255, 255, .87); |
|||
margin-left: 15px; |
|||
} |
|||
|
|||
|
|||
.tr { |
|||
display: flex; |
|||
flex-direction: row-reverse; |
|||
color: rgba(255, 255, 255, .87); |
|||
font-size: 18px; |
|||
} |
|||
|
|||
|
|||
.footer-item1 { |
|||
border-bottom: 1px solid rgba(255, 255, 255, .1); |
|||
height: 120px; |
|||
} |
|||
|
|||
.footer-item2 { |
|||
border-bottom: 1px solid rgba(255, 255, 255, .1); |
|||
height: 210px; |
|||
} |
|||
|
|||
.footer-item2 img { |
|||
object-fit: cover; |
|||
} |
|||
|
|||
.code { |
|||
border-radius: 8px; |
|||
} |
|||
|
|||
.lxfs { |
|||
background: linear-gradient(180deg, rgba(137, 107, 52, 1) 1%, rgba(250, 235, 201, 1) 100%); |
|||
padding: 5px 10px; |
|||
border-radius: 4px; |
|||
color: #303030; |
|||
font-size: 16px; |
|||
} |
|||
</style> |
@ -0,0 +1,137 @@ |
|||
<template> |
|||
<header class="header w-full"> |
|||
<div class="container header-height flex items-center"> |
|||
<NuxtLink :to="localePath('/')" class="logo-box flex items-center"> |
|||
<img class="logo" :src="siteInfo.logo"/> |
|||
</NuxtLink> |
|||
<div class="flex-1 flex"> |
|||
<NuxtLink :class="{active: activeKey.startsWith('index') }" class="nav-item items-center flex px-4 hover:text-yellow" :to="localePath('/')"> |
|||
{{ $t('homePage') }} |
|||
</NuxtLink> |
|||
<NuxtLink :class="{active: activeKey.startsWith('news')}" class="nav-item items-center flex px-4" :to="localePath('/news')"> |
|||
{{ $t('news') }} |
|||
</NuxtLink> |
|||
<NuxtLink :class="{active: activeKey.startsWith('african-video')}" class="nav-item items-center flex px-4" :to="localePath('/african-video')" > |
|||
{{ $t('africanVideo') }} |
|||
</NuxtLink> |
|||
<NPopover trigger="hover" placement="bottom"> |
|||
<template #trigger> |
|||
<span :style="{color: (activeKey.startsWith('service') || activeKey.startsWith('product')? '#896B34':'')}" class="nav-item items-center flex px-4 cursor-pointer"> |
|||
{{$t('serviceAndProduct')}} |
|||
</span> |
|||
</template> |
|||
<div class="p-2"> |
|||
<NuxtLink :class="{active: activeKey.startsWith('service')}" class="nav-item items-center flex py-2" :to="localePath('/service')"> |
|||
{{ $t('service') }} |
|||
</NuxtLink> |
|||
<NuxtLink :class="{active: activeKey.startsWith('product')}" class="nav-item items-center flex py-2" :to="localePath('/product')"> |
|||
{{ $t('product') }} |
|||
</NuxtLink> |
|||
</div> |
|||
</NPopover> |
|||
|
|||
|
|||
<NuxtLink :class="{active: activeKey.startsWith('about')}" class="nav-item items-center flex px-4" :to="localePath('/about')"> |
|||
{{ $t('aboutUs') }} |
|||
</NuxtLink> |
|||
</div> |
|||
<NSpace class="items-center"> |
|||
<NInput @keydown="searchFunc" :placeholder="$t('search')" size="medium" v-model:value="keyword"> |
|||
<template #prefix> |
|||
<n-icon :component="SearchOutline" color="#E5E5E5" /> |
|||
</template> |
|||
</NInput> |
|||
<NButton size="medium" text type="default" @click="switchLanguage" tertiary>{{ $t('language') }}</NButton> |
|||
</NSpace> |
|||
</div> |
|||
</header> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {MenuOption, NIcon, NInput, NButton, NSpace,NDropdown,NPopover} from "naive-ui"; |
|||
import {NuxtLink} from "#components"; |
|||
import {SearchOutline} from "@vicons/ionicons5"; |
|||
// 站点信息 |
|||
const siteInfo = useSiteInfo() |
|||
|
|||
// 当前页面高亮 |
|||
const activeKey = ref<String>('index') |
|||
const route = useRoute() |
|||
activeKey.value = route.name?route.name.toString(): '' |
|||
watch( |
|||
() => route.name, |
|||
(name) => { |
|||
console.log(name) |
|||
activeKey.value = name?name.toString(): '' |
|||
} |
|||
) |
|||
|
|||
const serviceAndProduct = ref<any[]>([ |
|||
{ |
|||
label: '布朗酒店,伦敦', |
|||
key: "brown's hotel, london" |
|||
}, |
|||
]) |
|||
|
|||
// 切换语言 |
|||
const { locale, locales, setLocale } = useI18n() |
|||
const localePath = useLocalePath() |
|||
const switchLanguage = () => { |
|||
locale.value = locale.value == 'zh' ? 'en' : 'zh' |
|||
useCookie('lang').value = locale.value |
|||
} |
|||
// 搜索 |
|||
const keyword = ref<String>('') |
|||
const searchFunc = (e: any) => { |
|||
if(e.key === 'Enter'){ |
|||
const path = localePath({ |
|||
path: '/search', |
|||
query: { |
|||
word: keyword.value |
|||
} |
|||
}) |
|||
navigateTo(path) |
|||
} |
|||
} |
|||
|
|||
</script> |
|||
<style scoped> |
|||
.header { |
|||
position: fixed; |
|||
top: 0; |
|||
z-index: 999; |
|||
background: rgba(255,255,255, .7); |
|||
color: #333333; |
|||
|
|||
} |
|||
|
|||
.logo-box{ |
|||
max-width: 300px; |
|||
height: 60px; |
|||
overflow: hidden; |
|||
display: flex; |
|||
align-content: center; |
|||
} |
|||
.logo{ |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: contain; |
|||
} |
|||
|
|||
.container { |
|||
width: 1200px; |
|||
margin: 0 auto; |
|||
} |
|||
|
|||
.nav-item { |
|||
font-size: 18px; |
|||
position: relative; |
|||
} |
|||
|
|||
.nav-item:hover { |
|||
color: #896B34; |
|||
} |
|||
|
|||
.nav-item.active { |
|||
color: #896B34; |
|||
} |
|||
</style> |
@ -0,0 +1,16 @@ |
|||
<template> |
|||
<div> |
|||
<Header></Header> |
|||
<slot/> |
|||
<Footer></Footer> |
|||
</div> |
|||
</template> |
|||
<script lang="ts" setup> |
|||
import Header from "~/layouts/components/Header.vue"; |
|||
import Footer from "~/layouts/components/Footer.vue"; |
|||
import {NSpin} from "naive-ui"; |
|||
|
|||
</script> |
|||
<style scoped> |
|||
|
|||
</style> |
@ -0,0 +1,63 @@ |
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|||
export default defineNuxtConfig({ |
|||
theme: "", |
|||
devtools: {enabled: false}, |
|||
css: ['animate.css/animate.css'], |
|||
build: { |
|||
transpile: |
|||
process.env.NODE_ENV === 'production' |
|||
? [ |
|||
'naive-ui', |
|||
'vueuc', |
|||
'@css-render/vue3-ssr', |
|||
'@juggle/resize-observer' |
|||
] |
|||
: ['@juggle/resize-observer'] |
|||
}, |
|||
vite: { |
|||
optimizeDeps: { |
|||
include: |
|||
process.env.NODE_ENV === 'development' |
|||
? ['naive-ui', 'vueuc', 'date-fns-tz/esm/formatInTimeZone'] |
|||
: [] |
|||
} |
|||
}, |
|||
modules: [ |
|||
[ |
|||
'@nuxtjs/i18n', |
|||
{ |
|||
vueI18n: './i18n.config.ts', |
|||
defaultLocale: 'zh', |
|||
locales: ['zh', 'en'] |
|||
} |
|||
], |
|||
[ |
|||
'nuxt-lodash', |
|||
{ |
|||
prefix: "_", |
|||
prefixSkip: ["string"], |
|||
upperAfterPrefix: false, |
|||
exclude: ["map"], |
|||
alias: [ |
|||
["camelCase", "stringToCamelCase"], // => stringToCamelCase
|
|||
["kebabCase", "stringToKebab"], // => stringToKebab
|
|||
["isDate", "isLodashDate"], // => _isLodashDate
|
|||
], |
|||
} |
|||
], |
|||
'@nuxtjs/tailwindcss', |
|||
'@hypernym/nuxt-anime', |
|||
'dayjs-nuxt' |
|||
], |
|||
plugins: [ |
|||
{ |
|||
src: '~/plugins/particles.ts' |
|||
}, |
|||
{ |
|||
src: '~/plugins/wow.ts', |
|||
mode: 'client' |
|||
} |
|||
], |
|||
|
|||
|
|||
}) |
@ -0,0 +1,31 @@ |
|||
{ |
|||
"name": "nuxt-app", |
|||
"private": true, |
|||
"scripts": { |
|||
"build": "nuxt build", |
|||
"dev": "nuxt dev", |
|||
"generate": "nuxt generate", |
|||
"preview": "nuxt preview", |
|||
"postinstall": "nuxt prepare" |
|||
}, |
|||
"devDependencies": { |
|||
"@hypernym/nuxt-anime": "^2.1.0", |
|||
"@nuxt/devtools": "latest", |
|||
"@nuxtjs/i18n": "^8.0.0-rc.2", |
|||
"@types/node": "^18.17.3", |
|||
"@vicons/ionicons5": "^0.12.0", |
|||
"animate.css": "^4.1.1", |
|||
"dayjs-nuxt": "^1.1.2", |
|||
"naive-ui": "^2.34.4", |
|||
"vue-i18n": "9.3.0-beta.24", |
|||
"nuxt": "^3.6.5", |
|||
"wow.js": "^1.2.2" |
|||
}, |
|||
"dependencies": { |
|||
"@css-render/vue3-ssr": "^0.15.12", |
|||
"@nuxtjs/tailwindcss": "^6.8.0", |
|||
"nuxt-lodash": "^2.5.0", |
|||
"tsparticles-slim": "^2.12.0", |
|||
"vue3-particles": "^2.12.0" |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<p>{{ locale == 'zh' ? aboutArticle.title : aboutArticle.titleEn }}</p> |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
|
|||
<div class="w-1200 py-8"> |
|||
<div v-html="locale == 'zh' ? aboutArticle.content: aboutArticle.contentEn"></div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem} from "naive-ui"; |
|||
|
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
import {getArticle,} from "~/api/article"; |
|||
useHead({ |
|||
title: `金梦网-关于金梦网` |
|||
}) |
|||
// 获取关于我们 |
|||
const aboutArticle = ref<any>({ |
|||
title: '', |
|||
titleEn: '', |
|||
content: '', |
|||
contentEn: '', |
|||
}) |
|||
getArticle({ |
|||
id: 30 |
|||
}).then((res: any) => { |
|||
if (res) { |
|||
aboutArticle.value = res |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
|
|||
</style> |
@ -0,0 +1,126 @@ |
|||
<template> |
|||
<div> |
|||
|
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
{{ $t('africanVideo') }} |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
<!-- 视频列表--> |
|||
<div class="africen-list w-1200 mt-6 py-6"> |
|||
<NuxtLink v-for="(item, index) in videoDataList" :to="localePath('/video-detail/' + item.id)" class="africen inline-block cursor-pointer "> |
|||
<div class="africen-img-box" @mouseleave="item.play = false" @mouseover="item.play = true" > |
|||
<video v-if="item.play" autoplay muted class="africen-img-cover" :src="item.videoUrl"/> |
|||
<video v-if="!item.picUrl" v-show="!item.play" muted class="africen-img" :src="item.videoUrl"/> |
|||
<img v-if="item.picUrl" v-show="!item.play" muted class="africen-img" :src="item.picUrl"/> |
|||
<div class="africen-video-desc"> |
|||
<div class="view-num pl-2"> |
|||
<p class="flex items-center"> <NIcon :component="VideocamOutline" size="25"></NIcon> <span class="ml-1">{{item.viewsCount}}</span></p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<p class="africen-title py-2">{{locale =='zh'?item.title:item.titleEn}}</p> |
|||
<div class="africen-desc"> |
|||
<div class="africen-time">{{dayjs(item.createTime).format('YYYY-MM-DD')}}</div> |
|||
</div> |
|||
</NuxtLink> |
|||
|
|||
</div> |
|||
|
|||
<!-- 分页--> |
|||
<div class="flex justify-center py-8"> |
|||
<NPagination |
|||
:item-count="videoItemCount" |
|||
@update-page="videoPageChange" |
|||
/> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
|
|||
import {NBreadcrumb, NBreadcrumbItem, NIcon, NPagination} from "naive-ui"; |
|||
import {getVideoList} from "~/api/video"; |
|||
import {VideocamOutline} from "@vicons/ionicons5"; |
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
//获取视频 |
|||
const videoPageParams = { |
|||
pageNo: 1, |
|||
pageSize: 10 |
|||
} |
|||
|
|||
const videoItemCount = ref(0) |
|||
const videoDataList = ref<any[]>([]) |
|||
const videoPageChange = (pageNo: number) => { |
|||
getVideoList(videoPageParams).then( (res: any) => { |
|||
videoDataList.value = res.list |
|||
videoItemCount.value = res.total |
|||
}) |
|||
|
|||
} |
|||
videoPageChange(1) |
|||
</script> |
|||
<style scoped> |
|||
.africen-list{ |
|||
background-color: #FFFFFF; |
|||
|
|||
} |
|||
.africen { |
|||
width: 280px; |
|||
margin: 0 10px 30px; |
|||
} |
|||
.africen-title{ |
|||
height: 50px; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
line-height: 20px; |
|||
} |
|||
.africen-img-box { |
|||
width: 100%; |
|||
height: 175px; |
|||
position: relative; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.africen-img { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
z-index: 1; |
|||
} |
|||
|
|||
.africen-img-cover{ |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
z-index: 2; |
|||
} |
|||
|
|||
.africen-video-desc { |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 25px; |
|||
line-height: 20px; |
|||
background-image: linear-gradient(to top, rgba(0, 0, 0, .5), transparent); |
|||
color: #FFFFFF; |
|||
z-index: 10; |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
.africen-time { |
|||
color: #9A9A9A; |
|||
} |
|||
|
|||
</style> |
@ -0,0 +1,689 @@ |
|||
<template> |
|||
<div> |
|||
<!-- 轮播图--> |
|||
<NCarousel draggable autoplay class="carousel"> |
|||
<img v-for="item in bannerList" |
|||
class="carousel-img w-full" |
|||
:src="item.picUrl" |
|||
/> |
|||
</NCarousel> |
|||
<!-- 关于我们--> |
|||
<div class="about-box "> |
|||
<ClientOnly> |
|||
<vue-particles id="particles" :particlesInit="particlesInit" :options="particlesJson" |
|||
:particlesLoaded="particlesLoaded"></vue-particles> |
|||
</ClientOnly> |
|||
|
|||
<div class="about"> |
|||
<div class="about-header flex justify-between items-center"> |
|||
<p class="about-title"> |
|||
<img class="about-title-left" src="~/assets/aboutindex.png"/> |
|||
{{ locale == 'zh' ? aboutArticle.title : aboutArticle.titleEn }} |
|||
</p> |
|||
<NuxtLink :to="localePath('/about')" class="about-more hover:opacity-75">{{ $t('readMord') }} >> |
|||
</NuxtLink> |
|||
</div> |
|||
<div class="about-body flex justify-between"> |
|||
<div class="about-body-left wow animate__slideInLeft" |
|||
v-html="locale =='zh'?aboutArticle.content:aboutArticle.contentEn"> |
|||
</div> |
|||
<div class="wow animate__slideInRight"> |
|||
<div class="about-body-right"> |
|||
<img :src="aboutArticle.picUrl"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- 最新资讯 start --> |
|||
<div class="news "> |
|||
<div style="height: 38px"></div> |
|||
<div class="news-header w-1440"> |
|||
<p class="news-header-title wow animate__bounceIn">-{{ $t('news') }}-</p> |
|||
<NuxtLink :to="localePath('/news')" class="news-more hover:opacity-75">{{ $t('readMord') }} >></NuxtLink> |
|||
</div> |
|||
<div class="news-carousel-box wow animate__fadeInUp"> |
|||
<NCarousel style="height: 350px" :default-index="1" centered-slides draggable :slides-per-view="3" |
|||
prev-slide-style="transform: translateX(-170%) translateZ(-200px);opacity: 1;" |
|||
next-slide-style="transform: translateX(70%) translateZ(-200px);opacity: 1;" |
|||
effect="card"> |
|||
<NCarouselItem v-for="(item, index) in articleDataList" :key="item.id" class="news-carousel-item"> |
|||
<NuxtLink :to="localePath('/news-detail/' + item.id)" class="news-item"> |
|||
<img class="news-item-img" :src="item.picUrl"/> |
|||
<p class="news-item-title truncate">{{ locale == 'zh' ? item.title : item.titleEn }}</p> |
|||
</NuxtLink> |
|||
</NCarouselItem> |
|||
</NCarousel> |
|||
|
|||
</div> |
|||
|
|||
</div> |
|||
<!-- 最新资讯 end --> |
|||
|
|||
<!-- 走近非洲 start --> |
|||
<div class="african"> |
|||
<div style="height: 52px"></div> |
|||
<div class="news-header "> |
|||
<p style="color: #896B34" class="news-header-title wow animate__flip">-{{ $t('africanVideo') }}-</p> |
|||
</div> |
|||
<!-- 视频列表--> |
|||
<div class="w-1440 pt-6 wow animate__fadeInUp"> |
|||
<NuxtLink v-for="(item, index) in videoDataList" :to="localePath('/video-detail/' + item.id)" |
|||
class="africen inline-block cursor-pointer"> |
|||
<div class="africen-img-box" @mouseleave="item.play = false" @mouseover="item.play = true"> |
|||
<video v-if="item.play" autoplay muted class="africen-img-cover" :src="item.videoUrl"/> |
|||
<video v-if="!item.picUrl" v-show="!item.play" muted class="africen-img" :src="item.videoUrl"/> |
|||
<img v-if="item.picUrl" v-show="!item.play" muted class="africen-img" :src="item.picUrl"/> |
|||
<div class="africen-video-desc"> |
|||
<div class="view-num pl-2"> |
|||
<p class="flex items-center"> |
|||
<NIcon :component="VideocamOutline" size="25"></NIcon> |
|||
<span class="ml-1">{{ item.viewsCount }}</span> |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<p class="africen-title py-2 truncate">{{ locale == 'zh' ? item.title : item.titleEn }}</p> |
|||
<div class="africen-desc"> |
|||
<div class="africen-time">{{ dayjs(item.createTime).format('YYYY-MM-DD') }}</div> |
|||
</div> |
|||
</NuxtLink> |
|||
|
|||
</div> |
|||
|
|||
<div class="flex justify-center"> |
|||
<NuxtLink :to="localePath('/african-video')" |
|||
class="africen-more hover:opacity-75 flex items-center justify-center"> |
|||
<img style="width: 28px;margin-right: 10px" src="~/assets/image/md-remove.png"/> |
|||
{{ $t('readMord') }} |
|||
</NuxtLink> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 走近非洲 end --> |
|||
|
|||
|
|||
<!-- 服务与产品 start --> |
|||
<div class="service-product"> |
|||
<div class="w-1200 wow animate__fadeInLeftBig"> |
|||
<div class="flex justify-between border-b"> |
|||
<div class="tabs flex"> |
|||
<div @click="activeKey = 'service'" :class="{active: activeKey === 'service'}" class="tab">{{ |
|||
$t('service') |
|||
}} |
|||
</div> |
|||
<div @click="activeKey = 'product'" :class="{active: activeKey === 'product'}" class="tab">{{ |
|||
$t('product') |
|||
}} |
|||
</div> |
|||
</div> |
|||
<div> |
|||
<NuxtLink :to="localePath('/product')" class="product-more">{{ $t('readMord') }}>></NuxtLink> |
|||
</div> |
|||
</div> |
|||
<div class="tab-pane-box"> |
|||
<div v-show="activeKey == 'service'" class="tab-pane"> |
|||
<!-- :to="localePath({name: 'news-detail',params: {id: item.id}})"--> |
|||
<NuxtLink :class="{animate__headShake:item.hover,animate__animated: item.hover}" |
|||
@mouseleave="item.hover = false" @mouseover="item.hover = true" |
|||
v-for="(item, index) in serviceDataList" |
|||
:to="localePath('/news-detail/' + item.id)" |
|||
class="product flex justify-between py-8"> |
|||
<div class="flex"> |
|||
<img class="product-img" :src="item.picUrl"/> |
|||
<div class="ml-8"> |
|||
<p class="product-title">{{ locale == 'zh' ? item.title : item.titleEn }}</p> |
|||
<p class="product-content">{{ locale == 'zh' ? item.content : item.contentEn }}</p> |
|||
<p class="product-desc"><span style="color: #906D2C;">{{ item.viewsCount }}</span> |
|||
{{ $t('viewsCount') }} <span class="pl-4">{{ dayjs(item.createTime).format('YYYY-MM-DD') }}</span> |
|||
</p> |
|||
</div> |
|||
</div> |
|||
<p class="btn-detail">{{ $t('detail') }}</p> |
|||
</NuxtLink> |
|||
</div> |
|||
|
|||
<div v-show="activeKey == 'product'" class="tab-pane"> |
|||
<!-- :to="localePath({name: 'news-detail',params: {id: item.id}})"--> |
|||
<NuxtLink :class="{animate__headShake:item.hover,animate__animated: item.hover}" |
|||
@mouseleave="item.hover = false" @mouseover="item.hover = true" |
|||
v-for="(item, index) in productDataList" |
|||
:to="localePath('/news-detail/' + item.id)" |
|||
class="product flex justify-between py-8"> |
|||
<div class="flex"> |
|||
<img class="product-img" :src="item.picUrl"/> |
|||
<div class="ml-8"> |
|||
<p class="product-title">{{ locale == 'zh' ? item.title : item.titleEn }}</p> |
|||
<p class="product-content">{{ locale == 'zh' ? item.content : item.contentEn }}</p> |
|||
<p class="product-desc"><span style="color: #906D2C;">{{ item.viewsCount }}</span> |
|||
{{ $t('viewsCount') }} <span class="pl-4">{{ dayjs(item.createTime).format('YYYY-MM-DD') }}</span> |
|||
</p> |
|||
</div> |
|||
</div> |
|||
<p class="btn-detail">{{ $t('detail') }}</p> |
|||
</NuxtLink> |
|||
</div> |
|||
</div> |
|||
<!-- 分页--> |
|||
<!-- <div class="flex justify-center py-8">--> |
|||
<!-- <NPagination :item-count="productItemCount" simple/>--> |
|||
<!-- </div>--> |
|||
</div> |
|||
</div> |
|||
<!-- 服务与产品 end --> |
|||
<!-- 加载动画 --> |
|||
<div v-if="loadIng" |
|||
class="w-screen h-screen fixed bg-white top-0 left-0 right-0 bottom-0 flex items-center justify-center z-[999]"> |
|||
|
|||
<!-- <div class="">--> |
|||
|
|||
<!-- </div>--> |
|||
<span class="loading"> |
|||
<span class="loading-inner"> |
|||
<img class="" src="~/assets/image/logo.png" /> |
|||
</span> |
|||
</span> |
|||
</div> |
|||
</div> |
|||
|
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NCarousel, NPagination, NCarouselItem, NIcon, NSpin} from 'naive-ui' |
|||
import {getArticle, getArticleList} from '~/api/article' |
|||
|
|||
const siteInfo = useSiteInfo() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
const dayjs = useDayjs() |
|||
import {VideocamOutline} from '@vicons/ionicons5' |
|||
// 设置标题 |
|||
useHead({ |
|||
title: `金梦网` |
|||
}) |
|||
const activeKey = ref<String>('service') |
|||
|
|||
const loadIng = ref<Boolean>(true) |
|||
|
|||
|
|||
// 关于我们 背景动画 |
|||
import {particlesJson} from '~/assets/particles' |
|||
import {loadSlim} from "tsparticles-slim" |
|||
import {Engine} from "tsparticles-engine"; |
|||
import {getVideoList} from "~/api/video"; |
|||
import {getBanner} from "~/api/site"; |
|||
|
|||
const particlesInit = async (engine: Engine) => { |
|||
//await loadFull(engine); |
|||
await loadSlim(engine); |
|||
}; |
|||
|
|||
const particlesLoaded = async (container: any) => { |
|||
console.log("Particles container loaded", container); |
|||
}; |
|||
|
|||
// 其他动画 |
|||
onMounted(() => { |
|||
loadIng.value = false |
|||
}) |
|||
setTimeout(() => { |
|||
loadIng.value = false |
|||
}, 10000) |
|||
// 轮播图 |
|||
const bannerList = ref<any[]>([]) |
|||
getBanner({ |
|||
position: 1 |
|||
}).then((res: any) => { |
|||
bannerList.value = res |
|||
}) |
|||
|
|||
//获取视频 |
|||
const videoPageParams = { |
|||
pageNo: 1, |
|||
pageSize: 8 |
|||
} |
|||
|
|||
const videoItemCount = ref(0) |
|||
const videoDataList = ref<any[]>([]) |
|||
const videoPageChange = (pageNo: number) => { |
|||
getVideoList(videoPageParams).then((res: any) => { |
|||
videoDataList.value = res.list |
|||
videoItemCount.value = res.total |
|||
}) |
|||
|
|||
} |
|||
videoPageChange(1) |
|||
|
|||
// 获取资讯 |
|||
const articleDataList = ref<any[]>([]) |
|||
getArticleList({ |
|||
pageNo: 1, |
|||
pageSize: 10, |
|||
categoryId: 28 |
|||
}).then((res: any) => { |
|||
articleDataList.value = res.list |
|||
}) |
|||
// 获取产品 |
|||
const productItemCount = ref(0) |
|||
const productDataList = ref<any[]>([{}]) |
|||
const serviceDataList = ref<any[]>([{}]) |
|||
getArticleList({ |
|||
pageNo: 1, |
|||
pageSize: 3, |
|||
categoryId: 30 |
|||
}).then((res: any) => { |
|||
if (process.client) { |
|||
res.list.forEach(item => { |
|||
// 创建一个临时的div元素 |
|||
var tempDiv = document.createElement('div'); |
|||
|
|||
tempDiv.innerHTML = item.content; |
|||
var plainText = tempDiv.textContent; |
|||
item.content = plainText |
|||
|
|||
tempDiv.innerHTML = item.contentEn; |
|||
plainText = tempDiv.textContent; |
|||
item.contentEn = plainText |
|||
|
|||
}) |
|||
} |
|||
productDataList.value = res.list |
|||
}) |
|||
getArticleList({ |
|||
pageNo: 1, |
|||
pageSize: 3, |
|||
categoryId: 31 |
|||
}).then((res: any) => { |
|||
if (process.client) { |
|||
res.list.forEach(item => { |
|||
// 创建一个临时的div元素 |
|||
var tempDiv = document.createElement('div'); |
|||
|
|||
tempDiv.innerHTML = item.content; |
|||
var plainText = tempDiv.textContent; |
|||
item.content = plainText |
|||
|
|||
tempDiv.innerHTML = item.contentEn; |
|||
plainText = tempDiv.textContent; |
|||
item.contentEn = plainText |
|||
|
|||
}) |
|||
} |
|||
|
|||
serviceDataList.value = res.list |
|||
}) |
|||
// 获取关于我们 |
|||
const aboutArticle = ref<any>({}) |
|||
getArticle({ |
|||
id: 36 |
|||
}).then((res: any) => { |
|||
if (res) { |
|||
aboutArticle.value = res |
|||
} |
|||
}) |
|||
</script> |
|||
<style scoped> |
|||
.btn-detail { |
|||
width: 60px; |
|||
height: 24px; |
|||
line-height: 24px; |
|||
border-radius: 4px; |
|||
background: linear-gradient(180deg, rgba(229, 203, 152, 1) 0%, rgba(250, 235, 201, 1) 100%); |
|||
color: rgba(137, 107, 52, 1); |
|||
font-size: 12px; |
|||
text-align: center; |
|||
} |
|||
|
|||
.product { |
|||
border-bottom: 1px solid rgba(137, 107, 52, 0.08); |
|||
} |
|||
|
|||
.product-title { |
|||
font-size: 20px; |
|||
color: #333333; |
|||
width: 420px; |
|||
} |
|||
|
|||
.product-content { |
|||
font-size: 16px; |
|||
color: #6C6C6C; |
|||
height: 40px; |
|||
line-height: 20px; |
|||
margin: 10px 0; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
width: 420px; |
|||
|
|||
} |
|||
|
|||
.product-desc { |
|||
font-size: 12px; |
|||
color: #999999; |
|||
width: 420px; |
|||
|
|||
} |
|||
|
|||
.product-img { |
|||
width: 200px; |
|||
height: 120px; |
|||
object-fit: cover; |
|||
} |
|||
|
|||
.product-more { |
|||
color: rgba(229, 203, 152, 1); |
|||
font-size: 14px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
} |
|||
|
|||
.tabs { |
|||
|
|||
} |
|||
|
|||
.tab { |
|||
width: 130px; |
|||
height: 40px; |
|||
font-size: 18px; |
|||
text-align: center; |
|||
line-height: 40px; |
|||
cursor: pointer; |
|||
|
|||
} |
|||
|
|||
.tab.active { |
|||
background: linear-gradient(180deg, rgba(51, 51, 51, 1) 0%, rgba(51, 51, 51, 0.56) 100%); |
|||
color: rgba(229, 203, 152, 1); |
|||
} |
|||
|
|||
|
|||
.carousel { |
|||
height: 800px; |
|||
} |
|||
|
|||
.about { |
|||
width: 1340px; |
|||
margin: 0 auto; |
|||
padding: 70px 0; |
|||
z-index: 20; |
|||
position: sticky; |
|||
|
|||
} |
|||
|
|||
.about-box { |
|||
position: relative; |
|||
background-image: url("~/assets/image/zixun-bg.jpg"); |
|||
background-size: contain; |
|||
background-position: center; |
|||
//background-repeat: no-repeat; background-color: #FFFFFF; |
|||
} |
|||
|
|||
#particles { |
|||
position: absolute; |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
|
|||
.about-header { |
|||
} |
|||
|
|||
.about-title { |
|||
font-size: 40px; |
|||
position: relative; |
|||
padding-left: 18px; |
|||
color: #101010; |
|||
} |
|||
|
|||
.about-title-left { |
|||
width: 6px; |
|||
height: 40px; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
bottom: 0; |
|||
margin: auto; |
|||
} |
|||
|
|||
.about-more { |
|||
width: 130px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
text-align: center; |
|||
color: #E5CB98; |
|||
background: linear-gradient(180deg, rgba(54, 54, 54, 1) 0%, rgba(132, 132, 132, 1) 99%); |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.about-body { |
|||
margin-top: 35px; |
|||
} |
|||
|
|||
.about-body-left { |
|||
width: 730px; |
|||
font-size: 18px; |
|||
line-height: 40px; |
|||
} |
|||
|
|||
.about-body-right { |
|||
height: auto; |
|||
position: relative; |
|||
width: 497px; |
|||
margin-right: 16px; |
|||
transition: all 0.6s; |
|||
} |
|||
|
|||
.about-body-right:hover { |
|||
transform: scale(1.2); |
|||
} |
|||
|
|||
.about-body-right::after { |
|||
content: ''; |
|||
position: absolute; |
|||
width: 100%; |
|||
height: 100%; |
|||
display: block; |
|||
background-color: rgba(51, 51, 51, 0.28); |
|||
top: 16px; |
|||
right: -16px; |
|||
z-index: -1; |
|||
} |
|||
|
|||
|
|||
.news { |
|||
width: 100%; |
|||
height: 610px; |
|||
background-image: url("~/assets/bg-zuixinzixun.png"); |
|||
margin: 0 auto; |
|||
background-repeat: no-repeat; |
|||
background-size: 100% 100%; |
|||
} |
|||
|
|||
.news-header { |
|||
height: 58px; |
|||
position: relative; |
|||
} |
|||
|
|||
.news-header-title { |
|||
color: #E5CB98; |
|||
font-size: 40px; |
|||
text-align: center; |
|||
line-height: 58px; |
|||
} |
|||
|
|||
.news-more { |
|||
width: 130px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
text-align: center; |
|||
color: #E5CB98; |
|||
background: linear-gradient(180deg, rgba(229, 203, 152, 1) 0%, rgba(250, 235, 201, 1) 99%); |
|||
color: rgba(137, 107, 52, 1); |
|||
border-radius: 4px; |
|||
cursor: pointer; |
|||
position: absolute; |
|||
right: 50px; |
|||
top: 0; |
|||
bottom: 0; |
|||
margin: auto; |
|||
} |
|||
|
|||
.news-carousel-box { |
|||
width: 1400px; |
|||
|
|||
margin: 140px auto 0; |
|||
height: 300px; |
|||
} |
|||
|
|||
.news-carousel-item { |
|||
display: block; |
|||
} |
|||
|
|||
.news-item { |
|||
width: 430px; |
|||
height: 243px; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
position: relative; |
|||
display: block; |
|||
|
|||
} |
|||
|
|||
.news-item-img { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
} |
|||
|
|||
.news-item-title { |
|||
background-color: #ffffff; |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
height: 45px; |
|||
line-height: 45px; |
|||
font-size: 16px; |
|||
padding: 0 16px; |
|||
display: block; |
|||
} |
|||
|
|||
|
|||
.africen { |
|||
width: 320px; |
|||
margin: 0 20px 30px; |
|||
} |
|||
|
|||
.africen-img-box { |
|||
width: 320px; |
|||
height: 175px; |
|||
position: relative; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.africen-img { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
z-index: 1; |
|||
} |
|||
|
|||
.africen-img-cover { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
z-index: 2; |
|||
} |
|||
|
|||
.africen-video-desc { |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 25px; |
|||
line-height: 20px; |
|||
background-image: linear-gradient(to top, rgba(0, 0, 0, .5), transparent); |
|||
color: #FFFFFF; |
|||
z-index: 10; |
|||
|
|||
} |
|||
|
|||
|
|||
.africen-time { |
|||
color: #9A9A9A; |
|||
} |
|||
|
|||
.africen-more { |
|||
width: 250px; |
|||
height: 50px; |
|||
line-height: 50px; |
|||
border-radius: 4px; |
|||
background: linear-gradient(180deg, rgba(51, 51, 51, 1) 0%, rgba(51, 51, 51, 0.56) 99%); |
|||
color: rgba(229, 203, 152, 1); |
|||
font-size: 16px; |
|||
text-align: center; |
|||
margin: 30px auto; |
|||
} |
|||
|
|||
.tab-pane { |
|||
min-height: 100px; |
|||
} |
|||
|
|||
.service-product { |
|||
background-image: url("~/assets/image/service-bg.png"); |
|||
background-size: contain; |
|||
} |
|||
|
|||
/* loading.css */ |
|||
.loading { |
|||
display: inline-block; |
|||
width: 100px; |
|||
height: 100px; |
|||
position: relative; |
|||
border: 4px solid #896B34; |
|||
animation: loader 4s infinite ease; |
|||
} |
|||
|
|||
.loading-inner { |
|||
vertical-align: top; |
|||
display: inline-block; |
|||
width: 100%; |
|||
background-color: #896B34; |
|||
animation: loader-inner 4s infinite ease-in; |
|||
} |
|||
|
|||
@keyframes loader { |
|||
0% { |
|||
transform: rotate(0deg); |
|||
} |
|||
25% { |
|||
transform: rotate(180deg); |
|||
} |
|||
50% { |
|||
transform: rotate(180deg); |
|||
} |
|||
75% { |
|||
transform: rotate(360deg); |
|||
} |
|||
100% { |
|||
transform: rotate(360deg); |
|||
} |
|||
} |
|||
|
|||
@keyframes loader-inner { |
|||
0% { |
|||
height: 0%; |
|||
} |
|||
25% { |
|||
height: 0%; |
|||
} |
|||
50% { |
|||
height: 100%; |
|||
} |
|||
75% { |
|||
height: 100%; |
|||
} |
|||
100% { |
|||
height: 0%; |
|||
} |
|||
} |
|||
|
|||
</style> |
@ -0,0 +1,68 @@ |
|||
|
|||
|
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/news')">{{ $t('news') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<p>{{ locale == 'zh' ? articleData.title : articleData.titleEn}}</p> |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
<div class="w-1200 py-8"> |
|||
<p class="title">{{ locale == 'zh' ? articleData.title : articleData.titleEn}}</p> |
|||
<NSpace class="article-footer"> |
|||
<span class="">{{dayjs(articleData.createTime).format('YYYY-MM-DD')}}</span> |
|||
<span class="">{{$t('source')}}:{{locale== 'zh'? articleData.source: articleData.sourceEn}}</span> |
|||
<span class="flex items-center"><NIcon :component="EyeOutline" size="20px"></NIcon>{{articleData.viewsCount}} {{$t('viewsCount')}}</span> |
|||
</NSpace> |
|||
<div v-html="locale == 'zh'?articleData.content: articleData.contentEn"></div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem, NIcon, NSpace} from "naive-ui"; |
|||
import {getArticle} from "~/api/article"; |
|||
import {EyeOutline} from "@vicons/ionicons5"; |
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
|
|||
|
|||
const router = useRoute() |
|||
const articleData = ref<any>({ |
|||
title: '', |
|||
titleEn: '', |
|||
content: '', |
|||
contentEn: '', |
|||
viewsCount: 0, |
|||
source: '', |
|||
sourceEn: '' |
|||
}) |
|||
|
|||
getArticle({ |
|||
id: router.params.id |
|||
}).then( (res: any) => { |
|||
articleData.value = res |
|||
}) |
|||
</script> |
|||
<style scoped> |
|||
.title{ |
|||
color: rgba(16, 16, 16, 1); |
|||
font-size: 36px; |
|||
font-weight: bold; |
|||
margin-bottom: 20px; |
|||
} |
|||
.article-footer{ |
|||
color: #9A9A9A; |
|||
font-size: 14px; |
|||
margin-bottom: 40px; |
|||
} |
|||
</style> |
@ -0,0 +1,102 @@ |
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
{{ $t('news') }} |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
|
|||
<!-- 文章列表--> |
|||
<div class="w-1440"> |
|||
<div class="w-1200"> |
|||
<NuxtLink v-for="(item, index) in articleDataList" :to="localePath('/news-detail/' + item.id)" class="article flex justify-between"> |
|||
<div class="flex flex-col justify-between"> |
|||
<p class="article-title line-clamp-2">{{ locale== 'zh'?item.title:item.titleEn}}</p> |
|||
<NSpace class="article-footer"> |
|||
<span class="">{{locale== 'zh'? item.source: item.sourceEn}}</span> |
|||
<span class="">{{item.viewsCount}} {{$t('viewsCount')}}</span> |
|||
<span class="">{{dayjs(item.createTime).format('YYYY-MM-DD')}}</span> |
|||
</NSpace> |
|||
</div> |
|||
<img :src="item.picUrl" class="article-img" /> |
|||
</NuxtLink> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- 分页--> |
|||
<div class="flex justify-center py-8"> |
|||
<NPagination |
|||
:itemCount="itemCount" |
|||
:page-size="10" |
|||
@update-page="queryList" |
|||
/> |
|||
</div> |
|||
|
|||
|
|||
|
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem, NSpace, NPagination, NThing} from 'naive-ui' |
|||
import {getArticleList} from "~/api/article"; |
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
useHead({ |
|||
title: `金梦网-最新资讯` |
|||
}) |
|||
const pageParams = { |
|||
pageNo: 1, |
|||
pageSize: 10, |
|||
categoryId: 28 |
|||
} |
|||
const itemCount = ref(0) |
|||
const articleDataList = ref<any[]>([]) |
|||
const queryList = (pageNo: number) => { |
|||
pageParams.pageNo = pageNo |
|||
getArticleList(pageParams).then((res: any)=> { |
|||
articleDataList.value = res.list |
|||
itemCount.value = res.total |
|||
}) |
|||
} |
|||
queryList(1) |
|||
|
|||
</script> |
|||
|
|||
<style scoped> |
|||
.data-list { |
|||
|
|||
} |
|||
.article{ |
|||
border-bottom: 1px solid rgba(137, 107, 52, 0.15); |
|||
padding: 38px 0 28px; |
|||
} |
|||
.article-img { |
|||
width: 260px; |
|||
height: 165px; |
|||
border-radius: 8px; |
|||
} |
|||
.article-title{ |
|||
width: 859px; |
|||
height: 92px; |
|||
line-height: 45px; |
|||
color: rgba(51, 51, 51, 1); |
|||
font-size: 20px; |
|||
text-align: left; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
} |
|||
.article-footer { |
|||
font-size: 14px; |
|||
color: #9A9A9A; |
|||
} |
|||
.nav { |
|||
border-bottom: 1px solid rgba(137, 107, 52, 0.15); |
|||
} |
|||
</style> |
@ -0,0 +1,68 @@ |
|||
|
|||
|
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/product')">{{ $t('product') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<p>{{ locale == 'zh' ? articleData.title : articleData.titleEn}}</p> |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
<div class="w-1200 py-8"> |
|||
<p class="title">{{ locale == 'zh' ? articleData.title : articleData.titleEn}}</p> |
|||
<NSpace class="article-footer"> |
|||
<span class="">{{dayjs(articleData.createTime).format('YYYY-MM-DD')}}</span> |
|||
<span class="">{{$t('source')}}:{{locale== 'zh'? articleData.source: articleData.sourceEn}}</span> |
|||
<span class="flex items-center"><NIcon :component="EyeOutline" size="20px"></NIcon>{{articleData.viewsCount}} {{$t('viewsCount')}}</span> |
|||
</NSpace> |
|||
<div v-html="locale == 'zh'?articleData.content: articleData.contentEn"></div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem, NIcon, NSpace} from "naive-ui"; |
|||
import {getArticle} from "~/api/article"; |
|||
import {EyeOutline} from "@vicons/ionicons5"; |
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
|
|||
|
|||
const router = useRoute() |
|||
const articleData = ref<any>({ |
|||
title: '', |
|||
titleEn: '', |
|||
content: '', |
|||
contentEn: '', |
|||
viewsCount: 0, |
|||
source: '', |
|||
sourceEn: '' |
|||
}) |
|||
|
|||
getArticle({ |
|||
id: router.params.id |
|||
}).then( (res: any) => { |
|||
articleData.value = res |
|||
}) |
|||
</script> |
|||
<style scoped> |
|||
.title{ |
|||
color: rgba(16, 16, 16, 1); |
|||
font-size: 36px; |
|||
font-weight: bold; |
|||
margin-bottom: 20px; |
|||
} |
|||
.article-footer{ |
|||
color: #9A9A9A; |
|||
font-size: 14px; |
|||
margin-bottom: 40px; |
|||
} |
|||
</style> |
@ -0,0 +1,140 @@ |
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
{{ $t('product') }} |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
|
|||
<!-- 文章列表--> |
|||
<div class="w-1440"> |
|||
<div class="w-1200"> |
|||
<NuxtLink v-for="item in articleDataList" :to="localePath('/product-detail/' + item.id)" class="product flex justify-between py-8"> |
|||
<div class="flex"> |
|||
<img class="product-img" :src="item.picUrl"/> |
|||
<div class="ml-8"> |
|||
<p class="product-title">{{locale == 'zh'?item.title: item.titleEn}}</p> |
|||
<p class="product-content">{{locale == 'zh'?item.content: item.contentEn}}</p> |
|||
<p class="product-desc"><span style="color: #906D2C;">{{item.viewsCount}}</span> {{$t('viewsCount')}} <span class="pl-4">{{dayjs(item.createTime).format('YYYY-MM-DD')}}</span></p> |
|||
</div> |
|||
</div> |
|||
<p class="btn-detail">{{$t('detail')}}</p> |
|||
</NuxtLink> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- 分页--> |
|||
<div class="flex justify-center py-8"> |
|||
<NPagination |
|||
:item-count="itemCount" |
|||
@update-page="queryList" |
|||
/> |
|||
</div> |
|||
|
|||
|
|||
|
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem, NSpace, NPagination, NThing} from 'naive-ui' |
|||
import {getArticleList} from "~/api/article"; |
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
useHead({ |
|||
title: `金梦网-产品` |
|||
}) |
|||
const pageParams = { |
|||
pageNo: 1, |
|||
pageSize: 10, |
|||
categoryId: 30 |
|||
} |
|||
const itemCount = ref(0) |
|||
const articleDataList = ref<any[]>([]) |
|||
const queryList = (pageNo: number) => { |
|||
pageParams.pageNo = pageNo |
|||
getArticleList(pageParams).then((res: any)=> { |
|||
if(process.client) { |
|||
res.list.forEach(item => { |
|||
// 创建一个临时的div元素 |
|||
var tempDiv = document.createElement('div'); |
|||
|
|||
tempDiv.innerHTML = item.content; |
|||
var plainText = tempDiv.textContent; |
|||
item.content = plainText |
|||
|
|||
tempDiv.innerHTML = item.contentEn; |
|||
plainText = tempDiv.textContent; |
|||
item.contentEn = plainText |
|||
|
|||
}) |
|||
} |
|||
articleDataList.value = res.list |
|||
itemCount.value = res.total |
|||
}) |
|||
} |
|||
queryList(1) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.data-list { |
|||
|
|||
} |
|||
|
|||
.btn-detail { |
|||
width: 60px; |
|||
height: 24px; |
|||
line-height: 24px; |
|||
border-radius: 4px; |
|||
background: linear-gradient(180deg, rgba(229, 203, 152, 1) 0%, rgba(250, 235, 201, 1) 100%); |
|||
color: rgba(137, 107, 52, 1); |
|||
font-size: 12px; |
|||
text-align: center; |
|||
} |
|||
|
|||
.product-title { |
|||
font-size: 20px; |
|||
color: #333333; |
|||
width: 420px; |
|||
} |
|||
|
|||
.product-content { |
|||
font-size: 16px; |
|||
color: #6C6C6C; |
|||
height: 40px; |
|||
line-height: 20px; |
|||
margin: 10px 0; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
width: 420px; |
|||
|
|||
} |
|||
|
|||
.product-desc { |
|||
font-size: 12px; |
|||
color: #999999; |
|||
width: 420px; |
|||
|
|||
} |
|||
|
|||
.product-img { |
|||
width: 200px; |
|||
height: 120px; |
|||
object-fit: cover; |
|||
} |
|||
|
|||
.product-more { |
|||
color: rgba(229, 203, 152, 1); |
|||
font-size: 14px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
} |
|||
.nav { |
|||
border-bottom: 1px solid rgba(137, 107, 52, 0.15); |
|||
} |
|||
</style> |
@ -0,0 +1,225 @@ |
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
{{ $t('searchResult') }} |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
|
|||
<!-- 文章列表--> |
|||
<div class="w-1440"> |
|||
<div class="w-1200"> |
|||
<n-divider title-placement="left"> |
|||
{{ $t('article') }} |
|||
</n-divider> |
|||
<NuxtLink v-for="(item, index) in articleDataList" :to="localePath('/news-detail/' + item.id)" |
|||
class="article flex justify-between"> |
|||
<div class="flex flex-col justify-between"> |
|||
<p class="article-title line-clamp-2">{{ locale == 'zh' ? item.title : item.titleEn }}</p> |
|||
<NSpace class="article-footer"> |
|||
<span class="">{{ locale == 'zh' ? item.source : item.sourceEn }}</span> |
|||
<span class="">{{ item.viewsCount }} {{ $t('viewsCount') }}</span> |
|||
<span class="">{{ dayjs(item.createTime).format('YYYY-MM-DD') }}</span> |
|||
</NSpace> |
|||
</div> |
|||
<img :src="item.picUrl" class="article-img"/> |
|||
</NuxtLink> |
|||
<!-- 分页--> |
|||
<div v-show="articleDataList.length >0" class="flex justify-center py-8"> |
|||
<NPagination |
|||
:itemCount="articleCount" |
|||
:page-size="10" |
|||
@change="queryArticleList" |
|||
/> |
|||
</div> |
|||
<NEmpty :description="$t('noArticle')" v-if="articleDataList.length == 0"></NEmpty> |
|||
</div> |
|||
|
|||
<div class="w-1200"> |
|||
<n-divider title-placement="left"> |
|||
{{ $t('video') }} |
|||
</n-divider> |
|||
<NuxtLink v-for="(item, index) in videoDataList" :to="localePath('/video-detail/' + item.id)" |
|||
class="africen inline-block cursor-pointer "> |
|||
<div class="africen-img-box" @mouseleave="item.play = false" @mouseover="item.play = true"> |
|||
<video v-if="item.play" autoplay muted class="africen-img-cover" :src="item.videoUrl"/> |
|||
<video v-if="!item.picUrl" v-show="!item.play" muted class="africen-img" :src="item.videoUrl"/> |
|||
<img v-if="item.picUrl" v-show="!item.play" muted class="africen-img" :src="item.picUrl"/> |
|||
<div class="africen-video-desc"> |
|||
<div class="view-num pl-2"> |
|||
<p class="flex items-center"> |
|||
<NIcon :component="VideocamOutline" size="25"></NIcon> |
|||
<span class="ml-1">{{ item.viewsCount }}</span></p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<p class="africen-title py-2">{{ locale == 'zh' ? item.title : item.titleEn }}</p> |
|||
<div class="africen-desc"> |
|||
<div class="africen-time">{{ dayjs(item.createTime).format('YYYY-MM-DD') }}</div> |
|||
</div> |
|||
</NuxtLink> |
|||
<!-- 分页--> |
|||
<div v-show="videoDataList.length >0" class="flex justify-center py-8"> |
|||
<NPagination |
|||
:itemCount="videoCount" |
|||
:page-size="10" |
|||
@change="queryVideoList" |
|||
/> |
|||
</div> |
|||
<NEmpty :description="$t('noVideo')" v-if="videoDataList.length == 0"></NEmpty> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem, NSpace, NPagination, NDivider, NIcon, NEmpty} from 'naive-ui' |
|||
import {getArticleList} from "~/api/article"; |
|||
import {getVideoList} from "~/api/video"; |
|||
import {VideocamOutline} from "@vicons/ionicons5"; |
|||
|
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
const router = useRoute() |
|||
useHead({ |
|||
title: `金梦网-搜索` |
|||
}) |
|||
const articlePageParams = { |
|||
pageNo: 1, |
|||
pageSize: 10, |
|||
keyWord: '' |
|||
} |
|||
const videoPageParams = { |
|||
pageNo: 1, |
|||
pageSize: 10, |
|||
keyWord: '' |
|||
} |
|||
articlePageParams.keyWord = router.query.word || '' |
|||
videoPageParams.keyWord = router.query.word || '' |
|||
watch(() => router.query, (newVal, oldValue) => { |
|||
articlePageParams.keyWord = newVal.word ? newVal.word.toString() : '' |
|||
videoPageParams.keyWord = newVal.word ? newVal.word.toString() : '' |
|||
queryArticleList(1) |
|||
queryVideoList(1) |
|||
}) |
|||
|
|||
|
|||
const articleCount = ref(0) |
|||
const videoCount = ref(0) |
|||
const articleDataList = ref<any[]>([]) |
|||
const videoDataList = ref<any[]>([]) |
|||
const queryArticleList = (pageNo: number) => { |
|||
articlePageParams.pageNo = pageNo |
|||
getArticleList(articlePageParams).then((res: any) => { |
|||
articleDataList.value = res.list |
|||
articleCount.value = res.total |
|||
}) |
|||
} |
|||
|
|||
queryArticleList(1) |
|||
|
|||
const queryVideoList = (pageNo: number) => { |
|||
videoPageParams.pageNo = pageNo |
|||
getVideoList(videoPageParams).then((res: any) => { |
|||
videoDataList.value = res.list |
|||
videoCount.value = res.total |
|||
}) |
|||
} |
|||
|
|||
queryVideoList(1) |
|||
|
|||
</script> |
|||
|
|||
<style scoped> |
|||
.data-list { |
|||
|
|||
} |
|||
|
|||
.article { |
|||
border-bottom: 1px solid rgba(137, 107, 52, 0.15); |
|||
padding: 38px 0 28px; |
|||
} |
|||
|
|||
.article-img { |
|||
width: 260px; |
|||
height: 165px; |
|||
border-radius: 8px; |
|||
} |
|||
|
|||
.article-title { |
|||
width: 859px; |
|||
height: 92px; |
|||
line-height: 45px; |
|||
color: rgba(51, 51, 51, 1); |
|||
font-size: 20px; |
|||
text-align: left; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
} |
|||
|
|||
.article-footer { |
|||
font-size: 14px; |
|||
color: #9A9A9A; |
|||
} |
|||
|
|||
.nav { |
|||
border-bottom: 1px solid rgba(137, 107, 52, 0.15); |
|||
} |
|||
|
|||
|
|||
.africen { |
|||
width: 280px; |
|||
margin: 0 10px 30px; |
|||
} |
|||
|
|||
.africen-title { |
|||
height: 50px; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
line-height: 20px; |
|||
} |
|||
|
|||
.africen-img-box { |
|||
width: 100%; |
|||
height: 175px; |
|||
position: relative; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.africen-img { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
z-index: 1; |
|||
} |
|||
|
|||
.africen-img-cover { |
|||
width: 100%; |
|||
height: 100%; |
|||
object-fit: cover; |
|||
z-index: 2; |
|||
} |
|||
|
|||
.africen-video-desc { |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 25px; |
|||
line-height: 20px; |
|||
background-image: linear-gradient(to top, rgba(0, 0, 0, .5), transparent); |
|||
color: #FFFFFF; |
|||
z-index: 10; |
|||
|
|||
} |
|||
</style> |
@ -0,0 +1,68 @@ |
|||
|
|||
|
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/service')">{{ $t('service') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<p>{{ locale == 'zh' ? articleData.title : articleData.titleEn}}</p> |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
<div class="w-1200 py-8"> |
|||
<p class="title">{{ locale == 'zh' ? articleData.title : articleData.titleEn}}</p> |
|||
<NSpace class="article-footer"> |
|||
<span class="">{{dayjs(articleData.createTime).format('YYYY-MM-DD')}}</span> |
|||
<span class="">{{$t('source')}}:{{locale== 'zh'? articleData.source: articleData.sourceEn}}</span> |
|||
<span class="flex items-center"><NIcon :component="EyeOutline" size="20px"></NIcon>{{articleData.viewsCount}} {{$t('viewsCount')}}</span> |
|||
</NSpace> |
|||
<div v-html="locale == 'zh'?articleData.content: articleData.contentEn"></div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem, NIcon, NSpace} from "naive-ui"; |
|||
import {getArticle} from "~/api/article"; |
|||
import {EyeOutline} from "@vicons/ionicons5"; |
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
|
|||
|
|||
const router = useRoute() |
|||
const articleData = ref<any>({ |
|||
title: '', |
|||
titleEn: '', |
|||
content: '', |
|||
contentEn: '', |
|||
viewsCount: 0, |
|||
source: '', |
|||
sourceEn: '' |
|||
}) |
|||
|
|||
getArticle({ |
|||
id: router.params.id |
|||
}).then( (res: any) => { |
|||
articleData.value = res |
|||
}) |
|||
</script> |
|||
<style scoped> |
|||
.title{ |
|||
color: rgba(16, 16, 16, 1); |
|||
font-size: 36px; |
|||
font-weight: bold; |
|||
margin-bottom: 20px; |
|||
} |
|||
.article-footer{ |
|||
color: #9A9A9A; |
|||
font-size: 14px; |
|||
margin-bottom: 40px; |
|||
} |
|||
</style> |
@ -0,0 +1,140 @@ |
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
{{ $t('service') }} |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
|
|||
<!-- 文章列表--> |
|||
<div class="w-1440"> |
|||
<div class="w-1200"> |
|||
<NuxtLink v-for="item in articleDataList" :to="localePath('/service-detail/' + item.id)" class="product flex justify-between py-8"> |
|||
<div class="flex"> |
|||
<img class="product-img" :src="item.picUrl"/> |
|||
<div class="ml-8"> |
|||
<p class="product-title">{{locale == 'zh'?item.title: item.titleEn}}</p> |
|||
<p class="product-content">{{locale == 'zh'?item.content: item.contentEn}}</p> |
|||
<p class="product-desc"><span style="color: #906D2C;">{{item.viewsCount}}</span> {{$t('viewsCount')}} <span class="pl-4">{{dayjs(item.createTime).format('YYYY-MM-DD')}}</span></p> |
|||
</div> |
|||
</div> |
|||
<p class="btn-detail">{{$t('detail')}}</p> |
|||
</NuxtLink> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- 分页--> |
|||
<div class="flex justify-center py-8"> |
|||
<NPagination |
|||
:item-count="itemCount" |
|||
@update-page="queryList" |
|||
/> |
|||
</div> |
|||
|
|||
|
|||
|
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem, NSpace, NPagination, NThing} from 'naive-ui' |
|||
import {getArticleList} from "~/api/article"; |
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
useHead({ |
|||
title: `金梦网-服务` |
|||
}) |
|||
const pageParams = { |
|||
pageNo: 1, |
|||
pageSize: 10, |
|||
categoryId: 31 |
|||
} |
|||
const itemCount = ref(0) |
|||
const articleDataList = ref<any[]>([]) |
|||
const queryList = (pageNo: number) => { |
|||
pageParams.pageNo = pageNo |
|||
getArticleList(pageParams).then((res: any)=> { |
|||
if(process.client) { |
|||
res.list.forEach(item => { |
|||
// 创建一个临时的div元素 |
|||
var tempDiv = document.createElement('div'); |
|||
|
|||
tempDiv.innerHTML = item.content; |
|||
var plainText = tempDiv.textContent; |
|||
item.content = plainText |
|||
|
|||
tempDiv.innerHTML = item.contentEn; |
|||
plainText = tempDiv.textContent; |
|||
item.contentEn = plainText |
|||
|
|||
}) |
|||
} |
|||
articleDataList.value = res.list |
|||
itemCount.value = res.total |
|||
}) |
|||
} |
|||
queryList(1) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.data-list { |
|||
|
|||
} |
|||
|
|||
.btn-detail { |
|||
width: 60px; |
|||
height: 24px; |
|||
line-height: 24px; |
|||
border-radius: 4px; |
|||
background: linear-gradient(180deg, rgba(229, 203, 152, 1) 0%, rgba(250, 235, 201, 1) 100%); |
|||
color: rgba(137, 107, 52, 1); |
|||
font-size: 12px; |
|||
text-align: center; |
|||
} |
|||
|
|||
.product-title { |
|||
font-size: 20px; |
|||
color: #333333; |
|||
width: 420px; |
|||
} |
|||
|
|||
.product-content { |
|||
font-size: 16px; |
|||
color: #6C6C6C; |
|||
height: 40px; |
|||
line-height: 20px; |
|||
margin: 10px 0; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
width: 420px; |
|||
|
|||
} |
|||
|
|||
.product-desc { |
|||
font-size: 12px; |
|||
color: #999999; |
|||
width: 420px; |
|||
|
|||
} |
|||
|
|||
.product-img { |
|||
width: 200px; |
|||
height: 120px; |
|||
object-fit: cover; |
|||
} |
|||
|
|||
.product-more { |
|||
color: rgba(229, 203, 152, 1); |
|||
font-size: 14px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
} |
|||
.nav { |
|||
border-bottom: 1px solid rgba(137, 107, 52, 0.15); |
|||
} |
|||
</style> |
@ -0,0 +1,70 @@ |
|||
|
|||
|
|||
<template> |
|||
<div> |
|||
<div class="header-height"></div> |
|||
<div class="w-1200 py-8 nav"> |
|||
<NBreadcrumb> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/')">{{ $t('homePage') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<NuxtLink :to="localePath('/news')">{{ $t('africanVideo') }}</NuxtLink> |
|||
</NBreadcrumbItem> |
|||
<NBreadcrumbItem> |
|||
<p>{{ locale == 'zh' ? articleData.title : articleData.titleEn}}</p> |
|||
</NBreadcrumbItem> |
|||
</NBreadcrumb> |
|||
</div> |
|||
<div class="w-1200 py-8"> |
|||
<p class="title">{{ locale == 'zh' ? articleData.title : articleData.titleEn}}</p> |
|||
<NSpace class="article-footer"> |
|||
<span class="">{{dayjs(articleData.createTime).format('YYYY-MM-DD')}}</span> |
|||
<!-- <span class="">{{$t('source')}}:{{locale== 'zh'? articleData.source: articleData.sourceEn}}</span>--> |
|||
|
|||
<span class="flex items-center"><NIcon :component="EyeOutline" size="20px"></NIcon> {{articleData.viewsCount}} {{$t('viewsCount')}}</span> |
|||
</NSpace> |
|||
<video class="video" controls :src="articleData.videoUrl"> |
|||
|
|||
</video> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import {NBreadcrumb, NBreadcrumbItem, NSpace,NIcon} from "naive-ui"; |
|||
import {getVideo} from "~/api/video"; |
|||
const dayjs = useDayjs() |
|||
const {locale} = useI18n() |
|||
const localePath = useLocalePath() |
|||
|
|||
import {EyeOutline} from '@vicons/ionicons5' |
|||
const router = useRoute() |
|||
const articleData = ref<any>({ |
|||
title: '', |
|||
titleEn: '', |
|||
content: '', |
|||
contentEn: '', |
|||
viewsCount: 0, |
|||
source: '', |
|||
sourceEn: '' |
|||
}) |
|||
|
|||
getVideo({ |
|||
id: router.params.id |
|||
}).then( (res: any) => { |
|||
articleData.value = res |
|||
}) |
|||
</script> |
|||
<style scoped> |
|||
.title{ |
|||
color: rgba(16, 16, 16, 1); |
|||
font-size: 36px; |
|||
font-weight: bold; |
|||
margin-bottom: 20px; |
|||
} |
|||
.article-footer{ |
|||
color: #9A9A9A; |
|||
font-size: 14px; |
|||
margin-bottom: 40px; |
|||
} |
|||
</style> |
@ -0,0 +1,6 @@ |
|||
import { defineNuxtPlugin } from '#app' |
|||
import particles from 'vue3-particles' |
|||
export default defineNuxtPlugin((nuxtApp) => { |
|||
nuxtApp.vueApp.use(particles); |
|||
|
|||
}) |
@ -0,0 +1,35 @@ |
|||
import { setup } from '@css-render/vue3-ssr' |
|||
import { defineNuxtPlugin } from '#app' |
|||
|
|||
|
|||
export default defineNuxtPlugin((nuxtApp) => { |
|||
|
|||
if (process.server) { |
|||
const { collect } = setup(nuxtApp.vueApp) |
|||
const originalRenderMeta = nuxtApp.ssrContext?.renderMeta |
|||
// @ts-ignore
|
|||
nuxtApp.ssrContext = nuxtApp.ssrContext || {} |
|||
// @ts-ignore
|
|||
nuxtApp.ssrContext.renderMeta = () => { |
|||
if (!originalRenderMeta) { |
|||
return { |
|||
headTags: collect() |
|||
} |
|||
} |
|||
const originalMeta = originalRenderMeta() |
|||
if ('then' in originalMeta) { |
|||
return originalMeta.then((resolvedOriginalMeta) => { |
|||
return { |
|||
...resolvedOriginalMeta, |
|||
headTags: resolvedOriginalMeta['headTags'] + collect() |
|||
} |
|||
}) |
|||
} else { |
|||
return { |
|||
...originalMeta, |
|||
headTags: originalMeta['headTags'] + collect() |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}) |
@ -0,0 +1,18 @@ |
|||
import { defineNuxtPlugin } from '#app' |
|||
// @ts-ignore
|
|||
import WOW from 'wow.js' |
|||
|
|||
|
|||
|
|||
export default defineNuxtPlugin((nuxtApp) => { |
|||
|
|||
new WOW({ //可以添加自定义内容
|
|||
animateClass: 'animate__animated', |
|||
boxClass: 'wow', |
|||
offset: 0, |
|||
mobile: true, |
|||
live: false, |
|||
scrollContainer: null, |
|||
resetAnimation: true, |
|||
}).init() |
|||
}) |
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,3 @@ |
|||
{ |
|||
"extends": "../.nuxt/tsconfig.server.json" |
|||
} |
@ -0,0 +1,4 @@ |
|||
{ |
|||
// https://nuxt.com/docs/guide/concepts/typescript |
|||
"extends": "./.nuxt/tsconfig.json" |
|||
} |