@ -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" |
||||
|
} |