first commit

This commit is contained in:
李志强 2026-01-26 09:33:40 +08:00
commit 2589ef668d
106 changed files with 17738 additions and 0 deletions

7
.env.development Normal file
View File

@ -0,0 +1,7 @@
# 环境变量配置 (开发环境)
NODE_ENV = 'development'
# 应用配置
VITE_APP_TITLE = '美天科技 - 官网'
# VITE_APP_API_URL = 'http://localhost:8000' # 接口基础URL
VITE_APP_API_URL = 'http://backapi.yunzer.cn'

6
.env.production Normal file
View File

@ -0,0 +1,6 @@
# 环境变量配置 (生产环境)
NODE_ENV = 'production'
# 应用配置
VITE_APP_TITLE = '美天科技 - 官网'
VITE_APP_API_URL = 'https://api.your-production-domain.com' # 生产环境接口基础URL

4
.env.test Normal file
View File

@ -0,0 +1,4 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'test'
VITE_APP_TITLE = 'ling'
VITE_APP_BASE_API = '/test-api'

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
dist
node_modules

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

7
.prettierignore Normal file
View File

@ -0,0 +1,7 @@
/dist/*
/html/*
.local
/node_modules/**
**/*.svg
**/*.sh
/public/*

9
.prettierrc.json Normal file
View File

@ -0,0 +1,9 @@
{
"singleQuote": true,
"semi": false,
"bracketSpacing": true,
"htmlWhitespaceSensitivity": "ignore",
"endOfLine": "auto",
"trailingComma": "all",
"tabWidth": 2
}

4
.stylelintignore Normal file
View File

@ -0,0 +1,4 @@
/node_modules/*
/dist/*
/html/*
/public/*

53
.stylelintrc.cjs Normal file
View File

@ -0,0 +1,53 @@
// @see https://stylelint.bootcss.com/
module.exports = {
extends: [
'stylelint-config-standard', // 配置stylelint拓展插件
'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化
'stylelint-config-standard-scss', // 配置stylelint scss插件
'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化
'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件,
'stylelint-config-prettier', // 配置stylelint和prettier兼容
],
overrides: [
{
files: ['**/*.(scss|css|vue|html)'],
customSyntax: 'postcss-scss',
},
{
files: ['**/*.(html|vue)'],
customSyntax: 'postcss-html',
},
],
ignoreFiles: [
'**/*.js',
'**/*.jsx',
'**/*.tsx',
'**/*.ts',
'**/*.json',
'**/*.md',
'**/*.yaml',
],
/**
* null => 关闭该规则
* always => 必须
*/
rules: {
'value-keyword-case': null, // 在 css 中使用 v-bind不报错
'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器
'function-url-quotes': 'always', // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)"
'no-empty-source': null, // 关闭禁止空源码
'selector-class-pattern': null, // 关闭强制选择器类名的格式
'property-no-unknown': null, // 禁止未知的属性(true 为不允许)
'block-opening-brace-space-before': 'always', //大括号之前必须有一个空格或不能有空白符
'value-no-vendor-prefix': null, // 关闭 属性值前缀 --webkit-box
'property-no-vendor-prefix': null, // 关闭 属性前缀 -webkit-mask
'selector-pseudo-class-no-unknown': [
// 不允许未知的选择器
true,
{
ignorePseudoClasses: ['global', 'v-deep', 'deep'], // 忽略属性修改element默认样式的时候能使用到
},
],
},
}

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# METETEME WEBSITE
# 美天智能科技官网前端

12
eslint.config.ts Normal file
View File

@ -0,0 +1,12 @@
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import pluginVue from "eslint-plugin-vue";
import { defineConfig } from "eslint/config";
export default defineConfig([
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts,vue}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: globals.browser } },
tseslint.configs.recommended,
pluginVue.configs["flat/essential"],
{ files: ["**/*.vue"], languageOptions: { parserOptions: { parser: tseslint.parser } } },
]);

13
index.html Normal file
View File

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>guanwang</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

10300
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

57
package.json Normal file
View File

@ -0,0 +1,57 @@
{
"name": "guanwang",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --open",
"build": "vue-tsc -b && vite build",
"build:test": "vue-tsc && vite build --mode test",
"build:pro": "vue-tsc && vite build --mode production",
"preview": "vite preview",
"lint": "eslint src",
"fix": "eslint src --fix",
"lint:style": "stylelint src/**/*.{css,scss,vue} --cache --fix"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.2",
"@tailwindcss/vite": "^4.1.18",
"axios": "^1.13.2",
"echarts": "^6.0.0",
"element-plus": "^2.13.0",
"pinia": "^3.0.4",
"swiper": "^10.0.4",
"vue": "^3.5.24",
"vue-router": "^4.6.4"
},
"devDependencies": {
"@babel/eslint-parser": "^7.28.5",
"@eslint/js": "^9.39.2",
"@types/node": "^24.10.4",
"@types/swiper": "^5.4.3",
"@types/terser": "^3.8.1",
"@vitejs/plugin-vue": "^6.0.1",
"@vue/tsconfig": "^0.8.1",
"autoprefixer": "^10.4.23",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-vue": "^10.6.2",
"fast-glob": "^3.3.3",
"globals": "^17.0.0",
"jiti": "^2.6.1",
"less": "^4.5.1",
"postcss": "^8.5.6",
"prettier": "^3.7.4",
"sass-embedded": "^1.97.2",
"tailwindcss": "^4.1.18",
"terser": "^5.44.1",
"typescript": "~5.9.3",
"typescript-eslint": "^8.52.0",
"vite": "^7.2.4",
"vite-plugin-svg-icons": "^2.0.1",
"vue-tsc": "^3.1.4"
}
}

1
public/vite.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

18
src/App.vue Normal file
View File

@ -0,0 +1,18 @@
<script setup lang="ts">
</script>
<template>
<router-view />
</template>
<style>
/* 全局样式 */
html, body, #app {
margin: 0;
padding: 0;
width: 100%;
min-height: 100vh;
}
</style>

26
src/api/article.ts Normal file
View File

@ -0,0 +1,26 @@
import service from '@/utils/request'
// 获取新闻中心顶部4篇文章
export const getNewsCenterTop4 = async () => {
const response = await service.get('index/newscentertop4')
return response.data
}
//点赞增加
export const addLike = async (id: number | string) => {
const response = await service.post(`index/articleLikes/${id}`)
return response.data
}
// 点赞减少
export const reduceLike = async (id: number | string) => {
const response = await service.post(`index/articleUnlikes/${id}`)
return response.data
}
//阅读增加
export const addViews = async (id: number | string) => {
const response = await service.post(`index/views/${id}`)
return response.data
}

13
src/api/index.ts Normal file
View File

@ -0,0 +1,13 @@
import service from '@/utils/request'
// 获取前端导航
export const getHeadMenu = async () => {
const response = await service.get('index/headmenu')
return response.data
}
// 根据路径获取单页内容
export const getOnePageByPath = async (path: string) => {
const response = await service.get(`index/onepage/${encodeURIComponent(path)}`)
return response.data
}

47
src/api/newscenter.ts Normal file
View File

@ -0,0 +1,47 @@
import service from '@/utils/request'
// 获取企业新闻
export const getCompanyNews = async (page: number = 1, limit: number = 10) => {
const response = await service.get('index/companynews', {
params: { page, limit }
})
return response.data
}
// 获取金蝶新闻
export const getKingdeeNews = async (page: number = 1, limit: number = 10) => {
const response = await service.get('index/kingdeenews', {
params: { page, limit }
})
return response.data
}
// 获取技术中心
export const getTechnologyCenter = async (page: number = 1, limit: number = 10, categoryId?: number) => {
const params: any = { page, limit }
if (categoryId) {
params.category_id = categoryId
}
const response = await service.get('index/technologyCenter', {
params
})
return response.data
}
// 获取技术中心分类
export const getTechnologyCategories = async () => {
const response = await service.get('index/technologyCategories')
return response.data
}
// 获取金蝶新闻详情
export const getKingdeeNewsDetail = async (id: number | string) => {
const response = await service.get(`index/kingdeenews/detail/${id}`)
return response.data
}
// 获取企业新闻详情
export const getCompanyNewsDetail = async (id: number | string) => {
const response = await service.get(`index/companynews/detail/${id}`)
return response.data
}

1
src/assets/css/404.min.css vendored Normal file
View File

@ -0,0 +1 @@
*,p{font-weight:300}.btn,.btn:hover{color:#fff;text-decoration:none}#wrapper,body,html{height:100%}.container,.info,body{position:relative}.btn,.switcher{cursor:pointer}*{font-family:Raleway,Helvetica,Arial,sans-serif}body{background-color:#000c2f}h1,h2,h3,h4,h5,h6{color:#fff}img{background-size:auto}.error{border-color:red!important}::-webkit-input-placeholder{color:#fff}:-moz-placeholder{color:#fff;opacity:1}::-moz-placeholder{color:#fff;opacity:1}:-ms-input-placeholder{color:#fff}.btn{font-size:18px;font-weight:600;border:0 solid #ec9228;border-bottom:2px solid;padding:10px 41px;border-radius:5px;background:#ffad32;text-transform:uppercase;display:inline-block;margin:10px 20px 10px 0;-webkit-transition:all .5s ease-in-out;-moz-transition:all .5s ease-in-out;-ms-transition:all .5s ease-in-out;-o-transition:all .5s ease-in-out;transition:all .5s ease-in-out}.btn:hover{background:#ec9228}.btn-brown{border-color:#ec5900;background-color:#ff7000}.btn-brown:hover{background:#ec5900}#wrapper{min-height:100%;width:100%}#dark{display:block;visibility:visible}#light{display:none;visibility:hidden}body.light{background-color:#eaff6f}body.light #light{display:block;visibility:visible}body.light #dark{display:none;visibility:hidden}.info{z-index:999;margin-top:200px;margin-bottom:60px}.info p{font-size:16px;line-height:24px;font-weight:300;color:#1b334d;margin:30px 0}#light .info img{margin-left:-54px}#light .info{margin-top:94px}.text-l{display:none}.light .text-l,.text-d{display:inline-block}.light .text-d{display:none}.switcher{width:185px;height:84px;position:absolute;top:100px;left:65px;z-index:9999}.switcher *{transition:all .2s;-moz-transition:all .2s;-webkit-transition:all .2s;-o-transition:all .2s;-ms-transition:all .2s}.switcher .sw_btn{background:url(../img/btn.png) no-repeat;width:42px;height:45px;display:block;cursor:pointer;z-index:1;position:absolute;top:22px;left:65px}.switcher .bg{background:url(../img/bg_btn.png) no-repeat;width:100%;height:100%;position:absolute;top:0;left:0;z-index:0}.switcher input.switcher-value{display:none}.switcher input.switcher-value:checked~.sw_btn{margin-left:55px}.switcher .text{color:#fff;font-size:14px;position:absolute;left:-24px;top:21px}.light .switcher .text{color:#343f69}.animationload{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#fff;z-index:999999}.loader{position:absolute;top:50%;left:50%;margin:-100px 0 0 -100px;width:200px;height:200px;background-image:url(../img/ajax-loader.gif);background-position:center;background-repeat:no-repeat}@media (max-width:1200px){.info h1{font-size:110px}.info h2{font-size:55px;line-height:55px}}@media (max-width:992px){.info h1{font-size:56px;line-height:36px;margin-top:85px}.info h2{font-size:30px;line-height:16px}#dark .info img,#light .info img{width:480px}#light .info{margin-top:154px}}@media (max-width:767px){#dark .info img,#light .info img{width:360px}.info{text-align:center}.info h1{margin-top:80px}.switcher{top:20px}}@media (max-width:500px){.info p{font-size:16px}#dark .info img{width:260px}#light .info img{width:260px;margin-left:-24px}}@media (max-width:440px){.info p br{display:none}.btn{display:block;margin:20px}}

9
src/assets/css/all.min.css vendored Normal file

File diff suppressed because one or more lines are too long

6
src/assets/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,280 @@
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 300;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCAIT5lu.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 300;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCkIT5lu.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 300;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCIIT5lu.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 300;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCMIT5lu.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 300;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyC0ITw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCAIT5lu.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCkIT5lu.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCIIT5lu.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCMIT5lu.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyC0ITw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCAIT5lu.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCkIT5lu.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCIIT5lu.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCMIT5lu.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 500;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyC0ITw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 600;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCAIT5lu.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 600;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCkIT5lu.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 600;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCIIT5lu.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 600;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCMIT5lu.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 600;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyC0ITw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCAIT5lu.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCkIT5lu.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCIIT5lu.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCMIT5lu.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 700;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyC0ITw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 800;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCAIT5lu.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 800;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCkIT5lu.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 800;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCIIT5lu.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 800;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCMIT5lu.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 800;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyC0ITw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 900;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCAIT5lu.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 900;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCkIT5lu.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* vietnamese */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 900;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCIIT5lu.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 900;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyCMIT5lu.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Raleway';
font-style: normal;
font-weight: 900;
src: url(https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyC0ITw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

277
src/assets/css/styles.css Normal file
View File

@ -0,0 +1,277 @@
@import 'tailwindcss';
/* =========================================
标题样式
========================================= */
h1,
h2,
h3,
h4,
h5,
h6 {
color: #111827;
font-weight: 700;
line-height: 1.25;
margin-top: 1.5em;
margin-bottom: 0.5em;
}
h1 {
font-size: 2.5rem;
letter-spacing: -0.025em;
margin-top: 0;
}
h2 {
font-size: 2rem;
letter-spacing: -0.025em;
}
h3 {
font-size: 1.75rem;
}
h4 {
font-size: 1.5rem;
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* =========================================
段落与文本
========================================= */
p {
margin-top: 0;
margin-bottom: 1rem;
color: var(--text-secondary);
font-size: 1.125rem; /* 18px */
}
/* 链接 */
a {
color: var(--primary-color);
text-decoration: none;
transition:
color 0.2s ease,
text-decoration 0.2s ease;
}
a:hover {
color: var(--primary-hover);
text-decoration: underline;
}
/* 强调文本 */
strong,
b {
font-weight: 600;
color: var(--text-main);
}
em,
i {
font-style: italic;
}
mark {
background-color: #fef3c7;
color: #92400e;
padding: 0.2em 0.4em;
border-radius: 4px;
}
del {
color: var(--text-muted);
text-decoration: line-through;
}
/* =========================================
Span 实用类
========================================= */
.span-primary {
color: var(--primary-color);
font-weight: 500;
}
.span-muted {
color: var(--text-muted);
font-size: 0.9em;
}
.span-badge {
display: inline-block;
padding: 0.25em 0.75em;
font-size: 0.75rem;
font-weight: 600;
line-height: 1;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: 1rem;
background-color: #dbeafe;
color: #1e40af;
}
.span-code {
font-family: monospace;
background: #f1f5f9;
padding: 0.2em 0.4em;
border-radius: 4px;
font-size: 0.9em;
color: #ef4444;
}
/* =========================================
列表样式
========================================= */
ul,
ol {
margin: 0 0 1rem 1.5rem;
color: var(--text-secondary);
}
ul li {
margin-bottom: 0.5rem;
padding-left: 0.25rem;
}
/* 自定义无序列表符号 */
ul {
list-style-type: disc;
}
ul ul {
list-style-type: circle;
}
ul ul ul {
list-style-type: square;
}
ol li {
margin-bottom: 0.5rem;
}
dl {
margin: 0 0 1rem;
}
dt {
font-weight: 600;
color: var(--text-main);
margin-top: 0.5rem;
}
dd {
margin-left: 1.5rem;
color: var(--text-secondary);
}
/* =========================================
引用块
========================================= */
blockquote {
margin: 1.5rem 0;
padding: 1rem 1.5rem;
border-left: 5px solid var(--primary-color);
background-color: #eff6ff;
color: #1e3a8a;
border-radius: 0 var(--border-radius) var(--border-radius) 0;
}
blockquote p {
margin-bottom: 0;
font-size: 1.1rem;
}
blockquote footer {
margin-top: 0.75rem;
font-size: 0.875rem;
color: #60a5fa;
font-style: italic;
}
/* =========================================
代码样式
========================================= */
code,
kbd,
pre {
font-family: 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
}
/* 行内代码 */
code {
background-color: #f3f4f6;
color: #c026d3; /* 紫色调 */
padding: 0.2em 0.4em;
border-radius: 4px;
font-size: 90%;
}
/* 代码块 */
pre {
background-color: var(--code-bg);
color: var(--code-text);
padding: 1.25rem;
border-radius: var(--border-radius);
overflow-x: auto;
margin: 1.5rem 0;
font-size: 0.9rem;
}
pre code {
background-color: transparent;
color: inherit;
padding: 0;
border-radius: 0;
font-size: inherit;
}
/* =========================================
表格样式
========================================= */
.table-responsive {
overflow-x: auto;
margin: 1.5rem 0;
}
table {
width: 100%;
border-collapse: collapse;
background-color: #fff;
font-size: 0.95rem;
}
th,
td {
padding: 0.75rem;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
th {
font-weight: 600;
color: var(--text-main);
background-color: #f9fafb;
}
tr:last-child td {
border-bottom: none;
}
tbody tr:hover {
background-color: #f8fafc;
}
/* =========================================
分割线
========================================= */
hr {
border: 0;
height: 1px;
background-image: linear-gradient(
to right,
rgba(0, 0, 0, 0),
var(--border-color),
rgba(0, 0, 0, 0)
);
margin: 2rem 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 KiB

BIN
src/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 KiB

1
src/assets/js/404.min.js vendored Normal file
View File

@ -0,0 +1 @@
$(window).load(function(){"use strict";$(".loader").delay(400).fadeOut(),$(".animationload").delay(400).fadeOut("fast")}),$(document).ready(function(){$(".sw_btn").on("click",function(){$("body").toggleClass("light")}),$("html").niceScroll({cursorcolor:"#fff",cursoropacitymin:"0",cursoropacitymax:"1",cursorwidth:"2px",zindex:999999,horizrailenabled:!1,enablekeyboard:!1})});

7
src/assets/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

4
src/assets/js/jquery-2.2.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

118
src/assets/js/jquery.nicescroll.min.js vendored Normal file
View File

@ -0,0 +1,118 @@
/* jquery.nicescroll 3.6.0 InuYaksa*2014 MIT http://nicescroll.areaaperta.com */(function(f){"function"===typeof define&&define.amd?define(["jquery"],f):f(jQuery)})(function(f){var y=!1,D=!1,N=0,O=2E3,x=0,H=["webkit","ms","moz","o"],s=window.requestAnimationFrame||!1,t=window.cancelAnimationFrame||!1;if(!s)for(var P in H){var E=H[P];s||(s=window[E+"RequestAnimationFrame"]);t||(t=window[E+"CancelAnimationFrame"]||window[E+"CancelRequestAnimationFrame"])}var v=window.MutationObserver||window.WebKitMutationObserver||!1,I={zindex:"auto",cursoropacitymin:0,cursoropacitymax:1,cursorcolor:"#424242",
cursorwidth:"5px",cursorborder:"1px solid #fff",cursorborderradius:"5px",scrollspeed:60,mousescrollstep:24,touchbehavior:!1,hwacceleration:!0,usetransition:!0,boxzoom:!1,dblclickzoom:!0,gesturezoom:!0,grabcursorenabled:!0,autohidemode:!0,background:"",iframeautoresize:!0,cursorminheight:32,preservenativescrolling:!0,railoffset:!1,railhoffset:!1,bouncescroll:!0,spacebarenabled:!0,railpadding:{top:0,right:0,left:0,bottom:0},disableoutline:!0,horizrailenabled:!0,railalign:"right",railvalign:"bottom",
enabletranslate3d:!0,enablemousewheel:!0,enablekeyboard:!0,smoothscroll:!0,sensitiverail:!0,enablemouselockapi:!0,cursorfixedheight:!1,directionlockdeadzone:6,hidecursordelay:400,nativeparentscrolling:!0,enablescrollonselection:!0,overflowx:!0,overflowy:!0,cursordragspeed:.3,rtlmode:"auto",cursordragontouch:!1,oneaxismousemode:"auto",scriptpath:function(){var f=document.getElementsByTagName("script"),f=f[f.length-1].src.split("?")[0];return 0<f.split("/").length?f.split("/").slice(0,-1).join("/")+
"/":""}(),preventmultitouchscrolling:!0},F=!1,Q=function(){if(F)return F;var f=document.createElement("DIV"),c=f.style,h=navigator.userAgent,m=navigator.platform,d={haspointerlock:"pointerLockElement"in document||"webkitPointerLockElement"in document||"mozPointerLockElement"in document};d.isopera="opera"in window;d.isopera12=d.isopera&&"getUserMedia"in navigator;d.isoperamini="[object OperaMini]"===Object.prototype.toString.call(window.operamini);d.isie="all"in document&&"attachEvent"in f&&!d.isopera;
d.isieold=d.isie&&!("msInterpolationMode"in c);d.isie7=d.isie&&!d.isieold&&(!("documentMode"in document)||7==document.documentMode);d.isie8=d.isie&&"documentMode"in document&&8==document.documentMode;d.isie9=d.isie&&"performance"in window&&9<=document.documentMode;d.isie10=d.isie&&"performance"in window&&10==document.documentMode;d.isie11="msRequestFullscreen"in f&&11<=document.documentMode;d.isie9mobile=/iemobile.9/i.test(h);d.isie9mobile&&(d.isie9=!1);d.isie7mobile=!d.isie9mobile&&d.isie7&&/iemobile/i.test(h);
d.ismozilla="MozAppearance"in c;d.iswebkit="WebkitAppearance"in c;d.ischrome="chrome"in window;d.ischrome22=d.ischrome&&d.haspointerlock;d.ischrome26=d.ischrome&&"transition"in c;d.cantouch="ontouchstart"in document.documentElement||"ontouchstart"in window;d.hasmstouch=window.MSPointerEvent||!1;d.hasw3ctouch=window.PointerEvent||!1;d.ismac=/^mac$/i.test(m);d.isios=d.cantouch&&/iphone|ipad|ipod/i.test(m);d.isios4=d.isios&&!("seal"in Object);d.isios7=d.isios&&"webkitHidden"in document;d.isandroid=/android/i.test(h);
d.haseventlistener="addEventListener"in f;d.trstyle=!1;d.hastransform=!1;d.hastranslate3d=!1;d.transitionstyle=!1;d.hastransition=!1;d.transitionend=!1;m=["transform","msTransform","webkitTransform","MozTransform","OTransform"];for(h=0;h<m.length;h++)if("undefined"!=typeof c[m[h]]){d.trstyle=m[h];break}d.hastransform=!!d.trstyle;d.hastransform&&(c[d.trstyle]="translate3d(1px,2px,3px)",d.hastranslate3d=/translate3d/.test(c[d.trstyle]));d.transitionstyle=!1;d.prefixstyle="";d.transitionend=!1;for(var m=
"transition webkitTransition msTransition MozTransition OTransition OTransition KhtmlTransition".split(" "),n=" -webkit- -ms- -moz- -o- -o -khtml-".split(" "),p="transitionend webkitTransitionEnd msTransitionEnd transitionend otransitionend oTransitionEnd KhtmlTransitionEnd".split(" "),h=0;h<m.length;h++)if(m[h]in c){d.transitionstyle=m[h];d.prefixstyle=n[h];d.transitionend=p[h];break}d.ischrome26&&(d.prefixstyle=n[1]);d.hastransition=d.transitionstyle;a:{h=["-webkit-grab","-moz-grab","grab"];if(d.ischrome&&
!d.ischrome22||d.isie)h=[];for(m=0;m<h.length;m++)if(n=h[m],c.cursor=n,c.cursor==n){c=n;break a}c="url(//mail.google.com/mail/images/2/openhand.cur),n-resize"}d.cursorgrabvalue=c;d.hasmousecapture="setCapture"in f;d.hasMutationObserver=!1!==v;return F=d},R=function(k,c){function h(){var b=a.doc.css(e.trstyle);return b&&"matrix"==b.substr(0,6)?b.replace(/^.*\((.*)\)$/g,"$1").replace(/px/g,"").split(/, +/):!1}function m(){var b=a.win;if("zIndex"in b)return b.zIndex();for(;0<b.length&&9!=b[0].nodeType;){var g=
b.css("zIndex");if(!isNaN(g)&&0!=g)return parseInt(g);b=b.parent()}return!1}function d(b,g,q){g=b.css(g);b=parseFloat(g);return isNaN(b)?(b=w[g]||0,q=3==b?q?a.win.outerHeight()-a.win.innerHeight():a.win.outerWidth()-a.win.innerWidth():1,a.isie8&&b&&(b+=1),q?b:0):b}function n(b,g,q,c){a._bind(b,g,function(a){a=a?a:window.event;var c={original:a,target:a.target||a.srcElement,type:"wheel",deltaMode:"MozMousePixelScroll"==a.type?0:1,deltaX:0,deltaZ:0,preventDefault:function(){a.preventDefault?a.preventDefault():
a.returnValue=!1;return!1},stopImmediatePropagation:function(){a.stopImmediatePropagation?a.stopImmediatePropagation():a.cancelBubble=!0}};"mousewheel"==g?(c.deltaY=-.025*a.wheelDelta,a.wheelDeltaX&&(c.deltaX=-.025*a.wheelDeltaX)):c.deltaY=a.detail;return q.call(b,c)},c)}function p(b,g,c){var d,e;0==b.deltaMode?(d=-Math.floor(a.opt.mousescrollstep/54*b.deltaX),e=-Math.floor(a.opt.mousescrollstep/54*b.deltaY)):1==b.deltaMode&&(d=-Math.floor(b.deltaX*a.opt.mousescrollstep),e=-Math.floor(b.deltaY*a.opt.mousescrollstep));
g&&a.opt.oneaxismousemode&&0==d&&e&&(d=e,e=0,c&&(0>d?a.getScrollLeft()>=a.page.maxw:0>=a.getScrollLeft())&&(e=d,d=0));d&&(a.scrollmom&&a.scrollmom.stop(),a.lastdeltax+=d,a.debounced("mousewheelx",function(){var b=a.lastdeltax;a.lastdeltax=0;a.rail.drag||a.doScrollLeftBy(b)},15));if(e){if(a.opt.nativeparentscrolling&&c&&!a.ispage&&!a.zoomactive)if(0>e){if(a.getScrollTop()>=a.page.maxh)return!0}else if(0>=a.getScrollTop())return!0;a.scrollmom&&a.scrollmom.stop();a.lastdeltay+=e;a.debounced("mousewheely",
function(){var b=a.lastdeltay;a.lastdeltay=0;a.rail.drag||a.doScrollBy(b)},15)}b.stopImmediatePropagation();return b.preventDefault()}var a=this;this.version="3.6.0";this.name="nicescroll";this.me=c;this.opt={doc:f("body"),win:!1};f.extend(this.opt,I);this.opt.snapbackspeed=80;if(k)for(var G in a.opt)"undefined"!=typeof k[G]&&(a.opt[G]=k[G]);this.iddoc=(this.doc=a.opt.doc)&&this.doc[0]?this.doc[0].id||"":"";this.ispage=/^BODY|HTML/.test(a.opt.win?a.opt.win[0].nodeName:this.doc[0].nodeName);this.haswrapper=
!1!==a.opt.win;this.win=a.opt.win||(this.ispage?f(window):this.doc);this.docscroll=this.ispage&&!this.haswrapper?f(window):this.win;this.body=f("body");this.iframe=this.isfixed=this.viewport=!1;this.isiframe="IFRAME"==this.doc[0].nodeName&&"IFRAME"==this.win[0].nodeName;this.istextarea="TEXTAREA"==this.win[0].nodeName;this.forcescreen=!1;this.canshowonmouseevent="scroll"!=a.opt.autohidemode;this.page=this.view=this.onzoomout=this.onzoomin=this.onscrollcancel=this.onscrollend=this.onscrollstart=this.onclick=
this.ongesturezoom=this.onkeypress=this.onmousewheel=this.onmousemove=this.onmouseup=this.onmousedown=!1;this.scroll={x:0,y:0};this.scrollratio={x:0,y:0};this.cursorheight=20;this.scrollvaluemax=0;this.isrtlmode="auto"==this.opt.rtlmode?"rtl"==(this.win[0]==window?this.body:this.win).css("direction"):!0===this.opt.rtlmode;this.observerbody=this.observerremover=this.observer=this.scrollmom=this.scrollrunning=!1;do this.id="ascrail"+O++;while(document.getElementById(this.id));this.hasmousefocus=this.hasfocus=
this.zoomactive=this.zoom=this.selectiondrag=this.cursorfreezed=this.cursor=this.rail=!1;this.visibility=!0;this.hidden=this.locked=this.railslocked=!1;this.cursoractive=!0;this.wheelprevented=!1;this.overflowx=a.opt.overflowx;this.overflowy=a.opt.overflowy;this.nativescrollingarea=!1;this.checkarea=0;this.events=[];this.saved={};this.delaylist={};this.synclist={};this.lastdeltay=this.lastdeltax=0;this.detected=Q();var e=f.extend({},this.detected);this.ishwscroll=(this.canhwscroll=e.hastransform&&
a.opt.hwacceleration)&&a.haswrapper;this.hasreversehr=this.isrtlmode&&!e.iswebkit;this.istouchcapable=!1;!e.cantouch||e.isios||e.isandroid||!e.iswebkit&&!e.ismozilla||(this.istouchcapable=!0,e.cantouch=!1);a.opt.enablemouselockapi||(e.hasmousecapture=!1,e.haspointerlock=!1);this.debounced=function(b,g,c){var d=a.delaylist[b];a.delaylist[b]=g;d||setTimeout(function(){var g=a.delaylist[b];a.delaylist[b]=!1;g.call(a)},c)};var r=!1;this.synched=function(b,g){a.synclist[b]=g;(function(){r||(s(function(){r=
!1;for(var b in a.synclist){var g=a.synclist[b];g&&g.call(a);a.synclist[b]=!1}}),r=!0)})();return b};this.unsynched=function(b){a.synclist[b]&&(a.synclist[b]=!1)};this.css=function(b,g){for(var c in g)a.saved.css.push([b,c,b.css(c)]),b.css(c,g[c])};this.scrollTop=function(b){return"undefined"==typeof b?a.getScrollTop():a.setScrollTop(b)};this.scrollLeft=function(b){return"undefined"==typeof b?a.getScrollLeft():a.setScrollLeft(b)};var A=function(a,g,c,d,e,f,h){this.st=a;this.ed=g;this.spd=c;this.p1=
d||0;this.p2=e||1;this.p3=f||0;this.p4=h||1;this.ts=(new Date).getTime();this.df=this.ed-this.st};A.prototype={B2:function(a){return 3*a*a*(1-a)},B3:function(a){return 3*a*(1-a)*(1-a)},B4:function(a){return(1-a)*(1-a)*(1-a)},getNow:function(){var a=1-((new Date).getTime()-this.ts)/this.spd,g=this.B2(a)+this.B3(a)+this.B4(a);return 0>a?this.ed:this.st+Math.round(this.df*g)},update:function(a,g){this.st=this.getNow();this.ed=a;this.spd=g;this.ts=(new Date).getTime();this.df=this.ed-this.st;return this}};
if(this.ishwscroll){this.doc.translate={x:0,y:0,tx:"0px",ty:"0px"};e.hastranslate3d&&e.isios&&this.doc.css("-webkit-backface-visibility","hidden");this.getScrollTop=function(b){if(!b){if(b=h())return 16==b.length?-b[13]:-b[5];if(a.timerscroll&&a.timerscroll.bz)return a.timerscroll.bz.getNow()}return a.doc.translate.y};this.getScrollLeft=function(b){if(!b){if(b=h())return 16==b.length?-b[12]:-b[4];if(a.timerscroll&&a.timerscroll.bh)return a.timerscroll.bh.getNow()}return a.doc.translate.x};this.notifyScrollEvent=
function(a){var g=document.createEvent("UIEvents");g.initUIEvent("scroll",!1,!0,window,1);g.niceevent=!0;a.dispatchEvent(g)};var K=this.isrtlmode?1:-1;e.hastranslate3d&&a.opt.enabletranslate3d?(this.setScrollTop=function(b,g){a.doc.translate.y=b;a.doc.translate.ty=-1*b+"px";a.doc.css(e.trstyle,"translate3d("+a.doc.translate.tx+","+a.doc.translate.ty+",0px)");g||a.notifyScrollEvent(a.win[0])},this.setScrollLeft=function(b,g){a.doc.translate.x=b;a.doc.translate.tx=b*K+"px";a.doc.css(e.trstyle,"translate3d("+
a.doc.translate.tx+","+a.doc.translate.ty+",0px)");g||a.notifyScrollEvent(a.win[0])}):(this.setScrollTop=function(b,g){a.doc.translate.y=b;a.doc.translate.ty=-1*b+"px";a.doc.css(e.trstyle,"translate("+a.doc.translate.tx+","+a.doc.translate.ty+")");g||a.notifyScrollEvent(a.win[0])},this.setScrollLeft=function(b,g){a.doc.translate.x=b;a.doc.translate.tx=b*K+"px";a.doc.css(e.trstyle,"translate("+a.doc.translate.tx+","+a.doc.translate.ty+")");g||a.notifyScrollEvent(a.win[0])})}else this.getScrollTop=
function(){return a.docscroll.scrollTop()},this.setScrollTop=function(b){return a.docscroll.scrollTop(b)},this.getScrollLeft=function(){return a.detected.ismozilla&&a.isrtlmode?Math.abs(a.docscroll.scrollLeft()):a.docscroll.scrollLeft()},this.setScrollLeft=function(b){return a.docscroll.scrollLeft(a.detected.ismozilla&&a.isrtlmode?-b:b)};this.getTarget=function(a){return a?a.target?a.target:a.srcElement?a.srcElement:!1:!1};this.hasParent=function(a,g){if(!a)return!1;for(var c=a.target||a.srcElement||
a||!1;c&&c.id!=g;)c=c.parentNode||!1;return!1!==c};var w={thin:1,medium:3,thick:5};this.getDocumentScrollOffset=function(){return{top:window.pageYOffset||document.documentElement.scrollTop,left:window.pageXOffset||document.documentElement.scrollLeft}};this.getOffset=function(){if(a.isfixed){var b=a.win.offset(),g=a.getDocumentScrollOffset();b.top-=g.top;b.left-=g.left;return b}b=a.win.offset();if(!a.viewport)return b;g=a.viewport.offset();return{top:b.top-g.top,left:b.left-g.left}};this.updateScrollBar=
function(b){if(a.ishwscroll)a.rail.css({height:a.win.innerHeight()-(a.opt.railpadding.top+a.opt.railpadding.bottom)}),a.railh&&a.railh.css({width:a.win.innerWidth()-(a.opt.railpadding.left+a.opt.railpadding.right)});else{var g=a.getOffset(),c=g.top,e=g.left-(a.opt.railpadding.left+a.opt.railpadding.right),c=c+d(a.win,"border-top-width",!0),e=e+(a.rail.align?a.win.outerWidth()-d(a.win,"border-right-width")-a.rail.width:d(a.win,"border-left-width")),f=a.opt.railoffset;f&&(f.top&&(c+=f.top),a.rail.align&&
f.left&&(e+=f.left));a.railslocked||a.rail.css({top:c,left:e,height:(b?b.h:a.win.innerHeight())-(a.opt.railpadding.top+a.opt.railpadding.bottom)});a.zoom&&a.zoom.css({top:c+1,left:1==a.rail.align?e-20:e+a.rail.width+4});if(a.railh&&!a.railslocked){c=g.top;e=g.left;if(f=a.opt.railhoffset)f.top&&(c+=f.top),f.left&&(e+=f.left);b=a.railh.align?c+d(a.win,"border-top-width",!0)+a.win.innerHeight()-a.railh.height:c+d(a.win,"border-top-width",!0);e+=d(a.win,"border-left-width");a.railh.css({top:b-(a.opt.railpadding.top+
a.opt.railpadding.bottom),left:e,width:a.railh.width})}}};this.doRailClick=function(b,g,c){var e;a.railslocked||(a.cancelEvent(b),g?(g=c?a.doScrollLeft:a.doScrollTop,e=c?(b.pageX-a.railh.offset().left-a.cursorwidth/2)*a.scrollratio.x:(b.pageY-a.rail.offset().top-a.cursorheight/2)*a.scrollratio.y,g(e)):(g=c?a.doScrollLeftBy:a.doScrollBy,e=c?a.scroll.x:a.scroll.y,b=c?b.pageX-a.railh.offset().left:b.pageY-a.rail.offset().top,c=c?a.view.w:a.view.h,g(e>=b?c:-c)))};a.hasanimationframe=s;a.hascancelanimationframe=
t;a.hasanimationframe?a.hascancelanimationframe||(t=function(){a.cancelAnimationFrame=!0}):(s=function(a){return setTimeout(a,15-Math.floor(+new Date/1E3)%16)},t=clearInterval);this.init=function(){a.saved.css=[];if(e.isie7mobile||e.isoperamini)return!0;e.hasmstouch&&a.css(a.ispage?f("html"):a.win,{"-ms-touch-action":"none"});a.zindex="auto";a.zindex=a.ispage||"auto"!=a.opt.zindex?a.opt.zindex:m()||"auto";!a.ispage&&"auto"!=a.zindex&&a.zindex>x&&(x=a.zindex);a.isie&&0==a.zindex&&"auto"==a.opt.zindex&&
(a.zindex="auto");if(!a.ispage||!e.cantouch&&!e.isieold&&!e.isie9mobile){var b=a.docscroll;a.ispage&&(b=a.haswrapper?a.win:a.doc);e.isie9mobile||a.css(b,{"overflow-y":"hidden"});a.ispage&&e.isie7&&("BODY"==a.doc[0].nodeName?a.css(f("html"),{"overflow-y":"hidden"}):"HTML"==a.doc[0].nodeName&&a.css(f("body"),{"overflow-y":"hidden"}));!e.isios||a.ispage||a.haswrapper||a.css(f("body"),{"-webkit-overflow-scrolling":"touch"});var g=f(document.createElement("div"));g.css({position:"relative",top:0,"float":"right",
width:a.opt.cursorwidth,height:"0px","background-color":a.opt.cursorcolor,border:a.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":a.opt.cursorborderradius,"-moz-border-radius":a.opt.cursorborderradius,"border-radius":a.opt.cursorborderradius});g.hborder=parseFloat(g.outerHeight()-g.innerHeight());g.addClass("nicescroll-cursors");a.cursor=g;var c=f(document.createElement("div"));c.attr("id",a.id);c.addClass("nicescroll-rails nicescroll-rails-vr");var d,h,k=["left","right",
"top","bottom"],J;for(J in k)h=k[J],(d=a.opt.railpadding[h])?c.css("padding-"+h,d+"px"):a.opt.railpadding[h]=0;c.append(g);c.width=Math.max(parseFloat(a.opt.cursorwidth),g.outerWidth());c.css({width:c.width+"px",zIndex:a.zindex,background:a.opt.background,cursor:"default"});c.visibility=!0;c.scrollable=!0;c.align="left"==a.opt.railalign?0:1;a.rail=c;g=a.rail.drag=!1;!a.opt.boxzoom||a.ispage||e.isieold||(g=document.createElement("div"),a.bind(g,"click",a.doZoom),a.bind(g,"mouseenter",function(){a.zoom.css("opacity",
a.opt.cursoropacitymax)}),a.bind(g,"mouseleave",function(){a.zoom.css("opacity",a.opt.cursoropacitymin)}),a.zoom=f(g),a.zoom.css({cursor:"pointer","z-index":a.zindex,backgroundImage:"url("+a.opt.scriptpath+"zoomico.png)",height:18,width:18,backgroundPosition:"0px 0px"}),a.opt.dblclickzoom&&a.bind(a.win,"dblclick",a.doZoom),e.cantouch&&a.opt.gesturezoom&&(a.ongesturezoom=function(b){1.5<b.scale&&a.doZoomIn(b);.8>b.scale&&a.doZoomOut(b);return a.cancelEvent(b)},a.bind(a.win,"gestureend",a.ongesturezoom)));
a.railh=!1;var l;a.opt.horizrailenabled&&(a.css(b,{"overflow-x":"hidden"}),g=f(document.createElement("div")),g.css({position:"absolute",top:0,height:a.opt.cursorwidth,width:"0px","background-color":a.opt.cursorcolor,border:a.opt.cursorborder,"background-clip":"padding-box","-webkit-border-radius":a.opt.cursorborderradius,"-moz-border-radius":a.opt.cursorborderradius,"border-radius":a.opt.cursorborderradius}),e.isieold&&g.css({overflow:"hidden"}),g.wborder=parseFloat(g.outerWidth()-g.innerWidth()),
g.addClass("nicescroll-cursors"),a.cursorh=g,l=f(document.createElement("div")),l.attr("id",a.id+"-hr"),l.addClass("nicescroll-rails nicescroll-rails-hr"),l.height=Math.max(parseFloat(a.opt.cursorwidth),g.outerHeight()),l.css({height:l.height+"px",zIndex:a.zindex,background:a.opt.background}),l.append(g),l.visibility=!0,l.scrollable=!0,l.align="top"==a.opt.railvalign?0:1,a.railh=l,a.railh.drag=!1);a.ispage?(c.css({position:"fixed",top:"0px",height:"100%"}),c.align?c.css({right:"0px"}):c.css({left:"0px"}),
a.body.append(c),a.railh&&(l.css({position:"fixed",left:"0px",width:"100%"}),l.align?l.css({bottom:"0px"}):l.css({top:"0px"}),a.body.append(l))):(a.ishwscroll?("static"==a.win.css("position")&&a.css(a.win,{position:"relative"}),b="HTML"==a.win[0].nodeName?a.body:a.win,f(b).scrollTop(0).scrollLeft(0),a.zoom&&(a.zoom.css({position:"absolute",top:1,right:0,"margin-right":c.width+4}),b.append(a.zoom)),c.css({position:"absolute",top:0}),c.align?c.css({right:0}):c.css({left:0}),b.append(c),l&&(l.css({position:"absolute",
left:0,bottom:0}),l.align?l.css({bottom:0}):l.css({top:0}),b.append(l))):(a.isfixed="fixed"==a.win.css("position"),b=a.isfixed?"fixed":"absolute",a.isfixed||(a.viewport=a.getViewport(a.win[0])),a.viewport&&(a.body=a.viewport,0==/fixed|absolute/.test(a.viewport.css("position"))&&a.css(a.viewport,{position:"relative"})),c.css({position:b}),a.zoom&&a.zoom.css({position:b}),a.updateScrollBar(),a.body.append(c),a.zoom&&a.body.append(a.zoom),a.railh&&(l.css({position:b}),a.body.append(l))),e.isios&&a.css(a.win,
{"-webkit-tap-highlight-color":"rgba(0,0,0,0)","-webkit-touch-callout":"none"}),e.isie&&a.opt.disableoutline&&a.win.attr("hideFocus","true"),e.iswebkit&&a.opt.disableoutline&&a.win.css({outline:"none"}));!1===a.opt.autohidemode?(a.autohidedom=!1,a.rail.css({opacity:a.opt.cursoropacitymax}),a.railh&&a.railh.css({opacity:a.opt.cursoropacitymax})):!0===a.opt.autohidemode||"leave"===a.opt.autohidemode?(a.autohidedom=f().add(a.rail),e.isie8&&(a.autohidedom=a.autohidedom.add(a.cursor)),a.railh&&(a.autohidedom=
a.autohidedom.add(a.railh)),a.railh&&e.isie8&&(a.autohidedom=a.autohidedom.add(a.cursorh))):"scroll"==a.opt.autohidemode?(a.autohidedom=f().add(a.rail),a.railh&&(a.autohidedom=a.autohidedom.add(a.railh))):"cursor"==a.opt.autohidemode?(a.autohidedom=f().add(a.cursor),a.railh&&(a.autohidedom=a.autohidedom.add(a.cursorh))):"hidden"==a.opt.autohidemode&&(a.autohidedom=!1,a.hide(),a.railslocked=!1);if(e.isie9mobile)a.scrollmom=new L(a),a.onmangotouch=function(){var b=a.getScrollTop(),c=a.getScrollLeft();
if(b==a.scrollmom.lastscrolly&&c==a.scrollmom.lastscrollx)return!0;var g=b-a.mangotouch.sy,e=c-a.mangotouch.sx;if(0!=Math.round(Math.sqrt(Math.pow(e,2)+Math.pow(g,2)))){var d=0>g?-1:1,f=0>e?-1:1,q=+new Date;a.mangotouch.lazy&&clearTimeout(a.mangotouch.lazy);80<q-a.mangotouch.tm||a.mangotouch.dry!=d||a.mangotouch.drx!=f?(a.scrollmom.stop(),a.scrollmom.reset(c,b),a.mangotouch.sy=b,a.mangotouch.ly=b,a.mangotouch.sx=c,a.mangotouch.lx=c,a.mangotouch.dry=d,a.mangotouch.drx=f,a.mangotouch.tm=q):(a.scrollmom.stop(),
a.scrollmom.update(a.mangotouch.sx-e,a.mangotouch.sy-g),a.mangotouch.tm=q,g=Math.max(Math.abs(a.mangotouch.ly-b),Math.abs(a.mangotouch.lx-c)),a.mangotouch.ly=b,a.mangotouch.lx=c,2<g&&(a.mangotouch.lazy=setTimeout(function(){a.mangotouch.lazy=!1;a.mangotouch.dry=0;a.mangotouch.drx=0;a.mangotouch.tm=0;a.scrollmom.doMomentum(30)},100)))}},c=a.getScrollTop(),l=a.getScrollLeft(),a.mangotouch={sy:c,ly:c,dry:0,sx:l,lx:l,drx:0,lazy:!1,tm:0},a.bind(a.docscroll,"scroll",a.onmangotouch);else{if(e.cantouch||
a.istouchcapable||a.opt.touchbehavior||e.hasmstouch){a.scrollmom=new L(a);a.ontouchstart=function(b){if(b.pointerType&&2!=b.pointerType&&"touch"!=b.pointerType)return!1;a.hasmoving=!1;if(!a.railslocked){var c;if(e.hasmstouch)for(c=b.target?b.target:!1;c;){var g=f(c).getNiceScroll();if(0<g.length&&g[0].me==a.me)break;if(0<g.length)return!1;if("DIV"==c.nodeName&&c.id==a.id)break;c=c.parentNode?c.parentNode:!1}a.cancelScroll();if((c=a.getTarget(b))&&/INPUT/i.test(c.nodeName)&&/range/i.test(c.type))return a.stopPropagation(b);
!("clientX"in b)&&"changedTouches"in b&&(b.clientX=b.changedTouches[0].clientX,b.clientY=b.changedTouches[0].clientY);a.forcescreen&&(g=b,b={original:b.original?b.original:b},b.clientX=g.screenX,b.clientY=g.screenY);a.rail.drag={x:b.clientX,y:b.clientY,sx:a.scroll.x,sy:a.scroll.y,st:a.getScrollTop(),sl:a.getScrollLeft(),pt:2,dl:!1};if(a.ispage||!a.opt.directionlockdeadzone)a.rail.drag.dl="f";else{var g=f(window).width(),d=f(window).height(),q=Math.max(document.body.scrollWidth,document.documentElement.scrollWidth),
h=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight),d=Math.max(0,h-d),g=Math.max(0,q-g);a.rail.drag.ck=!a.rail.scrollable&&a.railh.scrollable?0<d?"v":!1:a.rail.scrollable&&!a.railh.scrollable?0<g?"h":!1:!1;a.rail.drag.ck||(a.rail.drag.dl="f")}a.opt.touchbehavior&&a.isiframe&&e.isie&&(g=a.win.position(),a.rail.drag.x+=g.left,a.rail.drag.y+=g.top);a.hasmoving=!1;a.lastmouseup=!1;a.scrollmom.reset(b.clientX,b.clientY);if(!e.cantouch&&!this.istouchcapable&&!b.pointerType){if(!c||
!/INPUT|SELECT|TEXTAREA/i.test(c.nodeName))return!a.ispage&&e.hasmousecapture&&c.setCapture(),a.opt.touchbehavior?(c.onclick&&!c._onclick&&(c._onclick=c.onclick,c.onclick=function(b){if(a.hasmoving)return!1;c._onclick.call(this,b)}),a.cancelEvent(b)):a.stopPropagation(b);/SUBMIT|CANCEL|BUTTON/i.test(f(c).attr("type"))&&(pc={tg:c,click:!1},a.preventclick=pc)}}};a.ontouchend=function(b){if(!a.rail.drag)return!0;if(2==a.rail.drag.pt){if(b.pointerType&&2!=b.pointerType&&"touch"!=b.pointerType)return!1;
a.scrollmom.doMomentum();a.rail.drag=!1;if(a.hasmoving&&(a.lastmouseup=!0,a.hideCursor(),e.hasmousecapture&&document.releaseCapture(),!e.cantouch))return a.cancelEvent(b)}else if(1==a.rail.drag.pt)return a.onmouseup(b)};var n=a.opt.touchbehavior&&a.isiframe&&!e.hasmousecapture;a.ontouchmove=function(b,c){if(!a.rail.drag||b.targetTouches&&a.opt.preventmultitouchscrolling&&1<b.targetTouches.length||b.pointerType&&2!=b.pointerType&&"touch"!=b.pointerType)return!1;if(2==a.rail.drag.pt){if(e.cantouch&&
e.isios&&"undefined"==typeof b.original)return!0;a.hasmoving=!0;a.preventclick&&!a.preventclick.click&&(a.preventclick.click=a.preventclick.tg.onclick||!1,a.preventclick.tg.onclick=a.onpreventclick);b=f.extend({original:b},b);"changedTouches"in b&&(b.clientX=b.changedTouches[0].clientX,b.clientY=b.changedTouches[0].clientY);if(a.forcescreen){var g=b;b={original:b.original?b.original:b};b.clientX=g.screenX;b.clientY=g.screenY}var d,g=d=0;n&&!c&&(d=a.win.position(),g=-d.left,d=-d.top);var q=b.clientY+
d;d=q-a.rail.drag.y;var h=b.clientX+g,u=h-a.rail.drag.x,k=a.rail.drag.st-d;a.ishwscroll&&a.opt.bouncescroll?0>k?k=Math.round(k/2):k>a.page.maxh&&(k=a.page.maxh+Math.round((k-a.page.maxh)/2)):(0>k&&(q=k=0),k>a.page.maxh&&(k=a.page.maxh,q=0));var l;a.railh&&a.railh.scrollable&&(l=a.isrtlmode?u-a.rail.drag.sl:a.rail.drag.sl-u,a.ishwscroll&&a.opt.bouncescroll?0>l?l=Math.round(l/2):l>a.page.maxw&&(l=a.page.maxw+Math.round((l-a.page.maxw)/2)):(0>l&&(h=l=0),l>a.page.maxw&&(l=a.page.maxw,h=0)));g=!1;if(a.rail.drag.dl)g=
!0,"v"==a.rail.drag.dl?l=a.rail.drag.sl:"h"==a.rail.drag.dl&&(k=a.rail.drag.st);else{d=Math.abs(d);var u=Math.abs(u),z=a.opt.directionlockdeadzone;if("v"==a.rail.drag.ck){if(d>z&&u<=.3*d)return a.rail.drag=!1,!0;u>z&&(a.rail.drag.dl="f",f("body").scrollTop(f("body").scrollTop()))}else if("h"==a.rail.drag.ck){if(u>z&&d<=.3*u)return a.rail.drag=!1,!0;d>z&&(a.rail.drag.dl="f",f("body").scrollLeft(f("body").scrollLeft()))}}a.synched("touchmove",function(){a.rail.drag&&2==a.rail.drag.pt&&(a.prepareTransition&&
a.prepareTransition(0),a.rail.scrollable&&a.setScrollTop(k),a.scrollmom.update(h,q),a.railh&&a.railh.scrollable?(a.setScrollLeft(l),a.showCursor(k,l)):a.showCursor(k),e.isie10&&document.selection.clear())});e.ischrome&&a.istouchcapable&&(g=!1);if(g)return a.cancelEvent(b)}else if(1==a.rail.drag.pt)return a.onmousemove(b)}}a.onmousedown=function(b,c){if(!a.rail.drag||1==a.rail.drag.pt){if(a.railslocked)return a.cancelEvent(b);a.cancelScroll();a.rail.drag={x:b.clientX,y:b.clientY,sx:a.scroll.x,sy:a.scroll.y,
pt:1,hr:!!c};var g=a.getTarget(b);!a.ispage&&e.hasmousecapture&&g.setCapture();a.isiframe&&!e.hasmousecapture&&(a.saved.csspointerevents=a.doc.css("pointer-events"),a.css(a.doc,{"pointer-events":"none"}));a.hasmoving=!1;return a.cancelEvent(b)}};a.onmouseup=function(b){if(a.rail.drag){if(1!=a.rail.drag.pt)return!0;e.hasmousecapture&&document.releaseCapture();a.isiframe&&!e.hasmousecapture&&a.doc.css("pointer-events",a.saved.csspointerevents);a.rail.drag=!1;a.hasmoving&&a.triggerScrollEnd();return a.cancelEvent(b)}};
a.onmousemove=function(b){if(a.rail.drag&&1==a.rail.drag.pt){if(e.ischrome&&0==b.which)return a.onmouseup(b);a.cursorfreezed=!0;a.hasmoving=!0;if(a.rail.drag.hr){a.scroll.x=a.rail.drag.sx+(b.clientX-a.rail.drag.x);0>a.scroll.x&&(a.scroll.x=0);var c=a.scrollvaluemaxw;a.scroll.x>c&&(a.scroll.x=c)}else a.scroll.y=a.rail.drag.sy+(b.clientY-a.rail.drag.y),0>a.scroll.y&&(a.scroll.y=0),c=a.scrollvaluemax,a.scroll.y>c&&(a.scroll.y=c);a.synched("mousemove",function(){a.rail.drag&&1==a.rail.drag.pt&&(a.showCursor(),
a.rail.drag.hr?a.hasreversehr?a.doScrollLeft(a.scrollvaluemaxw-Math.round(a.scroll.x*a.scrollratio.x),a.opt.cursordragspeed):a.doScrollLeft(Math.round(a.scroll.x*a.scrollratio.x),a.opt.cursordragspeed):a.doScrollTop(Math.round(a.scroll.y*a.scrollratio.y),a.opt.cursordragspeed))});return a.cancelEvent(b)}};if(e.cantouch||a.opt.touchbehavior)a.onpreventclick=function(b){if(a.preventclick)return a.preventclick.tg.onclick=a.preventclick.click,a.preventclick=!1,a.cancelEvent(b)},a.bind(a.win,"mousedown",
a.ontouchstart),a.onclick=e.isios?!1:function(b){return a.lastmouseup?(a.lastmouseup=!1,a.cancelEvent(b)):!0},a.opt.grabcursorenabled&&e.cursorgrabvalue&&(a.css(a.ispage?a.doc:a.win,{cursor:e.cursorgrabvalue}),a.css(a.rail,{cursor:e.cursorgrabvalue}));else{var p=function(b){if(a.selectiondrag){if(b){var c=a.win.outerHeight();b=b.pageY-a.selectiondrag.top;0<b&&b<c&&(b=0);b>=c&&(b-=c);a.selectiondrag.df=b}0!=a.selectiondrag.df&&(a.doScrollBy(2*-Math.floor(a.selectiondrag.df/6)),a.debounced("doselectionscroll",
function(){p()},50))}};a.hasTextSelected="getSelection"in document?function(){return 0<document.getSelection().rangeCount}:"selection"in document?function(){return"None"!=document.selection.type}:function(){return!1};a.onselectionstart=function(b){a.ispage||(a.selectiondrag=a.win.offset())};a.onselectionend=function(b){a.selectiondrag=!1};a.onselectiondrag=function(b){a.selectiondrag&&a.hasTextSelected()&&a.debounced("selectionscroll",function(){p(b)},250)}}e.hasw3ctouch?(a.css(a.rail,{"touch-action":"none"}),
a.css(a.cursor,{"touch-action":"none"}),a.bind(a.win,"pointerdown",a.ontouchstart),a.bind(document,"pointerup",a.ontouchend),a.bind(document,"pointermove",a.ontouchmove)):e.hasmstouch?(a.css(a.rail,{"-ms-touch-action":"none"}),a.css(a.cursor,{"-ms-touch-action":"none"}),a.bind(a.win,"MSPointerDown",a.ontouchstart),a.bind(document,"MSPointerUp",a.ontouchend),a.bind(document,"MSPointerMove",a.ontouchmove),a.bind(a.cursor,"MSGestureHold",function(a){a.preventDefault()}),a.bind(a.cursor,"contextmenu",
function(a){a.preventDefault()})):this.istouchcapable&&(a.bind(a.win,"touchstart",a.ontouchstart),a.bind(document,"touchend",a.ontouchend),a.bind(document,"touchcancel",a.ontouchend),a.bind(document,"touchmove",a.ontouchmove));if(a.opt.cursordragontouch||!e.cantouch&&!a.opt.touchbehavior)a.rail.css({cursor:"default"}),a.railh&&a.railh.css({cursor:"default"}),a.jqbind(a.rail,"mouseenter",function(){if(!a.ispage&&!a.win.is(":visible"))return!1;a.canshowonmouseevent&&a.showCursor();a.rail.active=!0}),
a.jqbind(a.rail,"mouseleave",function(){a.rail.active=!1;a.rail.drag||a.hideCursor()}),a.opt.sensitiverail&&(a.bind(a.rail,"click",function(b){a.doRailClick(b,!1,!1)}),a.bind(a.rail,"dblclick",function(b){a.doRailClick(b,!0,!1)}),a.bind(a.cursor,"click",function(b){a.cancelEvent(b)}),a.bind(a.cursor,"dblclick",function(b){a.cancelEvent(b)})),a.railh&&(a.jqbind(a.railh,"mouseenter",function(){if(!a.ispage&&!a.win.is(":visible"))return!1;a.canshowonmouseevent&&a.showCursor();a.rail.active=!0}),a.jqbind(a.railh,
"mouseleave",function(){a.rail.active=!1;a.rail.drag||a.hideCursor()}),a.opt.sensitiverail&&(a.bind(a.railh,"click",function(b){a.doRailClick(b,!1,!0)}),a.bind(a.railh,"dblclick",function(b){a.doRailClick(b,!0,!0)}),a.bind(a.cursorh,"click",function(b){a.cancelEvent(b)}),a.bind(a.cursorh,"dblclick",function(b){a.cancelEvent(b)})));e.cantouch||a.opt.touchbehavior?(a.bind(e.hasmousecapture?a.win:document,"mouseup",a.ontouchend),a.bind(document,"mousemove",a.ontouchmove),a.onclick&&a.bind(document,"click",
a.onclick),a.opt.cursordragontouch&&(a.bind(a.cursor,"mousedown",a.onmousedown),a.bind(a.cursor,"mouseup",a.onmouseup),a.cursorh&&a.bind(a.cursorh,"mousedown",function(b){a.onmousedown(b,!0)}),a.cursorh&&a.bind(a.cursorh,"mouseup",a.onmouseup))):(a.bind(e.hasmousecapture?a.win:document,"mouseup",a.onmouseup),a.bind(document,"mousemove",a.onmousemove),a.onclick&&a.bind(document,"click",a.onclick),a.bind(a.cursor,"mousedown",a.onmousedown),a.bind(a.cursor,"mouseup",a.onmouseup),a.railh&&(a.bind(a.cursorh,
"mousedown",function(b){a.onmousedown(b,!0)}),a.bind(a.cursorh,"mouseup",a.onmouseup)),!a.ispage&&a.opt.enablescrollonselection&&(a.bind(a.win[0],"mousedown",a.onselectionstart),a.bind(document,"mouseup",a.onselectionend),a.bind(a.cursor,"mouseup",a.onselectionend),a.cursorh&&a.bind(a.cursorh,"mouseup",a.onselectionend),a.bind(document,"mousemove",a.onselectiondrag)),a.zoom&&(a.jqbind(a.zoom,"mouseenter",function(){a.canshowonmouseevent&&a.showCursor();a.rail.active=!0}),a.jqbind(a.zoom,"mouseleave",
function(){a.rail.active=!1;a.rail.drag||a.hideCursor()})));a.opt.enablemousewheel&&(a.isiframe||a.bind(e.isie&&a.ispage?document:a.win,"mousewheel",a.onmousewheel),a.bind(a.rail,"mousewheel",a.onmousewheel),a.railh&&a.bind(a.railh,"mousewheel",a.onmousewheelhr));a.ispage||e.cantouch||/HTML|^BODY/.test(a.win[0].nodeName)||(a.win.attr("tabindex")||a.win.attr({tabindex:N++}),a.jqbind(a.win,"focus",function(b){y=a.getTarget(b).id||!0;a.hasfocus=!0;a.canshowonmouseevent&&a.noticeCursor()}),a.jqbind(a.win,
"blur",function(b){y=!1;a.hasfocus=!1}),a.jqbind(a.win,"mouseenter",function(b){D=a.getTarget(b).id||!0;a.hasmousefocus=!0;a.canshowonmouseevent&&a.noticeCursor()}),a.jqbind(a.win,"mouseleave",function(){D=!1;a.hasmousefocus=!1;a.rail.drag||a.hideCursor()}))}a.onkeypress=function(b){if(a.railslocked&&0==a.page.maxh)return!0;b=b?b:window.e;var c=a.getTarget(b);if(c&&/INPUT|TEXTAREA|SELECT|OPTION/.test(c.nodeName)&&(!c.getAttribute("type")&&!c.type||!/submit|button|cancel/i.tp)||f(c).attr("contenteditable"))return!0;
if(a.hasfocus||a.hasmousefocus&&!y||a.ispage&&!y&&!D){c=b.keyCode;if(a.railslocked&&27!=c)return a.cancelEvent(b);var g=b.ctrlKey||!1,d=b.shiftKey||!1,e=!1;switch(c){case 38:case 63233:a.doScrollBy(72);e=!0;break;case 40:case 63235:a.doScrollBy(-72);e=!0;break;case 37:case 63232:a.railh&&(g?a.doScrollLeft(0):a.doScrollLeftBy(72),e=!0);break;case 39:case 63234:a.railh&&(g?a.doScrollLeft(a.page.maxw):a.doScrollLeftBy(-72),e=!0);break;case 33:case 63276:a.doScrollBy(a.view.h);e=!0;break;case 34:case 63277:a.doScrollBy(-a.view.h);
e=!0;break;case 36:case 63273:a.railh&&g?a.doScrollPos(0,0):a.doScrollTo(0);e=!0;break;case 35:case 63275:a.railh&&g?a.doScrollPos(a.page.maxw,a.page.maxh):a.doScrollTo(a.page.maxh);e=!0;break;case 32:a.opt.spacebarenabled&&(d?a.doScrollBy(a.view.h):a.doScrollBy(-a.view.h),e=!0);break;case 27:a.zoomactive&&(a.doZoom(),e=!0)}if(e)return a.cancelEvent(b)}};a.opt.enablekeyboard&&a.bind(document,e.isopera&&!e.isopera12?"keypress":"keydown",a.onkeypress);a.bind(document,"keydown",function(b){b.ctrlKey&&
(a.wheelprevented=!0)});a.bind(document,"keyup",function(b){b.ctrlKey||(a.wheelprevented=!1)});a.bind(window,"blur",function(b){a.wheelprevented=!1});a.bind(window,"resize",a.lazyResize);a.bind(window,"orientationchange",a.lazyResize);a.bind(window,"load",a.lazyResize);if(e.ischrome&&!a.ispage&&!a.haswrapper){var r=a.win.attr("style"),c=parseFloat(a.win.css("width"))+1;a.win.css("width",c);a.synched("chromefix",function(){a.win.attr("style",r)})}a.onAttributeChange=function(b){a.lazyResize(a.isieold?
250:30)};!1!==v&&(a.observerbody=new v(function(b){b.forEach(function(b){if("attributes"==b.type)return f("body").hasClass("modal-open")?a.hide():a.show()});if(document.body.scrollHeight!=a.page.maxh)return a.lazyResize(30)}),a.observerbody.observe(document.body,{childList:!0,subtree:!0,characterData:!1,attributes:!0,attributeFilter:["class"]}));a.ispage||a.haswrapper||(!1!==v?(a.observer=new v(function(b){b.forEach(a.onAttributeChange)}),a.observer.observe(a.win[0],{childList:!0,characterData:!1,
attributes:!0,subtree:!1}),a.observerremover=new v(function(b){b.forEach(function(b){if(0<b.removedNodes.length)for(var c in b.removedNodes)if(a&&b.removedNodes[c]==a.win[0])return a.remove()})}),a.observerremover.observe(a.win[0].parentNode,{childList:!0,characterData:!1,attributes:!1,subtree:!1})):(a.bind(a.win,e.isie&&!e.isie9?"propertychange":"DOMAttrModified",a.onAttributeChange),e.isie9&&a.win[0].attachEvent("onpropertychange",a.onAttributeChange),a.bind(a.win,"DOMNodeRemoved",function(b){b.target==
a.win[0]&&a.remove()})));!a.ispage&&a.opt.boxzoom&&a.bind(window,"resize",a.resizeZoom);a.istextarea&&a.bind(a.win,"mouseup",a.lazyResize);a.lazyResize(30)}if("IFRAME"==this.doc[0].nodeName){var M=function(){a.iframexd=!1;var b;try{b="contentDocument"in this?this.contentDocument:this.contentWindow.document}catch(c){a.iframexd=!0,b=!1}if(a.iframexd)return"console"in window&&console.log("NiceScroll error: policy restriced iframe"),!0;a.forcescreen=!0;a.isiframe&&(a.iframe={doc:f(b),html:a.doc.contents().find("html")[0],
body:a.doc.contents().find("body")[0]},a.getContentSize=function(){return{w:Math.max(a.iframe.html.scrollWidth,a.iframe.body.scrollWidth),h:Math.max(a.iframe.html.scrollHeight,a.iframe.body.scrollHeight)}},a.docscroll=f(a.iframe.body));if(!e.isios&&a.opt.iframeautoresize&&!a.isiframe){a.win.scrollTop(0);a.doc.height("");var g=Math.max(b.getElementsByTagName("html")[0].scrollHeight,b.body.scrollHeight);a.doc.height(g)}a.lazyResize(30);e.isie7&&a.css(f(a.iframe.html),{"overflow-y":"hidden"});a.css(f(a.iframe.body),
{"overflow-y":"hidden"});e.isios&&a.haswrapper&&a.css(f(b.body),{"-webkit-transform":"translate3d(0,0,0)"});"contentWindow"in this?a.bind(this.contentWindow,"scroll",a.onscroll):a.bind(b,"scroll",a.onscroll);a.opt.enablemousewheel&&a.bind(b,"mousewheel",a.onmousewheel);a.opt.enablekeyboard&&a.bind(b,e.isopera?"keypress":"keydown",a.onkeypress);if(e.cantouch||a.opt.touchbehavior)a.bind(b,"mousedown",a.ontouchstart),a.bind(b,"mousemove",function(b){return a.ontouchmove(b,!0)}),a.opt.grabcursorenabled&&
e.cursorgrabvalue&&a.css(f(b.body),{cursor:e.cursorgrabvalue});a.bind(b,"mouseup",a.ontouchend);a.zoom&&(a.opt.dblclickzoom&&a.bind(b,"dblclick",a.doZoom),a.ongesturezoom&&a.bind(b,"gestureend",a.ongesturezoom))};this.doc[0].readyState&&"complete"==this.doc[0].readyState&&setTimeout(function(){M.call(a.doc[0],!1)},500);a.bind(this.doc,"load",M)}};this.showCursor=function(b,c){a.cursortimeout&&(clearTimeout(a.cursortimeout),a.cursortimeout=0);if(a.rail){a.autohidedom&&(a.autohidedom.stop().css({opacity:a.opt.cursoropacitymax}),
a.cursoractive=!0);a.rail.drag&&1==a.rail.drag.pt||("undefined"!=typeof b&&!1!==b&&(a.scroll.y=Math.round(1*b/a.scrollratio.y)),"undefined"!=typeof c&&(a.scroll.x=Math.round(1*c/a.scrollratio.x)));a.cursor.css({height:a.cursorheight,top:a.scroll.y});if(a.cursorh){var d=a.hasreversehr?a.scrollvaluemaxw-a.scroll.x:a.scroll.x;!a.rail.align&&a.rail.visibility?a.cursorh.css({width:a.cursorwidth,left:d+a.rail.width}):a.cursorh.css({width:a.cursorwidth,left:d});a.cursoractive=!0}a.zoom&&a.zoom.stop().css({opacity:a.opt.cursoropacitymax})}};
this.hideCursor=function(b){a.cursortimeout||!a.rail||!a.autohidedom||a.hasmousefocus&&"leave"==a.opt.autohidemode||(a.cursortimeout=setTimeout(function(){a.rail.active&&a.showonmouseevent||(a.autohidedom.stop().animate({opacity:a.opt.cursoropacitymin}),a.zoom&&a.zoom.stop().animate({opacity:a.opt.cursoropacitymin}),a.cursoractive=!1);a.cursortimeout=0},b||a.opt.hidecursordelay))};this.noticeCursor=function(b,c,d){a.showCursor(c,d);a.rail.active||a.hideCursor(b)};this.getContentSize=a.ispage?function(){return{w:Math.max(document.body.scrollWidth,
document.documentElement.scrollWidth),h:Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)}}:a.haswrapper?function(){return{w:a.doc.outerWidth()+parseInt(a.win.css("paddingLeft"))+parseInt(a.win.css("paddingRight")),h:a.doc.outerHeight()+parseInt(a.win.css("paddingTop"))+parseInt(a.win.css("paddingBottom"))}}:function(){return{w:a.docscroll[0].scrollWidth,h:a.docscroll[0].scrollHeight}};this.onResize=function(b,c){if(!a||!a.win)return!1;if(!a.haswrapper&&!a.ispage){if("none"==
a.win.css("display"))return a.visibility&&a.hideRail().hideRailHr(),!1;a.hidden||a.visibility||a.showRail().showRailHr()}var d=a.page.maxh,e=a.page.maxw,f=a.view.h,h=a.view.w;a.view={w:a.ispage?a.win.width():parseInt(a.win[0].clientWidth),h:a.ispage?a.win.height():parseInt(a.win[0].clientHeight)};a.page=c?c:a.getContentSize();a.page.maxh=Math.max(0,a.page.h-a.view.h);a.page.maxw=Math.max(0,a.page.w-a.view.w);if(a.page.maxh==d&&a.page.maxw==e&&a.view.w==h&&a.view.h==f){if(a.ispage)return a;d=a.win.offset();
if(a.lastposition&&(e=a.lastposition,e.top==d.top&&e.left==d.left))return a;a.lastposition=d}0==a.page.maxh?(a.hideRail(),a.scrollvaluemax=0,a.scroll.y=0,a.scrollratio.y=0,a.cursorheight=0,a.setScrollTop(0),a.rail.scrollable=!1):(a.page.maxh-=a.opt.railpadding.top+a.opt.railpadding.bottom,a.rail.scrollable=!0);0==a.page.maxw?(a.hideRailHr(),a.scrollvaluemaxw=0,a.scroll.x=0,a.scrollratio.x=0,a.cursorwidth=0,a.setScrollLeft(0),a.railh.scrollable=!1):(a.page.maxw-=a.opt.railpadding.left+a.opt.railpadding.right,
a.railh.scrollable=!0);a.railslocked=a.locked||0==a.page.maxh&&0==a.page.maxw;if(a.railslocked)return a.ispage||a.updateScrollBar(a.view),!1;a.hidden||a.visibility?a.hidden||a.railh.visibility||a.showRailHr():a.showRail().showRailHr();a.istextarea&&a.win.css("resize")&&"none"!=a.win.css("resize")&&(a.view.h-=20);a.cursorheight=Math.min(a.view.h,Math.round(a.view.h/a.page.h*a.view.h));a.cursorheight=a.opt.cursorfixedheight?a.opt.cursorfixedheight:Math.max(a.opt.cursorminheight,a.cursorheight);a.cursorwidth=
Math.min(a.view.w,Math.round(a.view.w/a.page.w*a.view.w));a.cursorwidth=a.opt.cursorfixedheight?a.opt.cursorfixedheight:Math.max(a.opt.cursorminheight,a.cursorwidth);a.scrollvaluemax=a.view.h-a.cursorheight-a.cursor.hborder-(a.opt.railpadding.top+a.opt.railpadding.bottom);a.railh&&(a.railh.width=0<a.page.maxh?a.view.w-a.rail.width:a.view.w,a.scrollvaluemaxw=a.railh.width-a.cursorwidth-a.cursorh.wborder-(a.opt.railpadding.left+a.opt.railpadding.right));a.ispage||a.updateScrollBar(a.view);a.scrollratio=
{x:a.page.maxw/a.scrollvaluemaxw,y:a.page.maxh/a.scrollvaluemax};a.getScrollTop()>a.page.maxh?a.doScrollTop(a.page.maxh):(a.scroll.y=Math.round(a.getScrollTop()*(1/a.scrollratio.y)),a.scroll.x=Math.round(a.getScrollLeft()*(1/a.scrollratio.x)),a.cursoractive&&a.noticeCursor());a.scroll.y&&0==a.getScrollTop()&&a.doScrollTo(Math.floor(a.scroll.y*a.scrollratio.y));return a};this.resize=a.onResize;this.lazyResize=function(b){b=isNaN(b)?30:b;a.debounced("resize",a.resize,b);return a};this.jqbind=function(b,
c,d){a.events.push({e:b,n:c,f:d,q:!0});f(b).bind(c,d)};this.bind=function(b,c,d,f){var h="jquery"in b?b[0]:b;"mousewheel"==c?window.addEventListener||"onwheel"in document?a._bind(h,"wheel",d,f||!1):(b="undefined"!=typeof document.onmousewheel?"mousewheel":"DOMMouseScroll",n(h,b,d,f||!1),"DOMMouseScroll"==b&&n(h,"MozMousePixelScroll",d,f||!1)):h.addEventListener?(e.cantouch&&/mouseup|mousedown|mousemove/.test(c)&&a._bind(h,"mousedown"==c?"touchstart":"mouseup"==c?"touchend":"touchmove",function(a){if(a.touches){if(2>
a.touches.length){var b=a.touches.length?a.touches[0]:a;b.original=a;d.call(this,b)}}else a.changedTouches&&(b=a.changedTouches[0],b.original=a,d.call(this,b))},f||!1),a._bind(h,c,d,f||!1),e.cantouch&&"mouseup"==c&&a._bind(h,"touchcancel",d,f||!1)):a._bind(h,c,function(b){(b=b||window.event||!1)&&b.srcElement&&(b.target=b.srcElement);"pageY"in b||(b.pageX=b.clientX+document.documentElement.scrollLeft,b.pageY=b.clientY+document.documentElement.scrollTop);return!1===d.call(h,b)||!1===f?a.cancelEvent(b):
!0})};e.haseventlistener?(this._bind=function(b,c,d,e){a.events.push({e:b,n:c,f:d,b:e,q:!1});b.addEventListener(c,d,e||!1)},this.cancelEvent=function(a){if(!a)return!1;a=a.original?a.original:a;a.preventDefault();a.stopPropagation();a.preventManipulation&&a.preventManipulation();return!1},this.stopPropagation=function(a){if(!a)return!1;a=a.original?a.original:a;a.stopPropagation();return!1},this._unbind=function(a,c,d,e){a.removeEventListener(c,d,e)}):(this._bind=function(b,c,d,e){a.events.push({e:b,
n:c,f:d,b:e,q:!1});b.attachEvent?b.attachEvent("on"+c,d):b["on"+c]=d},this.cancelEvent=function(a){a=window.event||!1;if(!a)return!1;a.cancelBubble=!0;a.cancel=!0;return a.returnValue=!1},this.stopPropagation=function(a){a=window.event||!1;if(!a)return!1;a.cancelBubble=!0;return!1},this._unbind=function(a,c,d,e){a.detachEvent?a.detachEvent("on"+c,d):a["on"+c]=!1});this.unbindAll=function(){for(var b=0;b<a.events.length;b++){var c=a.events[b];c.q?c.e.unbind(c.n,c.f):a._unbind(c.e,c.n,c.f,c.b)}};this.showRail=
function(){0==a.page.maxh||!a.ispage&&"none"==a.win.css("display")||(a.visibility=!0,a.rail.visibility=!0,a.rail.css("display","block"));return a};this.showRailHr=function(){if(!a.railh)return a;0==a.page.maxw||!a.ispage&&"none"==a.win.css("display")||(a.railh.visibility=!0,a.railh.css("display","block"));return a};this.hideRail=function(){a.visibility=!1;a.rail.visibility=!1;a.rail.css("display","none");return a};this.hideRailHr=function(){if(!a.railh)return a;a.railh.visibility=!1;a.railh.css("display",
"none");return a};this.show=function(){a.hidden=!1;a.railslocked=!1;return a.showRail().showRailHr()};this.hide=function(){a.hidden=!0;a.railslocked=!0;return a.hideRail().hideRailHr()};this.toggle=function(){return a.hidden?a.show():a.hide()};this.remove=function(){a.stop();a.cursortimeout&&clearTimeout(a.cursortimeout);a.doZoomOut();a.unbindAll();e.isie9&&a.win[0].detachEvent("onpropertychange",a.onAttributeChange);!1!==a.observer&&a.observer.disconnect();!1!==a.observerremover&&a.observerremover.disconnect();
!1!==a.observerbody&&a.observerbody.disconnect();a.events=null;a.cursor&&a.cursor.remove();a.cursorh&&a.cursorh.remove();a.rail&&a.rail.remove();a.railh&&a.railh.remove();a.zoom&&a.zoom.remove();for(var b=0;b<a.saved.css.length;b++){var c=a.saved.css[b];c[0].css(c[1],"undefined"==typeof c[2]?"":c[2])}a.saved=!1;a.me.data("__nicescroll","");var d=f.nicescroll;d.each(function(b){if(this&&this.id===a.id){delete d[b];for(var c=++b;c<d.length;c++,b++)d[b]=d[c];d.length--;d.length&&delete d[d.length]}});
for(var h in a)a[h]=null,delete a[h];a=null};this.scrollstart=function(b){this.onscrollstart=b;return a};this.scrollend=function(b){this.onscrollend=b;return a};this.scrollcancel=function(b){this.onscrollcancel=b;return a};this.zoomin=function(b){this.onzoomin=b;return a};this.zoomout=function(b){this.onzoomout=b;return a};this.isScrollable=function(a){a=a.target?a.target:a;if("OPTION"==a.nodeName)return!0;for(;a&&1==a.nodeType&&!/^BODY|HTML/.test(a.nodeName);){var c=f(a),c=c.css("overflowY")||c.css("overflowX")||
c.css("overflow")||"";if(/scroll|auto/.test(c))return a.clientHeight!=a.scrollHeight;a=a.parentNode?a.parentNode:!1}return!1};this.getViewport=function(a){for(a=a&&a.parentNode?a.parentNode:!1;a&&1==a.nodeType&&!/^BODY|HTML/.test(a.nodeName);){var c=f(a);if(/fixed|absolute/.test(c.css("position")))return c;var d=c.css("overflowY")||c.css("overflowX")||c.css("overflow")||"";if(/scroll|auto/.test(d)&&a.clientHeight!=a.scrollHeight||0<c.getNiceScroll().length)return c;a=a.parentNode?a.parentNode:!1}return!1};
this.triggerScrollEnd=function(){if(a.onscrollend){var b=a.getScrollLeft(),c=a.getScrollTop();a.onscrollend.call(a,{type:"scrollend",current:{x:b,y:c},end:{x:b,y:c}})}};this.onmousewheel=function(b){if(!a.wheelprevented){if(a.railslocked)return a.debounced("checkunlock",a.resize,250),!0;if(a.rail.drag)return a.cancelEvent(b);"auto"==a.opt.oneaxismousemode&&0!=b.deltaX&&(a.opt.oneaxismousemode=!1);if(a.opt.oneaxismousemode&&0==b.deltaX&&!a.rail.scrollable)return a.railh&&a.railh.scrollable?a.onmousewheelhr(b):
!0;var c=+new Date,d=!1;a.opt.preservenativescrolling&&a.checkarea+600<c&&(a.nativescrollingarea=a.isScrollable(b),d=!0);a.checkarea=c;if(a.nativescrollingarea)return!0;if(b=p(b,!1,d))a.checkarea=0;return b}};this.onmousewheelhr=function(b){if(!a.wheelprevented){if(a.railslocked||!a.railh.scrollable)return!0;if(a.rail.drag)return a.cancelEvent(b);var c=+new Date,d=!1;a.opt.preservenativescrolling&&a.checkarea+600<c&&(a.nativescrollingarea=a.isScrollable(b),d=!0);a.checkarea=c;return a.nativescrollingarea?
!0:a.railslocked?a.cancelEvent(b):p(b,!0,d)}};this.stop=function(){a.cancelScroll();a.scrollmon&&a.scrollmon.stop();a.cursorfreezed=!1;a.scroll.y=Math.round(a.getScrollTop()*(1/a.scrollratio.y));a.noticeCursor();return a};this.getTransitionSpeed=function(b){var c=Math.round(10*a.opt.scrollspeed);b=Math.min(c,Math.round(b/20*a.opt.scrollspeed));return 20<b?b:0};a.opt.smoothscroll?a.ishwscroll&&e.hastransition&&a.opt.usetransition&&a.opt.smoothscroll?(this.prepareTransition=function(b,c){var d=c?20<
b?b:0:a.getTransitionSpeed(b),f=d?e.prefixstyle+"transform "+d+"ms ease-out":"";a.lasttransitionstyle&&a.lasttransitionstyle==f||(a.lasttransitionstyle=f,a.doc.css(e.transitionstyle,f));return d},this.doScrollLeft=function(b,c){var d=a.scrollrunning?a.newscrolly:a.getScrollTop();a.doScrollPos(b,d,c)},this.doScrollTop=function(b,c){var d=a.scrollrunning?a.newscrollx:a.getScrollLeft();a.doScrollPos(d,b,c)},this.doScrollPos=function(b,c,d){var f=a.getScrollTop(),h=a.getScrollLeft();(0>(a.newscrolly-
f)*(c-f)||0>(a.newscrollx-h)*(b-h))&&a.cancelScroll();0==a.opt.bouncescroll&&(0>c?c=0:c>a.page.maxh&&(c=a.page.maxh),0>b?b=0:b>a.page.maxw&&(b=a.page.maxw));if(a.scrollrunning&&b==a.newscrollx&&c==a.newscrolly)return!1;a.newscrolly=c;a.newscrollx=b;a.newscrollspeed=d||!1;if(a.timer)return!1;a.timer=setTimeout(function(){var d=a.getScrollTop(),f=a.getScrollLeft(),h,k;h=b-f;k=c-d;h=Math.round(Math.sqrt(Math.pow(h,2)+Math.pow(k,2)));h=a.newscrollspeed&&1<a.newscrollspeed?a.newscrollspeed:a.getTransitionSpeed(h);
a.newscrollspeed&&1>=a.newscrollspeed&&(h*=a.newscrollspeed);a.prepareTransition(h,!0);a.timerscroll&&a.timerscroll.tm&&clearInterval(a.timerscroll.tm);0<h&&(!a.scrollrunning&&a.onscrollstart&&a.onscrollstart.call(a,{type:"scrollstart",current:{x:f,y:d},request:{x:b,y:c},end:{x:a.newscrollx,y:a.newscrolly},speed:h}),e.transitionend?a.scrollendtrapped||(a.scrollendtrapped=!0,a.bind(a.doc,e.transitionend,a.onScrollTransitionEnd,!1)):(a.scrollendtrapped&&clearTimeout(a.scrollendtrapped),a.scrollendtrapped=
setTimeout(a.onScrollTransitionEnd,h)),a.timerscroll={bz:new A(d,a.newscrolly,h,0,0,.58,1),bh:new A(f,a.newscrollx,h,0,0,.58,1)},a.cursorfreezed||(a.timerscroll.tm=setInterval(function(){a.showCursor(a.getScrollTop(),a.getScrollLeft())},60)));a.synched("doScroll-set",function(){a.timer=0;a.scrollendtrapped&&(a.scrollrunning=!0);a.setScrollTop(a.newscrolly);a.setScrollLeft(a.newscrollx);if(!a.scrollendtrapped)a.onScrollTransitionEnd()})},50)},this.cancelScroll=function(){if(!a.scrollendtrapped)return!0;
var b=a.getScrollTop(),c=a.getScrollLeft();a.scrollrunning=!1;e.transitionend||clearTimeout(e.transitionend);a.scrollendtrapped=!1;a._unbind(a.doc[0],e.transitionend,a.onScrollTransitionEnd);a.prepareTransition(0);a.setScrollTop(b);a.railh&&a.setScrollLeft(c);a.timerscroll&&a.timerscroll.tm&&clearInterval(a.timerscroll.tm);a.timerscroll=!1;a.cursorfreezed=!1;a.showCursor(b,c);return a},this.onScrollTransitionEnd=function(){a.scrollendtrapped&&a._unbind(a.doc[0],e.transitionend,a.onScrollTransitionEnd);
a.scrollendtrapped=!1;a.prepareTransition(0);a.timerscroll&&a.timerscroll.tm&&clearInterval(a.timerscroll.tm);a.timerscroll=!1;var b=a.getScrollTop(),c=a.getScrollLeft();a.setScrollTop(b);a.railh&&a.setScrollLeft(c);a.noticeCursor(!1,b,c);a.cursorfreezed=!1;0>b?b=0:b>a.page.maxh&&(b=a.page.maxh);0>c?c=0:c>a.page.maxw&&(c=a.page.maxw);if(b!=a.newscrolly||c!=a.newscrollx)return a.doScrollPos(c,b,a.opt.snapbackspeed);a.onscrollend&&a.scrollrunning&&a.triggerScrollEnd();a.scrollrunning=!1}):(this.doScrollLeft=
function(b,c){var d=a.scrollrunning?a.newscrolly:a.getScrollTop();a.doScrollPos(b,d,c)},this.doScrollTop=function(b,c){var d=a.scrollrunning?a.newscrollx:a.getScrollLeft();a.doScrollPos(d,b,c)},this.doScrollPos=function(b,c,d){function e(){if(a.cancelAnimationFrame)return!0;a.scrollrunning=!0;if(n=1-n)return a.timer=s(e)||1;var b=0,c,d,g=d=a.getScrollTop();if(a.dst.ay){g=a.bzscroll?a.dst.py+a.bzscroll.getNow()*a.dst.ay:a.newscrolly;c=g-d;if(0>c&&g<a.newscrolly||0<c&&g>a.newscrolly)g=a.newscrolly;
a.setScrollTop(g);g==a.newscrolly&&(b=1)}else b=1;d=c=a.getScrollLeft();if(a.dst.ax){d=a.bzscroll?a.dst.px+a.bzscroll.getNow()*a.dst.ax:a.newscrollx;c=d-c;if(0>c&&d<a.newscrollx||0<c&&d>a.newscrollx)d=a.newscrollx;a.setScrollLeft(d);d==a.newscrollx&&(b+=1)}else b+=1;2==b?(a.timer=0,a.cursorfreezed=!1,a.bzscroll=!1,a.scrollrunning=!1,0>g?g=0:g>a.page.maxh&&(g=a.page.maxh),0>d?d=0:d>a.page.maxw&&(d=a.page.maxw),d!=a.newscrollx||g!=a.newscrolly?a.doScrollPos(d,g):a.onscrollend&&a.triggerScrollEnd()):
a.timer=s(e)||1}c="undefined"==typeof c||!1===c?a.getScrollTop(!0):c;if(a.timer&&a.newscrolly==c&&a.newscrollx==b)return!0;a.timer&&t(a.timer);a.timer=0;var f=a.getScrollTop(),h=a.getScrollLeft();(0>(a.newscrolly-f)*(c-f)||0>(a.newscrollx-h)*(b-h))&&a.cancelScroll();a.newscrolly=c;a.newscrollx=b;a.bouncescroll&&a.rail.visibility||(0>a.newscrolly?a.newscrolly=0:a.newscrolly>a.page.maxh&&(a.newscrolly=a.page.maxh));a.bouncescroll&&a.railh.visibility||(0>a.newscrollx?a.newscrollx=0:a.newscrollx>a.page.maxw&&
(a.newscrollx=a.page.maxw));a.dst={};a.dst.x=b-h;a.dst.y=c-f;a.dst.px=h;a.dst.py=f;var k=Math.round(Math.sqrt(Math.pow(a.dst.x,2)+Math.pow(a.dst.y,2)));a.dst.ax=a.dst.x/k;a.dst.ay=a.dst.y/k;var l=0,m=k;0==a.dst.x?(l=f,m=c,a.dst.ay=1,a.dst.py=0):0==a.dst.y&&(l=h,m=b,a.dst.ax=1,a.dst.px=0);k=a.getTransitionSpeed(k);d&&1>=d&&(k*=d);a.bzscroll=0<k?a.bzscroll?a.bzscroll.update(m,k):new A(l,m,k,0,1,0,1):!1;if(!a.timer){(f==a.page.maxh&&c>=a.page.maxh||h==a.page.maxw&&b>=a.page.maxw)&&a.checkContentSize();
var n=1;a.cancelAnimationFrame=!1;a.timer=1;a.onscrollstart&&!a.scrollrunning&&a.onscrollstart.call(a,{type:"scrollstart",current:{x:h,y:f},request:{x:b,y:c},end:{x:a.newscrollx,y:a.newscrolly},speed:k});e();(f==a.page.maxh&&c>=f||h==a.page.maxw&&b>=h)&&a.checkContentSize();a.noticeCursor()}},this.cancelScroll=function(){a.timer&&t(a.timer);a.timer=0;a.bzscroll=!1;a.scrollrunning=!1;return a}):(this.doScrollLeft=function(b,c){var d=a.getScrollTop();a.doScrollPos(b,d,c)},this.doScrollTop=function(b,
c){var d=a.getScrollLeft();a.doScrollPos(d,b,c)},this.doScrollPos=function(b,c,d){var e=b>a.page.maxw?a.page.maxw:b;0>e&&(e=0);var f=c>a.page.maxh?a.page.maxh:c;0>f&&(f=0);a.synched("scroll",function(){a.setScrollTop(f);a.setScrollLeft(e)})},this.cancelScroll=function(){});this.doScrollBy=function(b,c){var d=0,d=c?Math.floor((a.scroll.y-b)*a.scrollratio.y):(a.timer?a.newscrolly:a.getScrollTop(!0))-b;if(a.bouncescroll){var e=Math.round(a.view.h/2);d<-e?d=-e:d>a.page.maxh+e&&(d=a.page.maxh+e)}a.cursorfreezed=
!1;e=a.getScrollTop(!0);if(0>d&&0>=e)return a.noticeCursor();if(d>a.page.maxh&&e>=a.page.maxh)return a.checkContentSize(),a.noticeCursor();a.doScrollTop(d)};this.doScrollLeftBy=function(b,c){var d=0,d=c?Math.floor((a.scroll.x-b)*a.scrollratio.x):(a.timer?a.newscrollx:a.getScrollLeft(!0))-b;if(a.bouncescroll){var e=Math.round(a.view.w/2);d<-e?d=-e:d>a.page.maxw+e&&(d=a.page.maxw+e)}a.cursorfreezed=!1;e=a.getScrollLeft(!0);if(0>d&&0>=e||d>a.page.maxw&&e>=a.page.maxw)return a.noticeCursor();a.doScrollLeft(d)};
this.doScrollTo=function(b,c){c&&Math.round(b*a.scrollratio.y);a.cursorfreezed=!1;a.doScrollTop(b)};this.checkContentSize=function(){var b=a.getContentSize();b.h==a.page.h&&b.w==a.page.w||a.resize(!1,b)};a.onscroll=function(b){a.rail.drag||a.cursorfreezed||a.synched("scroll",function(){a.scroll.y=Math.round(a.getScrollTop()*(1/a.scrollratio.y));a.railh&&(a.scroll.x=Math.round(a.getScrollLeft()*(1/a.scrollratio.x)));a.noticeCursor()})};a.bind(a.docscroll,"scroll",a.onscroll);this.doZoomIn=function(b){if(!a.zoomactive){a.zoomactive=
!0;a.zoomrestore={style:{}};var c="position top left zIndex backgroundColor marginTop marginBottom marginLeft marginRight".split(" "),d=a.win[0].style,h;for(h in c){var k=c[h];a.zoomrestore.style[k]="undefined"!=typeof d[k]?d[k]:""}a.zoomrestore.style.width=a.win.css("width");a.zoomrestore.style.height=a.win.css("height");a.zoomrestore.padding={w:a.win.outerWidth()-a.win.width(),h:a.win.outerHeight()-a.win.height()};e.isios4&&(a.zoomrestore.scrollTop=f(window).scrollTop(),f(window).scrollTop(0));
a.win.css({position:e.isios4?"absolute":"fixed",top:0,left:0,"z-index":x+100,margin:"0px"});c=a.win.css("backgroundColor");(""==c||/transparent|rgba\(0, 0, 0, 0\)|rgba\(0,0,0,0\)/.test(c))&&a.win.css("backgroundColor","#fff");a.rail.css({"z-index":x+101});a.zoom.css({"z-index":x+102});a.zoom.css("backgroundPosition","0px -18px");a.resizeZoom();a.onzoomin&&a.onzoomin.call(a);return a.cancelEvent(b)}};this.doZoomOut=function(b){if(a.zoomactive)return a.zoomactive=!1,a.win.css("margin",""),a.win.css(a.zoomrestore.style),
e.isios4&&f(window).scrollTop(a.zoomrestore.scrollTop),a.rail.css({"z-index":a.zindex}),a.zoom.css({"z-index":a.zindex}),a.zoomrestore=!1,a.zoom.css("backgroundPosition","0px 0px"),a.onResize(),a.onzoomout&&a.onzoomout.call(a),a.cancelEvent(b)};this.doZoom=function(b){return a.zoomactive?a.doZoomOut(b):a.doZoomIn(b)};this.resizeZoom=function(){if(a.zoomactive){var b=a.getScrollTop();a.win.css({width:f(window).width()-a.zoomrestore.padding.w+"px",height:f(window).height()-a.zoomrestore.padding.h+"px"});
a.onResize();a.setScrollTop(Math.min(a.page.maxh,b))}};this.init();f.nicescroll.push(this)},L=function(f){var c=this;this.nc=f;this.steptime=this.lasttime=this.speedy=this.speedx=this.lasty=this.lastx=0;this.snapy=this.snapx=!1;this.demuly=this.demulx=0;this.lastscrolly=this.lastscrollx=-1;this.timer=this.chky=this.chkx=0;this.time=function(){return+new Date};this.reset=function(f,k){c.stop();var d=c.time();c.steptime=0;c.lasttime=d;c.speedx=0;c.speedy=0;c.lastx=f;c.lasty=k;c.lastscrollx=-1;c.lastscrolly=
-1};this.update=function(f,k){var d=c.time();c.steptime=d-c.lasttime;c.lasttime=d;var d=k-c.lasty,n=f-c.lastx,p=c.nc.getScrollTop(),a=c.nc.getScrollLeft(),p=p+d,a=a+n;c.snapx=0>a||a>c.nc.page.maxw;c.snapy=0>p||p>c.nc.page.maxh;c.speedx=n;c.speedy=d;c.lastx=f;c.lasty=k};this.stop=function(){c.nc.unsynched("domomentum2d");c.timer&&clearTimeout(c.timer);c.timer=0;c.lastscrollx=-1;c.lastscrolly=-1};this.doSnapy=function(f,k){var d=!1;0>k?(k=0,d=!0):k>c.nc.page.maxh&&(k=c.nc.page.maxh,d=!0);0>f?(f=0,d=
!0):f>c.nc.page.maxw&&(f=c.nc.page.maxw,d=!0);d?c.nc.doScrollPos(f,k,c.nc.opt.snapbackspeed):c.nc.triggerScrollEnd()};this.doMomentum=function(f){var k=c.time(),d=f?k+f:c.lasttime;f=c.nc.getScrollLeft();var n=c.nc.getScrollTop(),p=c.nc.page.maxh,a=c.nc.page.maxw;c.speedx=0<a?Math.min(60,c.speedx):0;c.speedy=0<p?Math.min(60,c.speedy):0;d=d&&60>=k-d;if(0>n||n>p||0>f||f>a)d=!1;f=c.speedx&&d?c.speedx:!1;if(c.speedy&&d&&c.speedy||f){var s=Math.max(16,c.steptime);50<s&&(f=s/50,c.speedx*=f,c.speedy*=f,s=
50);c.demulxy=0;c.lastscrollx=c.nc.getScrollLeft();c.chkx=c.lastscrollx;c.lastscrolly=c.nc.getScrollTop();c.chky=c.lastscrolly;var e=c.lastscrollx,r=c.lastscrolly,t=function(){var d=600<c.time()-k?.04:.02;c.speedx&&(e=Math.floor(c.lastscrollx-c.speedx*(1-c.demulxy)),c.lastscrollx=e,0>e||e>a)&&(d=.1);c.speedy&&(r=Math.floor(c.lastscrolly-c.speedy*(1-c.demulxy)),c.lastscrolly=r,0>r||r>p)&&(d=.1);c.demulxy=Math.min(1,c.demulxy+d);c.nc.synched("domomentum2d",function(){c.speedx&&(c.nc.getScrollLeft()!=
c.chkx&&c.stop(),c.chkx=e,c.nc.setScrollLeft(e));c.speedy&&(c.nc.getScrollTop()!=c.chky&&c.stop(),c.chky=r,c.nc.setScrollTop(r));c.timer||(c.nc.hideCursor(),c.doSnapy(e,r))});1>c.demulxy?c.timer=setTimeout(t,s):(c.stop(),c.nc.hideCursor(),c.doSnapy(e,r))};t()}else c.doSnapy(c.nc.getScrollLeft(),c.nc.getScrollTop())}},w=f.fn.scrollTop;f.cssHooks.pageYOffset={get:function(k,c,h){return(c=f.data(k,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollTop():w.call(k)},set:function(k,c){var h=f.data(k,"__nicescroll")||
!1;h&&h.ishwscroll?h.setScrollTop(parseInt(c)):w.call(k,c);return this}};f.fn.scrollTop=function(k){if("undefined"==typeof k){var c=this[0]?f.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollTop():w.call(this)}return this.each(function(){var c=f.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollTop(parseInt(k)):w.call(f(this),k)})};var B=f.fn.scrollLeft;f.cssHooks.pageXOffset={get:function(k,c,h){return(c=f.data(k,"__nicescroll")||!1)&&c.ishwscroll?c.getScrollLeft():B.call(k)},
set:function(k,c){var h=f.data(k,"__nicescroll")||!1;h&&h.ishwscroll?h.setScrollLeft(parseInt(c)):B.call(k,c);return this}};f.fn.scrollLeft=function(k){if("undefined"==typeof k){var c=this[0]?f.data(this[0],"__nicescroll")||!1:!1;return c&&c.ishwscroll?c.getScrollLeft():B.call(this)}return this.each(function(){var c=f.data(this,"__nicescroll")||!1;c&&c.ishwscroll?c.setScrollLeft(parseInt(k)):B.call(f(this),k)})};var C=function(k){var c=this;this.length=0;this.name="nicescrollarray";this.each=function(d){for(var f=
0,h=0;f<c.length;f++)d.call(c[f],h++);return c};this.push=function(d){c[c.length]=d;c.length++};this.eq=function(d){return c[d]};if(k)for(var h=0;h<k.length;h++){var m=f.data(k[h],"__nicescroll")||!1;m&&(this[this.length]=m,this.length++)}return this};(function(f,c,h){for(var m=0;m<c.length;m++)h(f,c[m])})(C.prototype,"show hide toggle onResize resize remove stop doScrollPos".split(" "),function(f,c){f[c]=function(){var f=arguments;return this.each(function(){this[c].apply(this,f)})}});f.fn.getNiceScroll=
function(k){return"undefined"==typeof k?new C(this):this[k]&&f.data(this[k],"__nicescroll")||!1};f.extend(f.expr[":"],{nicescroll:function(k){return f.data(k,"__nicescroll")?!0:!1}});f.fn.niceScroll=function(k,c){"undefined"!=typeof c||"object"!=typeof k||"jquery"in k||(c=k,k=!1);c=f.extend({},c);var h=new C;"undefined"==typeof c&&(c={});k&&(c.doc=f(k),c.win=f(this));var m=!("doc"in c);m||"win"in c||(c.win=f(this));this.each(function(){var d=f(this).data("__nicescroll")||!1;d||(c.doc=m?f(this):c.doc,
d=new R(c,f(this)),f(this).data("__nicescroll",d));h.push(d)});return 1==h.length?h[0]:h};window.NiceScroll={getjQuery:function(){return f}};f.nicescroll||(f.nicescroll=new C,f.nicescroll.options=I)});

File diff suppressed because one or more lines are too long

1
src/assets/vue.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

42
src/main.ts Normal file
View File

@ -0,0 +1,42 @@
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css'
import '@/styles/index.scss'
import '@/assets/css/styles.css'
import '@/assets/css/all.min.css'
import pinia from './store'
import * as echarts from 'echarts';
import router, { loadAndRegisterRoutes } from './router';
//@ts-expect-error忽略当前文件ts类型的检测否则有红色提示(打包会失败)
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
const app = createApp(App)
app.config.globalProperties.$echarts = echarts
app.use(ElementPlus, {
locale: zhCn
})
app.use(pinia);
// 在注册路由之前先加载并注册动态路由
// 这样 Vue Router 在创建时就能匹配到所有路由
loadAndRegisterRoutes()
.then(() => {
// 路由加载完成后再注册 router
app.use(router);
// 等待路由准备就绪
return router.isReady();
})
.then(() => {
app.mount('#app');
})
.catch((error) => {
console.error('Failed to load routes:', error);
// 即使路由加载失败,也要注册路由和挂载应用
// 路由守卫会处理后续的路由加载
app.use(router);
app.mount('#app');
});

70
src/router/index.ts Normal file
View File

@ -0,0 +1,70 @@
import { createRouter, createWebHistory } from 'vue-router';
import { constantRoute, registerDynamicRoutes } from './routes';
import { getHeadMenu } from '@/api/index';
// 先创建路由,但不立即匹配
const router = createRouter({
history: createWebHistory(),
routes: constantRoute,
// 延迟路由匹配,等待动态路由注册完成
strict: false,
});
// 在应用启动时加载菜单并注册路由
let routesLoaded = false;
let routesLoadingPromise: Promise<void> | null = null;
export async function loadAndRegisterRoutes() {
// 如果已经加载过,直接返回
if (routesLoaded) {
return;
}
// 如果正在加载,等待加载完成
if (routesLoadingPromise) {
return routesLoadingPromise;
}
// 开始加载
routesLoadingPromise = (async () => {
try {
const response = await getHeadMenu();
if (response.code === 200 && response.data) {
registerDynamicRoutes(router, response.data);
routesLoaded = true;
}
} catch (error) {
console.error('Failed to load menus and register routes:', error);
} finally {
routesLoadingPromise = null;
}
})();
return routesLoadingPromise;
}
// 路由守卫:确保路由已加载
router.beforeEach(async (to, _from, next) => {
// 如果路由还未加载,先加载路由
if (!routesLoaded) {
if (!routesLoadingPromise) {
routesLoadingPromise = loadAndRegisterRoutes();
}
// 等待路由加载完成
await routesLoadingPromise;
// 路由加载完成后,如果当前路径不匹配,尝试重新匹配
const matched = router.resolve(to.path).matched;
if (matched.length === 0 && to.path !== '/404') {
// 路由已加载但当前路径不匹配,可能是通配符路由
// 继续导航,让通配符路由处理
next();
return;
}
}
// 路由已加载,继续导航
next();
});
export default router;

143
src/router/routes.ts Normal file
View File

@ -0,0 +1,143 @@
import { createComponentLoader } from '@/utils/pathResolver'
// 对外暴漏配置路由,常量路由
export const constantRoute = [
{
path: '/',
component: () => import('@/views/home/index.vue'),
name: '首页',
meta: {
title: '首页',
hidden: false,
icon: 'HomeFilled',
},
},
{
path: '/404',
component: () => import('@/views/404/index.vue'),
name: '404',
meta: {
title: '404',
hidden: true,
icon: 'DocumentDelete',
},
},
{
path: '/newscenter/kingdeeNews/detail/:id',
component: () => import('@/views/components/articleDetail.vue'),
name: 'kingdeeNewsDetail',
meta: {
title: '金蝶新闻详情',
hidden: true,
},
},
{
path: '/newscenter/companyNews/detail/:id',
component: () => import('@/views/components/articleDetail.vue'),
name: 'companyNewsDetail',
meta: {
title: '企业新闻详情',
hidden: true,
},
},
]
// 动态路由注册函数
export function registerDynamicRoutes(router: any, menus: any[]) {
if (!menus || menus.length === 0) return
// 统一处理菜单路径大小写
const normalizeMenuPaths = (menus: any[]) => {
return menus.map(menu => {
const normalizedMenu = { ...menu }
// 将路径中的 /newscenter/ 替换为 /newsCenter/
if (normalizedMenu.path) {
normalizedMenu.path = normalizedMenu.path.replace(/\/newscenter\//g, '/newsCenter/')
}
// 递归处理子菜单
if (normalizedMenu.children && normalizedMenu.children.length > 0) {
normalizedMenu.children = normalizeMenuPaths(normalizedMenu.children)
}
return normalizedMenu
})
}
// 先规范化菜单路径
const normalizedMenus = normalizeMenuPaths(menus)
// 收集所有需要注册的路由
const routesToAdd: any[] = []
// 递归处理菜单,收集路由
const processMenu = (menu: any) => {
// type 2: 页面 - 根据 component_path 加载组件
if (menu.type === 2 && menu.path && menu.component_path) {
const path = menu.path
// 检查路由是否已存在
const existingRoute = router.getRoutes().find((r: any) => r.path === path)
if (!existingRoute) {
try {
// 使用 pathResolver 来解析 component_path
// component_path 可能的格式:
// 1. /views/newsCenter/companyNews/index.vue
// 2. views/newsCenter/companyNews/index.vue
// 3. newsCenter/companyNews/index.vue
const componentLoader = createComponentLoader(menu.component_path)
if (!componentLoader) {
console.error(`Failed to create component loader for: ${menu.component_path}`)
return
}
routesToAdd.push({
path: path,
name: `menu_${menu.id}`,
component: componentLoader,
meta: {
title: menu.title,
menuId: menu.id,
menuType: menu.type,
},
})
} catch (error) {
console.error(`Failed to prepare route for path ${path}, component_path: ${menu.component_path}`, error)
}
}
}
// type 4: 单页 - 使用通配符路由处理,不需要单独注册
// 递归处理子菜单
if (menu.children && menu.children.length > 0) {
menu.children.forEach((child: any) => processMenu(child))
}
}
// 处理所有菜单
normalizedMenus.forEach((menu) => processMenu(menu))
// 先移除通配符路由(如果存在),以便重新添加
const catchAllRoute = router.getRoutes().find((r: any) => r.path === '/:pathMatch(.*)*')
if (catchAllRoute) {
router.removeRoute('OnePage')
}
// 注册 type 2 的路由(必须在通配符路由之前)
routesToAdd.forEach((route) => {
router.addRoute(route)
})
// 最后添加通配符路由(用于单页和其他未匹配的路径)
const catchAllExists = router.getRoutes().find((r: any) => r.path === '/:pathMatch(.*)*')
if (!catchAllExists) {
router.addRoute({
path: '/:pathMatch(.*)*',
component: () => import('@/views/onepage/index.vue'),
name: 'OnePage',
meta: {
title: '单页',
hidden: true,
},
})
}
}

6
src/store/index.ts Normal file
View File

@ -0,0 +1,6 @@
//仓库大仓库
import { createPinia } from 'pinia'
//创建大仓库
const pinia = createPinia()
//对外暴露:入口文件需要安装仓库
export default pinia

15
src/store/modules/user.ts Normal file
View File

@ -0,0 +1,15 @@
//创建用户相关的小仓库
import { defineStore } from 'pinia'
//创建用户小仓库
const useUserStore = defineStore('User', {
//小仓库存储数据地方
state: () => {
return {
}
},
//处理异步|逻辑地方
actions: {},
getters: {},
})
//对外暴露小仓库
export default useUserStore

10
src/styles/index.scss Normal file
View File

@ -0,0 +1,10 @@
/* Main styles */
:root{
--tw-bg-opacity:#272727;
--header-bg-color:#fff;
--footer-color:#999;
--footer-size:12px;
--footer-title:14px;
--footer-title-weight:600;
--topnews-size:14px;
}

15
src/styles/reset.scss Normal file
View File

@ -0,0 +1,15 @@
/* Reset and base styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Add more reset styles as needed */

0
src/styles/variable.scss Normal file
View File

110
src/utils/pathResolver.ts Normal file
View File

@ -0,0 +1,110 @@
/**
*
* @
*/
// 使用 import.meta.glob 预加载所有组件
const viewsModules = import.meta.glob('../views/**/*.vue')
// 创建路径映射表
const pathMap = new Map<string, () => Promise<any>>()
// 初始化路径映射
Object.keys(viewsModules).forEach((relativePath) => {
// relativePath: ../views/newsCenter/companyNews/index.vue
// 1. 别名格式: @/views/newsCenter/companyNews/index.vue
const aliasPath = relativePath.replace('../views', '@/views')
pathMap.set(aliasPath, viewsModules[relativePath])
// 2. 数据库格式: /views/newsCenter/companyNews/index.vue 或 /newsCenter/companyNews/index.vue
const dbPath1 = relativePath.replace('../views', '/views')
pathMap.set(dbPath1, viewsModules[relativePath])
const dbPath2 = relativePath.replace('../views/', '/')
pathMap.set(dbPath2, viewsModules[relativePath])
// 3. 相对路径格式: newsCenter/companyNews/index.vue
const relativePathFormat = relativePath.replace('../views/', '')
pathMap.set(relativePathFormat, viewsModules[relativePath])
// 4. 原始相对路径也保留
pathMap.set(relativePath, viewsModules[relativePath])
// 5. 如果路径包含 views/,也添加不带 views/ 的格式
if (relativePath.includes('views/')) {
const withoutViews = relativePath.replace('../views/', '')
if (withoutViews !== relativePathFormat) {
pathMap.set(withoutViews, viewsModules[relativePath])
}
}
})
/**
*
* @param path -
* - @/views/newsCenter/companyNews/index.vue ()
* - /views/newsCenter/companyNews/index.vue ()
* - /newsCenter/companyNews/index.vue ()
* - newsCenter/companyNews/index.vue ()
* @returns null
*/
export function resolveComponent(path: string): (() => Promise<any>) | null {
if (!path) {
return null
}
// 尝试多种路径格式
const searchPaths: string[] = [
path, // 原始路径
// 如果是以 / 开头的数据库格式,转换为别名格式
path.startsWith('/') && !path.startsWith('@/') ? `@/views${path}` : null,
// 如果是以 /views 开头的,转换为别名格式
path.startsWith('/views/') ? path.replace('/views/', '@/views/') : null,
// 如果是相对路径但不在 views 下,添加 @/views 前缀
!path.includes('@') && !path.includes('/views') && !path.startsWith('/')
? `@/views/${path}`
: null,
// 如果包含 views 但不在开头,确保格式正确
path.includes('views/') && !path.startsWith('@/') && !path.startsWith('/')
? `@/${path}`
: null,
// 如果路径以 views/ 开头,添加 @/ 前缀
path.startsWith('views/') ? `@/${path}` : null,
].filter((p): p is string => p !== null)
// 遍历所有可能的路径格式
for (const searchPath of searchPaths) {
const loader = pathMap.get(searchPath)
if (loader) {
return loader
}
}
// 如果精确匹配失败,尝试模糊匹配(按文件名)
const fileName = path.split('/').pop()
if (fileName) {
for (const [mappedPath, loader] of pathMap.entries()) {
if (mappedPath.endsWith(fileName)) {
return loader
}
}
}
return null
}
/**
*
* @param componentPath -
* @returns Vue
*/
export function createComponentLoader(componentPath: string) {
const loader = resolveComponent(componentPath)
if (!loader) {
console.error(`Component not found: ${componentPath}`)
// 返回一个错误组件或默认组件
return () => import('@/views/404/index.vue')
}
return loader
}

32
src/utils/request.ts Normal file
View File

@ -0,0 +1,32 @@
import axios from 'axios'
// 创建axios实例
const service = axios.create({
baseURL: import.meta.env.VITE_APP_API_URL,
timeout: 10000, // 请求超时时间
})
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 可以在这里添加token等认证信息
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
(response) => {
// 直接返回响应数据
return response
},
(error) => {
console.error('API请求错误:', error)
return Promise.reject(error)
}
)
export default service

261
src/views/404/index.vue Normal file
View File

@ -0,0 +1,261 @@
<template>
<div class="not-found">
<!-- Load page -->
<div class="animationload">
<div class="loader"></div>
</div>
<!-- Content Wrapper -->
<div id="wrapper">
<div class="container">
<!-- Switcher -->
<div class="switcher">
<label for="sw" class="sw_btn"></label>
<div class="bg"></div>
</div>
<!-- Dark version -->
<div id="dark" class="row text-center" v-show="isDark">
<div class="info">
<img :src="darkImage" alt="404 error" />
</div>
</div>
<!-- Light version -->
<div
id="light"
class="row text-center"
style="display: flex; justify-content: center; align-items: center"
v-show="!isDark"
>
<div class="info">
<img :src="lightImage" alt="404 error" />
<p>
您要查找的页面已被移动或删除
<br />
被重新命名或者可能从未存在过
</p>
<router-link to="/" class="btn">返回首页</router-link>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import darkImage from '@/assets/images/404/404-dark.png'
import lightImage from '@/assets/images/404/404-light.gif'
// jQuery
import type { JQueryStatic } from 'jquery'
// Modernizr
interface ModernizrStatic {
// Modernizr
[key: string]: boolean | string | number | object | undefined
}
//
declare global {
interface Window {
jQuery: JQueryStatic
$: JQueryStatic
init404Page?: () => void
Modernizr: ModernizrStatic
}
}
// 使 useRouter
useRouter()
const isDark = ref(false)
const toggleTheme = () => {
document.body.classList.toggle('dark-theme', isDark.value)
}
onMounted(() => {
// Initialize theme
document.body.classList.toggle('dark-theme', isDark.value)
//
onMounted(() => {
// CSS
const loadCSS = (href: string) => {
return new Promise<void>((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = href
link.onload = () => resolve()
link.onerror = (err) => reject(err)
document.head.appendChild(link)
})
}
// JS
const loadJS = (src: string) => {
return new Promise<void>((resolve, reject) => {
const script = document.createElement('script')
script.src = src
script.onload = () => resolve()
script.onerror = (err) => reject(err)
document.body.appendChild(script)
})
}
//
const loadAll = async () => {
try {
// CSS
await Promise.all([
loadCSS('/src/assets/css/bootstrap.min.css'),
loadCSS('/src/assets/css/404.min.css'),
loadCSS('/src/assets/css/font-face.css'),
])
// JS
await loadJS('/node_modules/jquery/dist/jquery.min.js')
// jQuery
const win = window as unknown as {
jQuery: JQueryStatic
$: JQueryStatic
}
window.jQuery = window.$ = win.jQuery || win.$
await Promise.all([
loadJS('/node_modules/bootstrap/dist/js/bootstrap.bundle.min.js'),
loadJS('/src/assets/js/modernizr.custom.js'),
loadJS('/node_modules/jquery.nicescroll/jquery.nicescroll.min.js'),
loadJS('/src/assets/js/404.min.js'),
])
//
if (typeof window.init404Page === 'function') {
window.init404Page()
}
} catch (error) {
console.error('Error loading resources:', error)
}
}
loadAll()
})
})
</script>
<style scoped>
/* Add any component-specific styles here */
.not-found {
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
}
/* Ensure the wrapper takes full height */
#wrapper {
min-height: 100vh;
display: flex;
align-items: center;
}
/* Make sure the container is properly centered */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* Make images responsive */
img {
max-width: 100%;
height: auto;
}
/* Style the home button */
.btn {
display: inline-block;
margin-top: 20px;
padding: 10px 20px;
background: #3498db;
color: white;
text-decoration: none;
border-radius: 4px;
transition: background 0.3s ease;
}
.btn:hover {
background: #2980b9;
}
/* Add smooth transitions for theme switching */
#dark,
#light {
transition: opacity 0.3s ease;
}
.info{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
/* Ensure proper spacing for the switcher */
.switcher {
position: fixed;
top: 20px;
right: 20px;
z-index: 1000;
}
/* 主题切换器文本样式 */
.switcher .text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 12px;
color: #666;
text-align: center;
line-height: 1.4;
white-space: nowrap;
pointer-events: none;
user-select: none;
transition: color 0.3s ease;
}
.switcher .text-l {
display: block;
margin-top: 2px;
font-size: 11px;
color: #999;
}
/* 暗色主题下的文本颜色 */
.dark-theme .switcher .text {
color: #ccc;
}
.dark-theme .switcher .text-l {
color: #aaa;
}
/* Responsive adjustments */
@media (max-width: 768px) {
.container {
padding: 10px;
}
.switcher {
position: relative;
top: 0;
right: 0;
margin: 20px auto;
display: inline-block;
}
}
</style>

View File

@ -0,0 +1,617 @@
<template>
<Header />
<div class="detail">
<div class="backimage"></div>
<div class="content">
<div class="content-left">
<div class="detail-header">
<h1>{{ article.title }}</h1>
<el-divider></el-divider>
<div class="detail-meta">
<div>
<i class="fa-regular fa-calendar"></i>
{{ article.publishdate }}
</div>
<div>
<i class="fa-solid fa-user-pen"></i>
{{ article.author }}
</div>
<div>
<i class="fa-solid fa-list"></i>
{{ article.catename }}
</div>
<div>
<i class="fa-regular fa-thumbs-up"></i>
{{ article.likes }}
</div>
<div>
<i class="fa-regular fa-eye"></i>
{{ article.views }}
</div>
</div>
</div>
<div class="detail-content" ref="contentRef">
<div v-html="article.content" class="content-html"></div>
</div>
<div class="theend">
<el-divider></el-divider>
<div class="the-end">The End</div>
<el-divider></el-divider>
</div>
<div class="endtool">
<div
style="
margin-bottom: 65px;
display: flex;
justify-content: center;
align-items: center;
gap: 40px;
"
>
<div class="tool-item" @click="handleShareClick">
<div class="tool-icon">
<i class="fa-solid fa-share-nodes"></i>
</div>
<span class="tool-text">分享</span>
</div>
<div class="tool-item" @click="handleLikeClick">
<div class="tool-icon">
<i
class="fa-regular fa-thumbs-up"
:class="{ liked: article.liked }"
></i>
</div>
<span class="tool-text">
{{ article.liked ? '取消点赞' : '点赞' }}
</span>
</div>
<div class="tool-item">
<div class="tool-icon">
<i class="fa-regular fa-comment"></i>
</div>
<span class="tool-text">评论</span>
</div>
</div>
</div>
<div class="article-nav">
<div
class="nav-item"
v-if="nextPreviousArticles.previous"
@click="goToArticle(nextPreviousArticles.previous.id)"
>
<div class="nav-label">
<i class="fa-solid fa-arrow-left"></i>
上一篇
</div>
<div class="nav-title">
{{ nextPreviousArticles.previous.title }}
</div>
</div>
<div
class="nav-item"
v-if="nextPreviousArticles.next"
@click="goToArticle(nextPreviousArticles.next.id)"
>
<div class="nav-label">
下一篇
<i class="fa-solid fa-arrow-right"></i>
</div>
<div class="nav-title">{{ nextPreviousArticles.next.title }}</div>
</div>
</div>
</div>
<div class="content-right">
<div class="card-item">
<div class="card-header">相关文章</div>
<el-divider></el-divider>
<div class="card-content">
<div
class="article-item"
v-for="item in relatedArticles"
:key="item.id"
>
<div class="thumb-img">
<img :src="imagePath(item.image)" alt="" />
</div>
<div class="article-title">{{ item.title }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
<Footer />
</template>
<script lang="ts" setup>
import { ref, onMounted, nextTick, getCurrentInstance } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { addLike, reduceLike } from '@/api/article'
import Header from '@/views/components/header.vue'
import Footer from '@/views/components/footer.vue'
import { getKingdeeNewsDetail, getCompanyNewsDetail } from '@/api/newscenter'
const route = useRoute()
const article = ref({})
const relatedArticles = ref([])
const nextPreviousArticles = ref<{
previous?: { id: number; title: string }
next?: { id: number; title: string }
}>({})
const loading = ref(true)
const { proxy } = getCurrentInstance()
const router = useRouter()
const contentRef = ref<HTMLElement | null>(null)
const VITE_APP_API_URL = import.meta.env.VITE_APP_API_URL
//
const handleCopyCode = async (e: Event) => {
const target = e.target as HTMLElement
const preElement = target.closest('.code-block-wrapper')
if (!preElement) return
const codeElement = preElement.querySelector('code')
if (!codeElement) return
const code = codeElement.innerText
try {
await navigator.clipboard.writeText(code)
proxy.$message.success('复制成功')
} catch (err) {
proxy.$message.error('复制失败,请手动复制')
}
}
//
const initCodeBlocks = () => {
if (!contentRef.value) return
const preElements = contentRef.value.querySelectorAll('pre')
preElements.forEach((pre) => {
if (pre.parentElement?.classList.contains('code-block-wrapper')) return
const wrapper = document.createElement('div')
wrapper.className = 'code-block-wrapper'
pre.parentNode?.insertBefore(wrapper, pre)
wrapper.appendChild(pre)
const copyBtn = document.createElement('button')
copyBtn.className = 'copy-code-btn'
copyBtn.innerHTML = '<i class="fa-regular fa-copy"></i>'
copyBtn.title = '复制代码'
copyBtn.onclick = handleCopyCode
wrapper.appendChild(copyBtn)
})
}
//
const handleShareClick = async () => {
const url = window.location.href
try {
await navigator.clipboard.writeText(url)
proxy.$message.success('复制地址成功')
} catch (err) {
proxy.$message.error('复制失败,请手动复制地址')
}
}
//
const handleLikeClick = async () => {
if (article.value.liked) {
await reduceLike(article.value.id)
article.value.likes--
article.value.liked = false
} else {
await addLike(article.value.id)
article.value.likes++
article.value.liked = true
}
}
//
const imagePath = (path: string) => {
if (!path) {
return new URL('@/assets/images/noimage.png', import.meta.url).href
}
return VITE_APP_API_URL + path
}
const goToArticle = (id: number) => {
if (route.path.includes('companyNews')) {
router.push(`/companyNews/detail/${id}`)
} else if (route.path.includes('kingdeeNews')) {
router.push(`/kingdeeNews/detail/${id}`)
} else {
router.push(`/kingdeeNews/detail/${id}`)
}
}
onMounted(async () => {
const id = route.params.id
loading.value = true
try {
let res
const path = route.path
if (path.includes('companyNews')) {
res = await getCompanyNewsDetail(id)
} else if (path.includes('kingdeeNews')) {
res = await getKingdeeNewsDetail(id)
} else {
res = await getKingdeeNewsDetail(id)
}
if (res.code === 200) {
article.value = res.data
nextTick(() => {
initCodeBlocks()
})
if (res.data.relatedArticles && res.data.relatedArticles.list) {
relatedArticles.value = res.data.relatedArticles.list.map(
(item: any) => ({
...item,
catename: item.cate,
}),
)
}
if (res.data.nextPreviousArticles) {
nextPreviousArticles.value = res.data.nextPreviousArticles
}
}
} catch (err) {
console.error('获取文章详情失败:', err)
} finally {
loading.value = false
}
})
</script>
<style lang="scss" scoped>
.detail {
padding-top: 120px;
background-color: #f8f8f8;
padding-bottom: 120px;
.content {
width: 1200px;
margin: 0 auto;
display: flex;
gap: 20px;
position: relative;
z-index: 1;
.content-left {
width: 70%;
border-radius: 10px;
background-color: #fff;
opacity: 0.9;
.detail-header {
margin-bottom: 20px;
padding: 50px 50px 0 50px;
.detail-meta {
display: flex;
align-items: center;
gap: 20px;
color: #707070;
font-size: 14px;
padding-bottom: 20px;
}
}
.detail-content {
padding: 0 50px;
.content-html {
:deep(pre) {
position: relative;
padding-right: 50px;
}
}
/* 代码块包装器 */
:deep(.code-block-wrapper) {
position: relative;
border-radius: 12px;
overflow: hidden;
margin: 20px 0;
pre {
margin: 0;
}
}
/* 复制按钮 */
:deep(.copy-code-btn) {
position: absolute;
top: 10px;
right: 10px;
width: 25px;
height: 25px;
border: none;
border-radius: 6px;
background: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.7);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
transition: all 0.2s ease;
z-index: 10;
&:hover {
background: rgba(255, 255, 255, 0.2);
color: #fff;
}
&:active {
transform: scale(0.95);
}
}
/* 代码样式 */
:deep(code) {
border-radius: 4px;
padding: 2px 6px;
font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
font-size: 13px;
color: #f06b6b;
}
/* 代码块样式 */
:deep(pre) {
background: linear-gradient(135deg, #1e1e2e 0%, #2d2d3f 100%);
border-radius: 12px;
padding: 10px;
overflow-x: auto;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
code {
background-color: transparent;
padding: 0;
padding-left: 10px;
color: #cdd6f4;
font-size: 13px;
line-height: 1.7;
}
}
:deep(img) {
width: 100%;
height: auto;
max-width: 100%;
display: block;
}
:deep(p) {
font-size: 14px;
line-height: 25px;
color: #606266;
}
}
.theend {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
margin: 60px;
.the-end {
width: 200px;
text-align: center;
color: #dcdfe6;
}
}
.endtool {
padding: 65px;
.tool-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
cursor: pointer;
transition: transform 0.3s ease;
&:hover {
transform: translateY(-5px);
.tool-icon {
background-color: #ff6b6b;
box-shadow: 0 8px 20px rgba(64, 158, 255, 0.4);
}
}
&:active {
transform: translateY(-2px);
.tool-icon {
background-color: #337ecc;
box-shadow: 0 4px 10px rgba(64, 158, 255, 0.3);
transform: scale(0.95);
}
}
&:has(.liked) {
.tool-icon {
background-color: #ff6b6b;
box-shadow: 0 8px 20px rgba(255, 107, 107, 0.4);
}
.tool-text {
color: #ff6b6b;
}
}
.tool-icon {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: #409eff;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
box-shadow: 0 4px 15px rgba(64, 158, 255, 0.3);
transition: all 0.3s ease;
.fa-thumbs-up.liked {
color: #fff;
animation: likeAnimation 0.4s ease;
}
}
.tool-text {
font-size: 14px;
color: #606266;
font-weight: 500;
transition: color 0.3s ease;
}
&:hover .tool-text {
color: #409eff;
}
}
}
.article-nav {
display: flex;
justify-content: space-between;
padding: 30px 65px;
border-top: 1px solid #f0f0f0;
.nav-item {
max-width: 45%;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
.nav-label {
color: #409eff;
}
.nav-title {
color: #409eff;
}
}
.nav-label {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
color: #909399;
margin-bottom: 10px;
transition: color 0.3s ease;
}
.nav-title {
font-size: 14px;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
transition: color 0.3s ease;
}
}
}
}
.content-right {
width: 30%;
opacity: 0.9;
.card-item {
// position: sticky;
top: 100px;
padding: 30px;
border-radius: 10px;
background-color: #fff;
.card-header {
font-size: 18px;
font-weight: 500;
}
.card-content {
.article-item {
padding-bottom: 20px;
border-bottom: 1px solid #f0f0f0;
margin-bottom: 20px;
&:last-child {
padding-bottom: 0;
border-bottom: none;
margin-bottom: 0;
}
.thumb-img {
width: 100%;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 10px;
}
}
.article-title {
font-size: 16px;
font-weight: 500;
color: #303133;
margin-top: 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
&:hover {
color: #409eff;
transition: color 0.3s ease;
}
}
}
}
}
}
}
}
.backimage {
width: 800px;
height: 400px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
position: fixed;
right: 100px;
bottom: 100px;
pointer-events: none;
background-image: url('@/assets/images/sologen.png');
opacity: 0.2;
}
@keyframes likeAnimation {
0% {
transform: scale(1);
}
25% {
transform: scale(1.3);
}
50% {
transform: scale(0.9);
}
100% {
transform: scale(1);
}
}
</style>

View File

@ -0,0 +1,206 @@
<template>
<div class="footer">
<div class="gototop" v-show="showGototop" @click="goToTop">
<i class="fa-solid fa-arrow-up"></i>
</div>
<div class="footer-content">
<div class="footer-main">
<div class="left">
<div class="footer-column">
<div class="title">关于美天</div>
<ul>
<li>企业概况</li>
<li>公司证件</li>
<li>新闻中心</li>
<li>加入我们</li>
<li>联系我们</li>
</ul>
</div>
<div class="footer-column">
<div class="title">产品中心</div>
<ul>
<li>金蝶·云星空</li>
<li>金蝶·KIS Cloud</li>
<li>金蝶·EAS Cloud</li>
<li>警务保障系统</li>
<li>义警联盟平台</li>
<li>商超进销存系统</li>
</ul>
</div>
<div class="footer-column">
<div class="title">解决方案</div>
<ul>
<li>财务云</li>
<li>供应链云</li>
<li>全渠道云</li>
<li>制造云</li>
</ul>
</div>
<div class="footer-column">
<div class="title">服务支持</div>
<ul>
<li>常见问题</li>
<li>软件下载</li>
<li>投诉与建议</li>
</ul>
</div>
<div class="footer-column">
<div class="title">商务合作</div>
<ul>
<li>商务合作</li>
</ul>
</div>
</div>
<div class="right">
<div class="footer-column">
<div class="title">订阅我们</div>
<div>第一时间了解我们的最新信息</div>
</div>
</div>
</div>
<div class="footer-bottom">
<div class="left">
<span>美天为您用心多一点</span>
<span>江苏美天智能科技有限公司·所有版权©2019-2026</span>
<span>备案号:苏ICP备2020053493号</span>
</div>
<div class="right">
<span>法律声明 | 隐私条款</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
const showGototop = ref(false)
const handleScroll = () => {
showGototop.value = window.scrollY > 300
}
const goToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
})
}
onMounted(() => {
window.addEventListener('scroll', handleScroll)
handleScroll()
})
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll)
})
</script>
<style lang="scss" scoped>
.footer {
width: 100%;
background-color: var(--tw-bg-opacity);
color: var(--footer-color);
font-size: var(--footer-size);
padding: 20px 0;
margin-top: auto;
position: relative;
z-index: 99;
.footer-content {
width:1200px;
margin: 0 auto;
}
.title {
font-size: var(--footer-title);
font-weight: var(--footer-title-weight);
margin-bottom: 16px;
color: #fff;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
margin-bottom: 12px;
cursor: pointer;
transition: color 0.3s;
}
li:hover {
color: #fff;
}
.footer-main {
display: flex;
padding: 40px 0;
.left {
width: 80%;
display: flex;
.footer-column {
flex: 1;
padding: 0 15px;
}
}
.right {
width: 20%;
}
}
.footer-bottom {
border-top: 1px solid #fff;
padding: 20px 0;
display: flex;
justify-content: space-between;
.left {
display: flex;
p {
margin-right: 12px;
}
}
}
.gototop {
position: fixed;
right: 40px;
bottom: 40px;
width: 50px;
height: 50px;
border-radius: 50%;
background-color: #409eff;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
box-shadow: 0 4px 15px rgba(64, 158, 255, 0.3);
transition: all 0.3s ease;
z-index: 9999;
i {
font-size: 20px;
}
&:hover {
background-color: #ff6b6b;
transform: translateY(-5px);
box-shadow: 0 8px 20px rgba(64, 158, 255, 0.4);
}
&:active {
transform: scale(0.95);
}
}
}
</style>

View File

@ -0,0 +1,887 @@
<template>
<div class="site-header-nav" :class="{ scrolled: isScrolled }" id="top">
<div class="container">
<div class="maincontent">
<div class="logo">
<img src="@/assets/images/logo.png" alt="Logo" />
</div>
<div class="menu">
<ul @mouseleave="handleMenuLeave">
<li
v-for="(item, index) in menuItems"
:key="index"
@mouseenter="handleMenuEnter(index)"
>
<!-- 一级菜单根据类型处理跳转 -->
<template v-if="!item.children || item.children.length === 0">
<!-- type 2: 页面 - 正常路由跳转 -->
<router-link
v-if="item.type === 2"
:to="item.path"
class="menu-link"
>
{{ item.title }}
</router-link>
<!-- type 4: 单页 - 跳转到单页路由 -->
<router-link
v-else-if="item.type === 4"
:to="item.path"
class="menu-link"
>
{{ item.title }}
</router-link>
<!-- type 3: 外链 - 直接打开外链 -->
<a
v-else-if="item.type === 3 && item.link_url"
:href="item.link_url"
target="_blank"
rel="noopener noreferrer"
class="menu-link"
@click.prevent="handleExternalLink(item.link_url)"
>
{{ item.title }}
</a>
<!-- type 1: 目录 - 不可点击只显示文本 -->
<span v-else class="menu-text">{{ item.title }}</span>
</template>
<span v-else class="menu-text">{{ item.title }}</span>
<!-- 下拉菜单显示二级和三级 -->
<div
v-if="
item.children &&
item.children.length > 0 &&
activeMenu === index
"
class="site-header-dropdown-menu"
@mouseenter="handleMenuEnter(index)"
@mouseleave="handleMenuLeave"
>
<div class="site-header-dropdown-container">
<!-- 左侧二级菜单列表 -->
<div class="category-list">
<div
v-for="(category, catIndex) in item.children"
:key="'cat-' + catIndex"
class="category-item"
:class="{ active: activeCategory === catIndex }"
@mouseenter="activeCategory = catIndex"
>
{{ category.title }}
</div>
</div>
<!-- 右侧三级菜单内容 -->
<div class="content-panel">
<div v-if="item.children[activeCategory || 0]">
<div class="content-section11">
<div>
<h3>
{{ item.children[activeCategory || 0].title }}
</h3>
</div>
<div class="content-grid">
<!-- 如果二级菜单有子菜单三级显示三级菜单 -->
<template
v-if="
item.children[activeCategory || 0].children &&
item.children[activeCategory || 0].children
.length > 0
"
>
<template
v-for="(subItem, subIndex) in item.children[
activeCategory || 0
].children"
:key="'sub-' + subIndex"
>
<!-- type 2: 页面 - 正常路由跳转 -->
<router-link
v-if="subItem.type === 2"
:to="subItem.path"
class="content-item"
>
<div class="icon" v-if="subItem.icon">
<i :class="subItem.icon"></i>
</div>
<div class="content">
<h4>{{ subItem.title }}</h4>
<p v-if="subItem.desc">{{ subItem.desc }}</p>
</div>
</router-link>
<!-- type 4: 单页 - 跳转到单页路由 -->
<router-link
v-else-if="subItem.type === 4"
:to="subItem.path"
class="content-item"
>
<div class="icon" v-if="subItem.icon">
<i :class="subItem.icon"></i>
</div>
<div class="content">
<h4>{{ subItem.title }}</h4>
<p v-if="subItem.desc">{{ subItem.desc }}</p>
</div>
</router-link>
<!-- type 3: 外链 - 直接打开外链 -->
<a
v-else-if="
subItem.type === 3 && subItem.link_url
"
:href="subItem.link_url"
target="_blank"
rel="noopener noreferrer"
class="content-item"
@click.prevent="
handleExternalLink(subItem.link_url)
"
>
<div class="icon" v-if="subItem.icon">
<i :class="subItem.icon"></i>
</div>
<div class="content">
<h4>{{ subItem.title }}</h4>
<p v-if="subItem.desc">{{ subItem.desc }}</p>
</div>
</a>
<!-- type 1: 目录 - 不可点击 -->
<div
v-else
class="content-item"
style="cursor: default"
>
<div class="icon" v-if="subItem.icon">
<i :class="subItem.icon"></i>
</div>
<div class="content">
<h4>{{ subItem.title }}</h4>
<p v-if="subItem.desc">{{ subItem.desc }}</p>
</div>
</div>
</template>
</template>
<!-- 如果二级菜单没有子菜单直接显示二级菜单为可点击项 -->
<template v-else>
<!-- type 2: 页面 - 正常路由跳转 -->
<router-link
v-if="
item.children[activeCategory || 0].type === 2
"
:to="item.children[activeCategory || 0].path"
class="content-item"
>
<div
class="icon"
v-if="item.children[activeCategory || 0].icon"
>
<i
:class="
item.children[activeCategory || 0].icon
"
></i>
</div>
<div class="content">
<h4>
{{ item.children[activeCategory || 0].title }}
</h4>
<p
v-if="item.children[activeCategory || 0].desc"
>
{{ item.children[activeCategory || 0].desc }}
</p>
</div>
</router-link>
<!-- type 4: 单页 - 跳转到单页路由 -->
<router-link
v-else-if="
item.children[activeCategory || 0].type === 4
"
:to="item.children[activeCategory || 0].path"
class="content-item"
>
<div
class="icon"
v-if="item.children[activeCategory || 0].icon"
>
<i
:class="
item.children[activeCategory || 0].icon
"
></i>
</div>
<div class="content">
<h4>
{{ item.children[activeCategory || 0].title }}
</h4>
<p
v-if="item.children[activeCategory || 0].desc"
>
{{ item.children[activeCategory || 0].desc }}
</p>
</div>
</router-link>
<!-- type 3: 外链 - 直接打开外链 -->
<a
v-else-if="
item.children[activeCategory || 0].type === 3 &&
item.children[activeCategory || 0].link_url
"
:href="
item.children[activeCategory || 0].link_url
"
target="_blank"
rel="noopener noreferrer"
class="content-item"
@click.prevent="
handleExternalLink(
item.children[activeCategory || 0].link_url,
)
"
>
<div
class="icon"
v-if="item.children[activeCategory || 0].icon"
>
<i
:class="
item.children[activeCategory || 0].icon
"
></i>
</div>
<div class="content">
<h4>
{{ item.children[activeCategory || 0].title }}
</h4>
<p
v-if="item.children[activeCategory || 0].desc"
>
{{ item.children[activeCategory || 0].desc }}
</p>
</div>
</a>
<!-- type 1: 目录 - 不可点击 -->
<div
v-else
class="content-item"
style="cursor: default"
>
<div
class="icon"
v-if="item.children[activeCategory || 0].icon"
>
<i
:class="
item.children[activeCategory || 0].icon
"
></i>
</div>
<div class="content">
<h4>
{{ item.children[activeCategory || 0].title }}
</h4>
<p
v-if="item.children[activeCategory || 0].desc"
>
{{ item.children[activeCategory || 0].desc }}
</p>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
<div class="search">
<div class="search-icon" @click="showSearch = true">
<i class="fa-solid fa-magnifying-glass"></i>
</div>
<div class="language-switcher" @click="showLanguage = true">
<span>中文</span>
<i class="fa-solid fa-caret-down"></i>
</div>
</div>
<!-- 搜索弹窗 -->
<div
class="modal"
:class="{ active: showSearch }"
@click.self="showSearch = false"
>
<div class="modal-content">
<div class="search-box">
<input
type="text"
placeholder="请输入搜索内容..."
v-model="searchQuery"
@keyup.enter="performSearch"
/>
<button @click="performSearch">搜索</button>
</div>
<button class="close-btn" @click="showSearch = false">×</button>
</div>
</div>
<!-- 语言选择弹窗 -->
<div
class="modal"
:class="{ active: showLanguage }"
@click.self="showLanguage = false"
>
<div class="modal-content language-modal">
<h3>选择语言 / Language</h3>
<div class="language-options">
<div
class="language-option"
:class="{ active: currentLanguage === 'zh' }"
@click="changeLanguage('zh')"
>
<span>中文</span>
</div>
<div
class="language-option"
:class="{ active: currentLanguage === 'en' }"
@click="changeLanguage('en')"
>
<span>English</span>
</div>
</div>
<button class="close-btn" @click="showLanguage = false">×</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { getHeadMenu } from '@/api/index'
//
const menuItems = ref([])
//
const normalizeMenuPaths = (menus) => {
return menus.map(menu => {
const normalizedMenu = { ...menu }
// /newscenter/ /newsCenter/
if (normalizedMenu.path) {
normalizedMenu.path = normalizedMenu.path.replace(/\/newscenter\//g, '/newsCenter/')
}
//
if (normalizedMenu.children && normalizedMenu.children.length > 0) {
normalizedMenu.children = normalizeMenuPaths(normalizedMenu.children)
}
return normalizedMenu
})
}
//
const loadMenu = async () => {
try {
const response = await getHeadMenu()
if (response.code === 200) {
menuItems.value = normalizeMenuPaths(response.data)
}
} catch (error) {
console.error('加载菜单失败:', error)
menuItems.value = []
}
}
const activeMenu = ref(null)
const activeCategory = ref(0)
const showSearch = ref(false)
const showLanguage = ref(false)
const searchQuery = ref('')
const currentLanguage = ref('zh')
const isScrolled = ref(false)
let closeTimer = null
const handleScroll = () => {
isScrolled.value = window.scrollY > 10
}
const performSearch = () => {
if (searchQuery.value.trim()) {
console.log('Searching for:', searchQuery.value)
showSearch.value = false
}
}
const changeLanguage = (lang) => {
currentLanguage.value = lang
showLanguage.value = false
console.log('Language changed to:', lang)
}
const handleMenuEnter = (index) => {
//
if (closeTimer) {
clearTimeout(closeTimer)
closeTimer = null
}
activeMenu.value = index
activeCategory.value = 0 //
}
const handleMenuLeave = () => {
//
closeTimer = setTimeout(() => {
activeMenu.value = null
activeCategory.value = 0
}, 150) // 150ms
}
//
const handleExternalLink = (url) => {
if (url) {
// URL
const fullUrl =
url.startsWith('http://') || url.startsWith('https://')
? url
: `https://${url}`
window.open(fullUrl, '_blank', 'noopener,noreferrer')
}
}
onMounted(() => {
window.addEventListener('scroll', handleScroll)
loadMenu() //
})
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll)
if (closeTimer) {
clearTimeout(closeTimer)
closeTimer = null
}
})
</script>
<style lang="scss" scoped>
.site-header-nav {
width: 100%;
height: 80px;
position: fixed;
top: 0;
left: 0;
color: #fff;
z-index: 500; // z-index
transition: all 0.3s ease;
padding: 0 20px;
&.scrolled {
background: rgba(255, 255, 255, 0.95);
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
color: #333;
height: 70px;
.menu ul > li .site-header-dropdown-menu {
top: 70px;
}
}
.container {
max-width: 1200px;
height: 100%;
margin: 0 auto;
display: flex;
align-items: center;
padding: 0 20px;
}
.maincontent {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
img {
max-width: 300px;
object-fit: contain;
}
}
.menu {
ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
gap: 30px;
position: relative;
> li {
position: relative;
font-size: 16px;
/*font-weight: 500;*/
cursor: pointer;
padding: 5px 0;
transition: color 0.3s ease;
.menu-link,
.menu-text {
// color: inherit;
color: #1f1f1f;
text-decoration: none;
display: block;
&:hover {
color: #1890ff;
}
}
// menu-link
a.menu-link {
color: #1f1f1f;
text-decoration: none;
display: block;
cursor: pointer;
&:hover {
color: #1890ff;
}
}
&:hover {
color: #1890ff;
}
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background-color: #1890ff;
transition: width 0.3s ease;
}
&:hover::after {
width: 100%;
}
/* 下拉菜单样式 */
.site-header-dropdown-menu {
position: fixed;
left: 0;
right: 0;
top: 75px;
width: 100vw;
background: #fff;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
z-index: 9999; // z-index
display: flex;
opacity: 0;
visibility: hidden;
transition:
opacity 0.3s ease,
visibility 0.3s ease;
pointer-events: none;
margin-top: 5px; /* 添加一个小间隙,让鼠标可以移动 */
.site-header-dropdown-container {
display: flex;
width: 100%;
margin: 0 auto;
min-height: 350px;
pointer-events: auto;
}
/* 二级菜单(左侧) */
.category-list {
// width: 200px;
background: #f8f9fa;
border-right: 1px solid #eee;
overflow-y: auto;
padding: 20px 0;
padding-left: 15%;
.category-item {
display: flex;
align-items: center;
min-height: 40px;
padding: 10px 20px;
cursor: pointer;
transition: all 0.2s ease;
color: #333;
font-size: 14px;
&:hover,
&.active {
background: #e9ecef;
color: #1890ff;
}
}
}
.content-panel {
flex: 1;
padding: 20px;
overflow-y: auto;
.content-section11 {
h3 {
margin: 0 0 20px;
color: #333;
font-size: 18px;
border-bottom: 1px solid #efefef;
padding-bottom: 20px;
}
.content-grid {
display: flex;
flex-wrap: wrap;
gap: 15px;
.content-item {
display: flex;
align-items: flex-start;
flex: 0 0 calc(33.333% - 10px); // 3gap
min-width: 250px; //
padding: 15px;
border-radius: 4px;
transition: all 0.2s ease;
color: #333;
text-decoration: none;
&:hover {
background: #f8f9fa;
transform: translateY(-2px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.icon {
margin-right: 12px;
color: #1890ff;
font-size: 20px;
flex-shrink: 0;
}
.content {
flex: 1;
}
h4 {
margin: 0 0 5px;
font-size: 15px;
}
p {
margin: 0;
font-size: 13px;
color: #666;
}
}
}
}
}
}
&:hover .site-header-dropdown-menu,
.site-header-dropdown-menu:hover {
opacity: 1;
visibility: visible;
pointer-events: auto;
}
}
}
}
.search {
display: flex;
align-items: center;
gap: 20px;
color: #1f1f1f;
.search-icon,
.language-switcher {
cursor: pointer;
font-size: 18px;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 5px;
&:hover {
color: #1890ff;
transform: scale(1.1);
}
}
}
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
z-index: 2000;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(5px);
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
&.active {
opacity: 1;
visibility: visible;
}
.modal-content {
background: white;
padding: 30px;
border-radius: 8px;
width: 90%;
max-width: 500px;
position: relative;
transform: translateY(20px);
transition:
transform 0.3s ease,
opacity 0.3s ease;
opacity: 0;
.search-box {
display: flex;
gap: 10px;
margin-top: 20px;
input {
flex: 1;
padding: 12px 15px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
transition: border-color 0.3s ease;
&:focus {
border-color: #1890ff;
outline: none;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
}
button {
padding: 0 25px;
background-color: #1890ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.3s ease;
&:hover {
background-color: #40a9ff;
transform: translateY(-1px);
}
&:active {
transform: translateY(0);
}
}
}
.close-btn {
position: absolute;
top: 15px;
right: 20px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #999;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: all 0.3s ease;
&:hover {
color: #333;
background-color: #f5f5f5;
}
}
&.language-modal {
text-align: center;
h3 {
margin: 0 0 20px;
color: #333;
font-size: 18px;
}
.language-options {
display: flex;
flex-direction: column;
gap: 10px;
.language-option {
padding: 12px 20px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s ease;
background-color: #f9f9f9;
&:hover {
background-color: #f0f0f0;
transform: translateX(5px);
}
&.active {
background-color: #e6f7ff;
color: #1890ff;
font-weight: 500;
}
}
}
}
}
&.active .modal-content {
transform: translateY(0);
opacity: 1;
}
}
}
/* 响应式调整 */
@media (max-width: 992px) {
.site-header-nav {
.menu {
display: none;
}
.search {
margin-left: auto;
}
}
}
@media (max-width: 576px) {
.site-header-nav {
.logo img {
max-width: 150px;
}
.search {
gap: 15px;
}
}
}
</style>

1078
src/views/home/index.vue Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,559 @@
<template>
<Header />
<div class="headtop"></div>
<div class="content-container">
<div class="topcontent">
<div class="top-content">
<div class="top-content-title">新闻中心 - 企业新闻</div>
<div class="top-content-subtitle">NEWS CENTER - COMPANY NEWS</div>
</div>
</div>
<div class="maincontent">
<!-- 筛选栏 -->
<div class="filter-panel">
<div class="filter-row">
<span class="filter-label">新闻分类</span>
<div class="filter-options">
<span
v-for="item in categoryList"
:key="item.value"
:class="[
'filter-item',
{ active: activeCategory === item.value },
]"
@click="activeCategory = item.value"
>
{{ item.label }}
</span>
</div>
</div>
<div class="filter-row">
<span class="filter-label">新闻属性</span>
<div class="filter-options">
<span
v-for="item in flagList"
:key="item.value"
:class="['filter-item', { active: activeFlag === item.value }]"
@click="activeFlag = item.value"
>
{{ item.label }}
</span>
</div>
</div>
</div>
<!-- 加载状态 -->
<div v-if="loading" class="loading-state">
<i class="fas fa-spinner fa-spin"></i>
<span>加载中...</span>
</div>
<!-- 错误信息 -->
<div v-else-if="error" class="error-state">
<i class="fas fa-exclamation-circle"></i>
<span>{{ error }}</span>
</div>
<!-- 新闻列表 -->
<div v-else-if="newsData.length > 0" class="news-grid">
<div
v-for="news in newsData"
:key="news.id"
class="news-card"
@click="goToDetail(news.id)"
>
<div class="card-image" v-if="news.image">
<img :src="getImageUrl(news.image)" :alt="news.title" />
</div>
<div v-else class="card-image-placeholder">
<i class="fas fa-image"></i>
</div>
<div class="card-content">
<div class="card-title-container">
<h3 class="card-title">
<span v-if="news.top === 1" class="top-tag">置顶</span>
<span v-if="news.recommend === 1" class="recommend-tag">
推荐
</span>
{{ news.title }}
</h3>
</div>
<div class="card-meta">
<span class="card-date">
<i class="fa-regular fa-calendar-minus"></i>
{{ formatDate(news.publishdate) }}
</span>
<span class="right-meta">
<span class="card-date">
<i class="fa-regular fa-heart"></i>
{{ news.likes }}
</span>
<span class="card-date">
<i class="fa-regular fa-eye"></i>
{{ news.views }}
</span>
</span>
</div>
</div>
</div>
</div>
<!-- 无数据状态 -->
<div v-else class="empty-state">
<el-empty :image-size="200" />
</div>
<!-- 加载更多按钮 -->
<div
v-if="!loading && !error && newsData.length > 0 && hasMore"
class="load-more"
>
<button class="load-more-btn" @click="loadMore" :disabled="loadingMore">
<i v-if="loadingMore" class="fas fa-spinner fa-spin"></i>
<span v-else>加载更多</span>
</button>
</div>
<!-- 没有更多数据提示 -->
<div
v-if="!loading && !error && newsData.length > 0 && !hasMore"
class="no-more"
>
<span>已加载全部数据</span>
</div>
</div>
<div class="bottomcontent"></div>
</div>
<Footer />
</template>
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import Header from '@/views/components/header.vue'
import Footer from '@/views/components/footer.vue'
import { getCompanyNews } from '@/api/newscenter'
const router = useRouter()
const newsData = ref<any[]>([])
const loading = ref(false)
const loadingMore = ref(false)
const error = ref('')
const currentPage = ref(1)
const pageSize = ref(12) // 12
const total = ref(0)
//
const categoryList = [
{ label: '全部', value: 'all' },
{ label: '公司新闻', value: 'company' },
{ label: '行业新闻', value: 'industry' },
{ label: '媒体报道', value: 'media' },
]
const flagList = [
{ label: '全部', value: 'all' },
{ label: '置顶', value: 'top' },
{ label: '推荐', value: 'recommend' },
]
//
const activeCategory = ref('all')
const activeFlag = ref('all')
//
const hasMore = computed(() => {
return newsData.value.length < total.value
})
// URL
const getImageUrl = (image: string) => {
if (!image) return ''
if (image.startsWith('http')) return image
return `${import.meta.env.VITE_APP_API_URL || ''}${image}`
}
//
const formatDate = (date: string) => {
if (!date) return ''
const d = new Date(date)
return d.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
}
const goToDetail = (id: number) => {
router.push(`/newscenter/companyNews/detail/${id}`)
}
//
const loadMore = async () => {
if (loadingMore.value || !hasMore.value) return
loadingMore.value = true
currentPage.value++
try {
const response = await getCompanyNews(currentPage.value, pageSize.value)
if (response.code === 200) {
//
newsData.value = [...newsData.value, ...(response.list || [])]
total.value = response.total || 0
} else {
error.value = response.msg || '加载更多数据失败'
currentPage.value-- // 退
}
} catch (err: any) {
error.value = '加载更多数据时发生错误'
console.error('加载更多数据错误:', err)
currentPage.value-- // 退
} finally {
loadingMore.value = false
}
}
//
const loadNews = async () => {
loading.value = true
error.value = ''
currentPage.value = 1
try {
const response = await getCompanyNews(currentPage.value, pageSize.value)
if (response.code === 200) {
newsData.value = response.list || []
total.value = response.total || 0
} else {
error.value = response.msg || '获取新闻数据失败'
}
} catch (err: any) {
error.value = '获取新闻数据时发生错误'
console.error('获取新闻数据错误:', err)
} finally {
loading.value = false
}
}
onMounted(() => {
loadNews()
})
</script>
<style lang="scss" scoped>
.headtop {
height: 80px;
flex-shrink: 0;
}
.content-container {
min-height: calc(100vh - 80px);
display: flex;
flex-direction: column;
.filter-panel {
background: #fff;
padding: 20px 30px;
margin-bottom: 40px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
.filter-row {
display: flex;
align-items: center;
padding: 12px 0;
border-bottom: 1px dashed #eee;
&:last-child {
border-bottom: none;
}
.filter-label {
width: 90px;
font-size: 14px;
font-weight: 500;
color: #333;
flex-shrink: 0;
}
.filter-options {
display: flex;
flex-wrap: wrap;
gap: 16px;
.filter-item {
font-size: 14px;
color: #666;
cursor: pointer;
transition: all 0.2s;
&:hover {
color: #1890ff;
}
&.active {
color: #1890ff;
font-weight: 600;
}
}
}
}
}
.topcontent {
height: 450px;
width: 100%;
background-image: url(@/assets/images/newscenter.jpg);
background-size: cover;
background-position: center;
flex-shrink: 0;
.top-content {
padding-top: 180px;
width: 1200px;
margin: 0 auto;
.top-content-title {
font-size: 35px;
font-weight: 600;
color: #fff;
}
.top-content-subtitle {
width: 300px;
margin-top: 20px;
padding-top: 20px;
font-size: 16px;
color: #fff;
border-top: 2px solid #fff;
}
}
}
.maincontent {
flex: 1;
width: 1200px;
margin: 80px auto;
padding: 0 20px;
.loading-state,
.error-state,
.empty-state {
display: flex;
align-items: center;
justify-content: center;
padding: 60px 20px;
text-align: center;
color: #666;
font-size: 16px;
i {
margin-right: 10px;
font-size: 24px;
}
}
.error-state {
color: #f56c6c;
i {
color: #f56c6c;
}
}
.news-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 30px;
margin-bottom: 40px;
@media (max-width: 992px) {
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
@media (max-width: 576px) {
grid-template-columns: 1fr;
gap: 20px;
}
.news-card {
display: flex;
flex-direction: column;
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
cursor: pointer;
&:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform: translateY(-4px);
}
.card-image {
width: 100%;
height: 140px;
overflow: hidden;
background: #f5f5f5;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
&:hover img {
transform: scale(1.05);
}
}
.card-image-placeholder {
width: 100%;
height: 140px;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
color: #ccc;
font-size: 48px;
}
.card-content {
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
flex: 1;
.card-title-container {
display: flex;
align-items: flex-start;
gap: 8px;
flex-wrap: wrap;
.recommend-tag {
padding: 4px 10px;
background: #1890ff;
color: #fff;
font-size: 12px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
}
.top-tag {
padding: 4px 10px;
background: #ff5050;
color: #fff;
font-size: 12px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
}
.card-title {
font-size: 14px;
font-weight: 600;
color: #333;
margin: 0;
height: 40px;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
min-width: 0;
}
}
.card-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 13px;
color: #999;
.right-meta {
display: flex;
gap: 6px;
}
span {
margin-right: 6px;
}
.card-date {
display: flex;
align-items: center;
gap: 5px;
}
}
.card-desc {
font-size: 14px;
color: #666;
line-height: 1.6;
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 3;
line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
}
}
}
}
.load-more {
display: flex;
justify-content: center;
margin-top: 40px;
padding: 20px 0;
.load-more-btn {
padding: 12px 40px;
border: 1px solid #1890ff;
border-radius: 6px;
background: #fff;
color: #1890ff;
cursor: pointer;
transition: all 0.3s ease;
font-size: 15px;
display: flex;
align-items: center;
gap: 8px;
&:hover:not(:disabled) {
background: #1890ff;
color: #fff;
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
}
.no-more {
display: flex;
justify-content: center;
margin-top: 40px;
padding: 20px 0;
color: #999;
font-size: 14px;
}
}
.bottomcontent {
flex-shrink: 0;
}
}
</style>

View File

@ -0,0 +1,94 @@
<template>
<Header />
<div class="detail">
<div class="detail-header">
<h1>{{ article.title }}</h1>
<p>{{ article.create_time }}</p>
</div>
<div class="detail-content">
<p v-html="article.content"></p>
</div>
</div>
<Footer />
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import Header from '@/views/components/header.vue'
import Footer from '@/views/components/footer.vue'
import { getKingdeeNewsDetail, getCompanyNewsDetail } from '@/api/newscenter'
const route = useRoute()
const article = ref({})
const loading = ref(true)
onMounted(async () => {
const id = route.params.id
loading.value = true
try {
let res
const path = route.path
if (path.includes('companyNews')) {
res = await getCompanyNewsDetail(id)
} else if (path.includes('kingdeeNews')) {
res = await getKingdeeNewsDetail(id)
} else {
res = await getKingdeeNewsDetail(id)
}
if (res.code === 200) {
article.value = res.data
}
} catch (err) {
console.error('获取文章详情失败:', err)
} finally {
loading.value = false
}
})
</script>
<style lang="scss" scoped>
.detail {
padding: 40px 0;
background-color: var(--tw-bg-opacity);
color: var(--footer-color);
font-size: var(--footer-size);
.detail-header {
margin-bottom: 20px;
}
.detail-content {
::v-deep code {
background-color: #f0f2f5;
border-radius: 4px;
padding: 2px 6px;
font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
font-size: 13px;
color: #f06b6b;
}
::v-deep pre {
background: linear-gradient(135deg, #1e1e2e 0%, #2d2d3f 100%) !important;
border-radius: 12px;
padding: 20px;
overflow-x: auto;
margin: 20px 0;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
code {
background-color: transparent !important;
padding: 0;
color: #cdd6f4;
font-size: 13px;
line-height: 1.7;
display: block;
}
}
}
}
</style>

View File

@ -0,0 +1,459 @@
<template>
<Header />
<div class="headtop"></div>
<div class="content-container">
<div class="topcontent">
<div class="top-content">
<div class="top-content-title">新闻中心 - 金蝶新闻</div>
<div class="top-content-subtitle">NEWS CENTER - KINGDEE NEWS</div>
</div>
</div>
<div class="maincontent">
<!-- 加载状态 -->
<div v-if="loading" class="loading-state">
<i class="fas fa-spinner fa-spin"></i>
<span>加载中...</span>
</div>
<!-- 错误信息 -->
<div v-else-if="error" class="error-state">
<i class="fas fa-exclamation-circle"></i>
<span>{{ error }}</span>
</div>
<!-- 新闻列表 -->
<div v-else-if="newsData.length > 0" class="news-grid">
<div
v-for="news in newsData"
:key="news.id"
class="news-card"
@click="goToDetail(news.id)"
>
<div class="card-image" v-if="news.image">
<img :src="getImageUrl(news.image)" :alt="news.title" />
</div>
<div v-else class="card-image-placeholder card-image">
<img src="@/assets/images/noimage.png">
</div>
<div class="card-content">
<div class="card-title-container">
<h3 class="card-title">
<span v-if="news.top === 1" class="top-tag">置顶</span>
<span v-if="news.recommend === 1" class="recommend-tag">
推荐
</span>
{{ news.title }}
</h3>
</div>
<div class="card-meta">
<span class="card-date">
<i class="fa-regular fa-calendar-minus"></i>
{{ formatDate(news.publishdate) }}
</span>
<span class="right-meta">
<span class="card-date">
<i class="fa-regular fa-heart"></i>
{{ news.likes }}
</span>
<span class="card-date">
<i class="fa-regular fa-eye"></i>
{{ news.views }}
</span>
</span>
</div>
</div>
</div>
</div>
<!-- 无数据状态 -->
<div v-else class="empty-state">
<el-empty :image-size="200" />
</div>
<!-- 加载更多按钮 -->
<div
v-if="!loading && !error && newsData.length > 0 && hasMore"
class="load-more"
>
<button class="load-more-btn" @click="loadMore" :disabled="loadingMore">
<i v-if="loadingMore" class="fas fa-spinner fa-spin"></i>
<span v-else>加载更多</span>
</button>
</div>
<!-- 没有更多数据提示 -->
<div
v-if="!loading && !error && newsData.length > 0 && !hasMore"
class="no-more"
>
<span>已加载全部数据</span>
</div>
</div>
<div class="bottomcontent"></div>
</div>
<Footer />
</template>
<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import Header from '@/views/components/header.vue'
import Footer from '@/views/components/footer.vue'
import { getKingdeeNews } from '@/api/newscenter'
const router = useRouter()
const newsData = ref<any[]>([])
const loading = ref(false)
const loadingMore = ref(false)
const error = ref('')
const currentPage = ref(1)
const pageSize = ref(12) // 12
const total = ref(0)
//
const goToDetail = (id: number) => {
router.push(`/newscenter/kingdeeNews/detail/${id}`)
}
//
const hasMore = computed(() => {
return newsData.value.length < total.value
})
// URL
const getImageUrl = (image: string) => {
if (!image) return ''
if (image.startsWith('http')) return image
return `${import.meta.env.VITE_APP_API_URL || ''}${image}`
}
//
const formatDate = (date: string) => {
if (!date) return ''
const d = new Date(date)
return d.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
}
//
const loadMore = async () => {
if (loadingMore.value || !hasMore.value) return
loadingMore.value = true
currentPage.value++
try {
const response = await getKingdeeNews(currentPage.value, pageSize.value)
if (response.code === 200) {
//
newsData.value = [...newsData.value, ...(response.list || [])]
total.value = response.total || 0
} else {
error.value = response.msg || '加载更多数据失败'
currentPage.value-- // 退
}
} catch (err: any) {
error.value = '加载更多数据时发生错误'
console.error('加载更多数据错误:', err)
currentPage.value-- // 退
} finally {
loadingMore.value = false
}
}
//
const loadNews = async () => {
loading.value = true
error.value = ''
currentPage.value = 1
try {
const response = await getKingdeeNews(currentPage.value, pageSize.value)
if (response.code === 200) {
newsData.value = response.list || []
total.value = response.total || 0
} else {
error.value = response.msg || '获取新闻数据失败'
}
} catch (err: any) {
error.value = '获取新闻数据时发生错误'
console.error('获取新闻数据错误:', err)
} finally {
loading.value = false
}
}
onMounted(() => {
loadNews()
})
</script>
<style lang="scss" scoped>
.headtop {
height: 80px;
flex-shrink: 0;
}
.content-container {
min-height: calc(100vh - 80px);
display: flex;
flex-direction: column;
.topcontent {
height: 450px;
width: 100%;
background-image: url(@/assets/images/kingdeenews.jpg);
background-size: cover;
background-position: center;
flex-shrink: 0;
.top-content {
padding-top: 180px;
width: 1200px;
margin: 0 auto;
.top-content-title {
font-size: 35px;
font-weight: 600;
color: #fff;
}
.top-content-subtitle {
width: 300px;
margin-top: 20px;
padding-top: 20px;
font-size: 16px;
color: #fff;
border-top: 2px solid #fff;
}
}
}
.maincontent {
flex: 1;
width: 1200px;
margin: 80px auto;
padding: 0 20px;
.loading-state,
.error-state,
.empty-state {
display: flex;
align-items: center;
justify-content: center;
padding: 60px 20px;
text-align: center;
color: #666;
font-size: 16px;
i {
margin-right: 10px;
font-size: 24px;
}
}
.error-state {
color: #f56c6c;
i {
color: #f56c6c;
}
}
.news-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 30px;
margin-bottom: 40px;
@media (max-width: 992px) {
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
@media (max-width: 576px) {
grid-template-columns: 1fr;
gap: 20px;
}
.news-card {
display: flex;
flex-direction: column;
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
cursor: pointer;
&:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform: translateY(-4px);
}
.card-image {
width: 100%;
height: 140px;
overflow: hidden;
background: #f5f5f5;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
&:hover img {
transform: scale(1.05);
}
}
.card-image-placeholder {
width: 100%;
height: 140px;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
color: #ccc;
font-size: 48px;
}
.card-content {
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
flex: 1;
.card-title-container {
display: flex;
align-items: flex-start;
gap: 8px;
flex-wrap: wrap;
.recommend-tag {
padding: 4px 10px;
background: #1890ff;
color: #fff;
font-size: 12px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
}
.top-tag {
padding: 4px 10px;
background: #ff5050;
color: #fff;
font-size: 12px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
}
.card-title {
font-size: 14px;
font-weight: 600;
color: #333;
margin: 0;
height: 40px;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
min-width: 0;
span {
margin-right: 6px;
}
}
}
.card-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 13px;
color: #999;
.right-meta {
display: flex;
gap: 6px;
}
span {
margin-right: 6px;
}
.card-date {
display: flex;
align-items: center;
gap: 5px;
}
}
.card-desc {
font-size: 14px;
color: #666;
line-height: 1.6;
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 3;
line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
}
}
}
}
.load-more {
display: flex;
justify-content: center;
margin-top: 40px;
padding: 20px 0;
.load-more-btn {
padding: 12px 40px;
border: 1px solid #1890ff;
border-radius: 6px;
background: #fff;
color: #1890ff;
cursor: pointer;
transition: all 0.3s ease;
font-size: 15px;
display: flex;
align-items: center;
gap: 8px;
&:hover:not(:disabled) {
background: #1890ff;
color: #fff;
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
}
.no-more {
display: flex;
justify-content: center;
margin-top: 40px;
padding: 20px 0;
color: #999;
font-size: 14px;
}
}
.bottomcontent {
flex-shrink: 0;
}
}
</style>

View File

@ -0,0 +1,584 @@
<template>
<Header />
<div class="headtop"></div>
<div class="container">
<div class="topcontent">
<div class="top-content">
<div class="top-content-title">技术中心</div>
<div class="top-content-subtitle">Technology Center</div>
</div>
</div>
<div class="maincontent">
<div class="content-wrapper">
<!-- 左侧分类列表 -->
<div class="category-sidebar">
<div class="sidebar-title">分类</div>
<div class="category-list">
<div
v-for="category in categories"
:key="category.id"
class="category-item"
:class="{ active: selectedCategoryId === category.id }"
@click="selectCategory(category.id)"
>
{{ category.name }}
</div>
</div>
</div>
<!-- 右侧新闻列表 -->
<div class="news-content">
<!-- 加载状态 -->
<div v-if="loading" class="loading-state">
<i class="fas fa-spinner fa-spin"></i>
<span>加载中...</span>
</div>
<!-- 错误信息 -->
<div v-else-if="error" class="error-state">
<i class="fas fa-exclamation-circle"></i>
<span>{{ error }}</span>
</div>
<!-- 新闻列表 -->
<div v-else-if="newsData.length > 0" class="news-grid">
<div
v-for="news in newsData"
:key="news.id"
class="news-card"
@click="goToDetail(news.id)"
>
<div class="card-image" v-if="news.image || news.cate">
<img :src="getImageUrl(news.image, news.cate)" :alt="news.title" />
</div>
<div v-else class="card-image-placeholder">
<i class="fas fa-image"></i>
</div>
<div class="card-content">
<div class="card-title-container">
<h3 class="card-title">
<span v-if="news.top === 1" class="top-tag">置顶</span>
<span v-if="news.recommend === 1" class="recommend-tag">
推荐
</span>
{{ news.title }}
</h3>
</div>
<div class="card-meta">
<span class="card-date">
<i class="fa-regular fa-calendar-minus"></i>
{{ formatDate(news.publishdate) }}
</span>
<span class="right-meta">
<span class="card-date">
<i class="fa-regular fa-heart"></i>
{{ news.likes }}
</span>
<span class="card-date">
<i class="fa-regular fa-eye"></i>
{{ news.views }}
</span>
</span>
</div>
</div>
</div>
</div>
<!-- 无数据状态 -->
<div v-else class="empty-state">
<el-empty :image-size="200" />
</div>
<!-- 加载更多按钮 -->
<div
v-if="!loading && !error && newsData.length > 0 && hasMore"
class="load-more"
>
<button
class="load-more-btn"
@click="loadMore"
:disabled="loadingMore"
>
<i v-if="loadingMore" class="fas fa-spinner fa-spin"></i>
<span v-else>加载更多</span>
</button>
</div>
<!-- 没有更多数据提示 -->
<div
v-if="!loading && !error && newsData.length > 0 && !hasMore"
class="no-more"
>
<span>已加载全部数据</span>
</div>
</div>
</div>
</div>
<div class="bottomcontent"></div>
</div>
<Footer />
</template>
<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import Header from '@/views/components/header.vue'
import Footer from '@/views/components/footer.vue'
import { getTechnologyCenter, getTechnologyCategories } from '@/api/newscenter'
const router = useRouter()
//
const categories = ref<any[]>([])
const selectedCategoryId = ref<number | null>(null)
//
const newsData = ref<any[]>([])
const loading = ref(false)
const loadingMore = ref(false)
const error = ref('')
const currentPage = ref(1)
const pageSize = ref(6) // 6
const total = ref(0)
//
const hasMore = computed(() => {
return newsData.value.length < total.value
})
// URL
const getImageUrl = (image: string, cateId?: number) => {
if (image) {
if (image.startsWith('http')) return image
return `${import.meta.env.VITE_APP_API_URL || ''}${image}`
}
// 使
if (cateId) {
const category = categories.value.find(c => c.id === cateId)
if (category?.image) {
const catImage = category.image
if (catImage.startsWith('http')) return catImage
return `${import.meta.env.VITE_APP_API_URL || ''}${catImage}`
}
}
return ''
}
//
const formatDate = (date: string) => {
if (!date) return ''
const d = new Date(date)
const year = d.getFullYear().toString().slice(-2)
const month = (d.getMonth() + 1).toString()
const day = d.getDate().toString()
return `${year}${month}${day}`
}
const goToDetail = (id: number) => {
router.push(`/newscenter/companyNews/detail/${id}`)
}
//
const selectCategory = (categoryId: number) => {
if (selectedCategoryId.value === categoryId) {
//
return
}
selectedCategoryId.value = categoryId
//
loadNews()
}
//
const loadCategories = async () => {
try {
const response = await getTechnologyCategories()
if (response.code === 200) {
categories.value = response.data || []
//
if (categories.value.length > 0) {
selectedCategoryId.value = categories.value[0].id
loadNews()
}
}
} catch (err: any) {
console.error('加载分类错误:', err)
}
}
//
const loadMore = async () => {
if (loadingMore.value || !hasMore.value) return
loadingMore.value = true
currentPage.value++
try {
const response = await getTechnologyCenter(
currentPage.value,
pageSize.value,
selectedCategoryId.value || undefined,
)
if (response.code === 200) {
//
newsData.value = [...newsData.value, ...(response.list || [])]
total.value = response.total || 0
} else {
error.value = response.msg || '加载更多数据失败'
currentPage.value-- // 退
}
} catch (err: any) {
error.value = '加载更多数据时发生错误'
console.error('加载更多数据错误:', err)
currentPage.value-- // 退
} finally {
loadingMore.value = false
}
}
//
const loadNews = async () => {
loading.value = true
error.value = ''
currentPage.value = 1
try {
const response = await getTechnologyCenter(
currentPage.value,
pageSize.value,
selectedCategoryId.value || undefined,
)
if (response.code === 200) {
newsData.value = response.list || []
total.value = response.total || 0
} else {
error.value = response.msg || '获取数据失败'
}
} catch (err: any) {
error.value = '获取数据时发生错误'
console.error('获取数据错误:', err)
} finally {
loading.value = false
}
}
onMounted(() => {
loadCategories()
})
</script>
<style lang="scss" scoped>
.headtop {
height: 80px;
flex-shrink: 0;
}
.container {
min-height: calc(100vh - 80px);
display: flex;
flex-direction: column;
.topcontent {
height: 450px;
width: 100%;
background-image: url(@/assets/images/newscenter.jpg);
background-size: cover;
background-position: center;
flex-shrink: 0;
.top-content {
padding-top: 180px;
width: 1200px;
margin: 0 auto;
.top-content-title {
font-size: 35px;
font-weight: 600;
color: #fff;
}
.top-content-subtitle {
width: 300px;
margin-top: 20px;
padding-top: 20px;
font-size: 16px;
color: #fff;
border-top: 2px solid #fff;
}
}
}
.maincontent {
flex: 1;
width: 1200px;
margin: 80px auto;
padding: 0 20px;
.content-wrapper {
display: flex;
gap: 40px;
//
.category-sidebar {
width: 200px;
flex-shrink: 0;
.sidebar-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid #1890ff;
}
.category-list {
.category-item {
padding: 14px 20px;
margin-bottom: 8px;
background: #f8f9fa;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
font-size: 15px;
color: #333;
&:hover {
background: #e9ecef;
color: #1890ff;
}
&.active {
background: #1890ff;
color: #fff;
font-weight: 500;
}
}
}
}
//
.news-content {
flex: 1;
min-width: 0;
.loading-state,
.error-state,
.empty-state {
display: flex;
align-items: center;
justify-content: center;
padding: 60px 20px;
text-align: center;
color: #666;
font-size: 16px;
i {
margin-right: 10px;
font-size: 24px;
}
}
.error-state {
color: #f56c6c;
i {
color: #f56c6c;
}
}
.news-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 30px;
margin-bottom: 40px;
@media (max-width: 992px) {
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
@media (max-width: 576px) {
grid-template-columns: 1fr;
gap: 20px;
}
.news-card {
display: flex;
flex-direction: column;
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
cursor: pointer;
&:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform: translateY(-4px);
}
.card-image {
width: 100%;
height: 140px;
overflow: hidden;
background: #f5f5f5;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
&:hover img {
transform: scale(1.05);
}
}
.card-image-placeholder {
width: 100%;
height: 140px;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
color: #ccc;
font-size: 48px;
}
.card-content {
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
flex: 1;
.card-title-container {
display: flex;
align-items: flex-start;
gap: 8px;
flex-wrap: wrap;
.recommend-tag {
padding: 4px 10px;
background: #1890ff;
color: #fff;
font-size: 12px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
}
.top-tag {
padding: 4px 10px;
background: #ff5050;
color: #fff;
font-size: 12px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
}
.card-title {
font-size: 14px;
font-weight: 600;
color: #333;
margin: 0;
line-height: 1.4;
height: 40px;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
min-width: 0;
}
}
.card-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 10px;
color: #999;
.right-meta {
display: flex;
gap: 6px;
}
span {
margin-right: 6px;
}
.card-date {
display: flex;
align-items: center;
gap: 5px;
}
}
.card-desc {
font-size: 14px;
color: #666;
line-height: 1.6;
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 3;
line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
}
}
}
}
.load-more {
display: flex;
justify-content: center;
margin-top: 40px;
padding: 20px 0;
.load-more-btn {
padding: 12px 40px;
border: 1px solid #1890ff;
border-radius: 6px;
background: #fff;
color: #1890ff;
cursor: pointer;
transition: all 0.3s ease;
font-size: 15px;
display: flex;
align-items: center;
gap: 8px;
&:hover:not(:disabled) {
background: #1890ff;
color: #fff;
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
}
.no-more {
display: flex;
justify-content: center;
margin-top: 40px;
padding: 20px 0;
color: #999;
font-size: 14px;
}
}
}
}
.bottomcontent {
flex-shrink: 0;
}
}
</style>

View File

@ -0,0 +1,446 @@
<template>
<Header />
<div class="headtop"></div>
<div class="container">
<div class="topcontent">
<div class="top-content">
<div class="top-content-title">技术中心</div>
<div class="top-content-subtitle">Technology Center</div>
</div>
</div>
<div class="maincontent">
<!-- 加载状态 -->
<div v-if="loading" class="loading-state">
<i class="fas fa-spinner fa-spin"></i>
<span>加载中...</span>
</div>
<!-- 错误信息 -->
<div v-else-if="error" class="error-state">
<i class="fas fa-exclamation-circle"></i>
<span>{{ error }}</span>
</div>
<!-- 新闻列表 -->
<div v-else-if="newsData.length > 0" class="news-grid">
<div v-for="news in newsData" :key="news.id" class="news-card" @click="goToDetail(news.id)">
<div class="card-image" v-if="news.image">
<img :src="getImageUrl(news.image)" :alt="news.title" />
</div>
<div v-else class="card-image-placeholder">
<i class="fas fa-image"></i>
</div>
<div class="card-content">
<div class="card-title-container">
<h3 class="card-title">
<span v-if="news.top === 1" class="top-tag">置顶</span>
<span v-if="news.recommend === 1" class="recommend-tag">
推荐
</span>
{{ news.title }}
</h3>
</div>
<div class="card-meta">
<span class="card-date">
<i class="fa-regular fa-calendar-minus"></i>
{{ formatDate(news.publishdate) }}
</span>
<span class="right-meta">
<span class="card-date">
<i class="fa-regular fa-heart"></i>
{{ news.likes }}
</span>
<span class="card-date">
<i class="fa-regular fa-eye"></i>
{{ news.views }}
</span>
</span>
</div>
</div>
</div>
</div>
<!-- 无数据状态 -->
<div v-else class="empty-state">
<el-empty :image-size="200" />
</div>
<!-- 加载更多按钮 -->
<div v-if="!loading && !error && newsData.length > 0 && hasMore" class="load-more">
<button class="load-more-btn" @click="loadMore" :disabled="loadingMore">
<i v-if="loadingMore" class="fas fa-spinner fa-spin"></i>
<span v-else>加载更多</span>
</button>
</div>
<!-- 没有更多数据提示 -->
<div v-if="!loading && !error && newsData.length > 0 && !hasMore" class="no-more">
<span>已加载全部数据</span>
</div>
</div>
<div class="bottomcontent"></div>
</div>
<Footer />
</template>
<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import Header from '@/views/components/header.vue'
import Footer from '@/views/components/footer.vue'
import { getTechnologyCenter } from '@/api/newscenter'
const router = useRouter()
const newsData = ref<any[]>([])
const loading = ref(false)
const loadingMore = ref(false)
const error = ref('')
const currentPage = ref(1)
const pageSize = ref(6) // 6
const total = ref(0)
//
const hasMore = computed(() => {
return newsData.value.length < total.value
})
// URL
const getImageUrl = (image: string) => {
if (!image) return ''
if (image.startsWith('http')) return image
return `${import.meta.env.VITE_APP_API_URL || ''}${image}`
}
//
const formatDate = (date: string) => {
if (!date) return ''
const d = new Date(date)
return d.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
}
const goToDetail = (id: number) => {
router.push(`/newscenter/companyNews/detail/${id}`)
}
//
const loadMore = async () => {
if (loadingMore.value || !hasMore.value) return
loadingMore.value = true
currentPage.value++
try {
const response = await getTechnologyCenter(currentPage.value, pageSize.value)
if (response.code === 200) {
//
newsData.value = [...newsData.value, ...(response.list || [])]
total.value = response.total || 0
} else {
error.value = response.msg || '加载更多数据失败'
currentPage.value-- // 退
}
} catch (err: any) {
error.value = '加载更多数据时发生错误'
console.error('加载更多数据错误:', err)
currentPage.value-- // 退
} finally {
loadingMore.value = false
}
}
//
const loadNews = async () => {
loading.value = true
error.value = ''
currentPage.value = 1
try {
const response = await getTechnologyCenter(currentPage.value, pageSize.value)
if (response.code === 200) {
newsData.value = response.list || []
total.value = response.total || 0
} else {
error.value = response.msg || '获取数据失败'
}
} catch (err: any) {
error.value = '获取数据时发生错误'
console.error('获取数据错误:', err)
} finally {
loading.value = false
}
}
onMounted(() => {
loadNews()
})
</script>
<style lang="scss" scoped>
.headtop {
height: 80px;
flex-shrink: 0;
}
.container {
min-height: calc(100vh - 80px);
display: flex;
flex-direction: column;
.topcontent {
height: 450px;
width: 100%;
background-image: url(@/assets/images/newscenter.jpg);
background-size: cover;
background-position: center;
flex-shrink: 0;
.top-content {
padding-top: 180px;
width: 1200px;
margin: 0 auto;
.top-content-title {
font-size: 35px;
font-weight: 600;
color: #fff;
}
.top-content-subtitle {
width: 300px;
margin-top: 20px;
padding-top: 20px;
font-size: 16px;
color: #fff;
border-top: 2px solid #fff;
}
}
}
.maincontent {
flex: 1;
width: 1200px;
margin: 80px auto;
padding: 0 20px;
.loading-state,
.error-state,
.empty-state {
display: flex;
align-items: center;
justify-content: center;
padding: 60px 20px;
text-align: center;
color: #666;
font-size: 16px;
i {
margin-right: 10px;
font-size: 24px;
}
}
.error-state {
color: #f56c6c;
i {
color: #f56c6c;
}
}
.news-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
margin-bottom: 40px;
@media (max-width: 992px) {
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
@media (max-width: 576px) {
grid-template-columns: 1fr;
gap: 20px;
}
.news-card {
display: flex;
flex-direction: column;
background: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s ease;
cursor: pointer;
&:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
transform: translateY(-4px);
}
.card-image {
width: 100%;
height: 200px;
overflow: hidden;
background: #f5f5f5;
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
&:hover img {
transform: scale(1.05);
}
}
.card-image-placeholder {
width: 100%;
height: 200px;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
color: #ccc;
font-size: 48px;
}
.card-content {
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
flex: 1;
.card-title-container {
display: flex;
align-items: flex-start;
gap: 8px;
flex-wrap: wrap;
.recommend-tag {
padding: 4px 10px;
background: #1890ff;
color: #fff;
font-size: 12px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
}
.top-tag {
padding: 4px 10px;
background: #ff5050;
color: #fff;
font-size: 12px;
border-radius: 4px;
white-space: nowrap;
flex-shrink: 0;
}
.card-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 0;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
min-width: 0;
}
}
.card-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 13px;
color: #999;
.right-meta {
display: flex;
gap: 6px;
}
span {
margin-right: 6px;
}
.card-date {
display: flex;
align-items: center;
gap: 5px;
}
}
.card-desc {
font-size: 14px;
color: #666;
line-height: 1.6;
margin: 0;
display: -webkit-box;
-webkit-line-clamp: 3;
line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
flex: 1;
}
}
}
}
.load-more {
display: flex;
justify-content: center;
margin-top: 40px;
padding: 20px 0;
.load-more-btn {
padding: 12px 40px;
border: 1px solid #1890ff;
border-radius: 6px;
background: #fff;
color: #1890ff;
cursor: pointer;
transition: all 0.3s ease;
font-size: 15px;
display: flex;
align-items: center;
gap: 8px;
&:hover:not(:disabled) {
background: #1890ff;
color: #fff;
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
}
.no-more {
display: flex;
justify-content: center;
margin-top: 40px;
padding: 20px 0;
color: #999;
font-size: 14px;
}
}
.bottomcontent {
flex-shrink: 0;
}
}
</style>

184
src/views/onepage/index.vue Normal file
View File

@ -0,0 +1,184 @@
<template>
<div class="onepage-container">
<Header />
<div class="headtop"></div>
<div v-if="loading" class="loading">
<i class="fas fa-spinner fa-spin"></i>
<span>加载中...</span>
</div>
<div v-else-if="error" class="error">
<i class="fas fa-exclamation-triangle"></i>
<p>{{ error }}</p>
<button @click="loadOnePage" class="retry-btn">重试</button>
</div>
<div v-else-if="onePage" class="content">
<div class="page-wrapper" v-html="onePage.content"></div>
</div>
<div v-else class="not-found">
<i class="fas fa-file-alt"></i>
<p>单页内容不存在</p>
</div>
<Footer />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import Header from '../components/header.vue'
import Footer from '../components/footer.vue'
import { getOnePageByPath } from '@/api/index'
interface OnePage {
id: number
title: string
content: string
path: string
sort: number
status: 0 | 1
}
const route = useRoute()
const router = useRouter()
const loading = ref(false)
const error = ref('')
const onePage = ref<OnePage | null>(null)
//
const loadOnePage = async () => {
const path = route.path
if (!path || path === '/') {
router.push('/404')
return
}
// type 2
//
const matchedRoute = route.matched[route.matched.length - 1]
if (matchedRoute && matchedRoute.name && matchedRoute.name !== 'OnePage') {
// OnePage type 2
// meta
if (matchedRoute.meta && matchedRoute.meta.menuType === 2) {
router.push('/404')
return
}
}
loading.value = true
error.value = ''
try {
const result = await getOnePageByPath(path)
if (result.code === 200 && result.data) {
onePage.value = result.data
} else {
// 404
router.push('/404')
}
} catch (err: any) {
// 404
router.push('/404')
} finally {
loading.value = false
}
}
onMounted(() => {
loadOnePage()
})
</script>
<style lang="scss" scoped>
.onepage-container {
min-height: 100vh;
display: flex;
flex-direction: column;
width: 100%;
}
// 80px
.headtop {
height: 80px;
width: 100%;
flex-shrink: 0;
background-color: #F8F8F8;
}
.loading,
.error,
.not-found {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 60vh;
gap: 16px;
color: #666;
padding: 40px 20px;
flex: 1;
i {
font-size: 48px;
color: #999;
}
p {
margin: 0;
font-size: 16px;
}
}
.error {
i {
color: #f56c6c;
}
}
.retry-btn {
padding: 10px 20px;
background-color: #409eff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s;
&:hover {
background-color: #66b1ff;
}
}
.content {
flex: 1;
width: 100%;
min-height: 0; // flex
.page-wrapper {
width: 100%;
min-height: 100%;
position: relative; //
//
:deep(*) {
box-sizing: border-box;
}
//
//
:deep(.dropdown-menu:not(.site-header-dropdown-menu)) {
position: relative !important;
top: auto !important;
left: auto !important;
right: auto !important;
width: auto !important;
z-index: auto !important;
}
//
:deep(*) {
z-index: auto !important;
}
}
}
</style>

View File

@ -0,0 +1,363 @@
<script setup lang="ts">
import { ref,reactive } from "vue";
import Header from "@/views/components/header.vue";
import Footer from "@/views/components/footer.vue";
import { VideoPlay } from "@element-plus/icons-vue";
const activeIndex = ref(0);
const industryTabs = [
{
title: "制造行业",
icon: "src/assets/images/solution/14194311qxyp.png",
iconActive: "src/assets/images/solution/15172752x7hf.png",
contents: [
{ title: "制造业概述", route: "/solution/manufacture" },
{ title: "电子行业", route: "/solution/electronics" }
]
},
{
title: "服务行业",
icon: "@/assets/icons/zz1.png",
iconActive: "@/assets/icons/zz1.png",
contents: [
{ title: "服务行业概述", route: "/solution/service" }
]
},
{
title: "批发与零售",
icon: new URL("@/assets/icons/zf1.png", import.meta.url).href,
iconActive: new URL("@/assets/icons/zf2.png", import.meta.url).href,
contents: [
{ title: "贸易零售", route: "/solution/government" }
]
},
{
title: "建筑与房地产",
icon: new URL("@/assets/icons/yy1.png", import.meta.url).href,
iconActive: new URL("@/assets/icons/yy2.png", import.meta.url).href,
contents: [
{ title: "建筑行业", route: "/solution/medical" }
]
},
{
title: "快速消费品",
icon: new URL("@/assets/icons/qc1.png", import.meta.url).href,
iconActive: new URL("@/assets/icons/qc2.png", import.meta.url).href,
contents: [
{ title: "食品行业", route: "/solution/auto" }
]
}
];
const caseList = [
{
id: 111,
title: '碧桂园:数字化驱动业务创新',
desc:
'碧桂园集团,是中国最大的新型城镇化住宅开发商。采用集中及标准化的运营模式,业务包含物业发展、建安、装修、物业管理、物业投资、酒店开发和管理,以及现代农业、机器人。\n',
image: 'http://backapi.yunzer.cn/storage/uploads/2026/01/20/696ee14c17458.jpg'
},
{
id: 114,
title: '四川路桥:“财务共享助力业务腾飞”',
desc:
'四川路桥建设集团股份有限公司是国有控股上市公司中国500强企业于2003年3月在上海证券交易所挂牌交易是四川省交通系统首家A股上市企业母公司为四川省铁路产业投资集团公司。',
image: 'http://backapi.yunzer.cn/storage/uploads/2026/01/20/696eec54c8e64.png'
}
]
/* 视频弹窗 */
const showVideo = ref(false);
</script>
<template>
<Header />
<!-- Banner -->
<div class="banner">
<div class="banner-inner">
<h1>行业解决方案</h1>
<p>
金蝶行业解决方案致力于应用智能技术助力企业实现数字化转型重塑企业核心竞争力
</p>
<el-button type="primary" size="large">立即咨询</el-button>
</div>
</div>
<!-- 行业解决方案 -->
<div class="section">
<!-- Tabs-->
<div class="industry-tabs-grid">
<div
v-for="(tab, index) in industryTabs"
:key="index"
class="tab-item"
@mouseenter="activeIndex = index"
>
<div
class="tab-box"
:class="{ active: activeIndex === index }"
>
<img
:src="tab.icon"
v-show="activeIndex !== index"
/>
<img
:src="tab.iconActive"
v-show="activeIndex === index"
/>
<p class="text-xl">{{ tab.title }}</p>
</div>
</div>
</div>
<!-- 内容区 -->
<div class="industry-content">
<router-link
v-for="(item, i) in industryTabs[activeIndex].contents"
:key="i"
:to="item.route"
class="content-card"
>
<div class="card-img">
<img src="@/assets/images/noimage.png">
</div>
<div class="flex-1">
<p class="card-title">{{ item.title }}</p>
<p class=""></p>
</div>
</router-link>
</div>
</div>
<!-- 视频 -->
<div class="banner-center">
<div class="banner-center-container">
<p class="banner-center-title">金蝶助力传统制造企业由大变强</p>
<el-button type="primary" :icon="VideoPlay" @click="showVideo = true">
观看视频
</el-button>
</div>
</div>
<div class="py-10 flex flex-col items-center">
<div class="text-left w-7xl">
<div class="text-3xl mb-5">客户成功故事</div>
<div class="con3-list mb-5">
<router-link
v-for="item in caseList"
:key="item.id"
:to="`/newscenter/kingdeeNews/detail/${item.id}`"
class="con3-list-link"
>
<div class="con3-list-box">
<img
class="con3-list-box-img"
:src="item.image"
:alt="item.title"
/>
<div class="con3-list-box-content">
<p class="con3-list-content-title">
{{ item.title }}
</p>
<p class="con3-list-content-text">
{{ item.desc }}
</p>
</div>
</div>
</router-link>
</div>
<div>
<el-link type="primary" underline="never">
更多客户成功故事
</el-link>
</div>
</div>
</div>
<el-dialog v-model="showVideo" width="800px">
<video
src=""
controls
autoplay
style="width:100%"
/>
</el-dialog>
<Footer />
</template>
<style scoped lang="scss">
.banner {
height: 360px;
background: url("@/assets/images/solution/solution.png") center / cover no-repeat;
color: #fff;
.banner-inner {
width: 1200px;
margin: 0 auto;
padding-top: 110px;
h1 {
font-size: 40px;
font-weight: 600;
}
p {
width: 420px;
margin: 20px 0;
font-size: 16px;
}
}
}
.section {
width: 1300px;
margin: 80px auto;
}
/* Tabs Grid */
.industry-tabs-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 24px;
}
.tab-box {
display: flex;
flex-direction: column;
align-items: center;
height: 200px;
background: #f7f7f7;
padding-top: 10px;
text-align: center;
border-bottom: 6px solid #f7f7f7;
cursor: pointer;
transition: 0.2s;
img {
height: 67px;
margin: 30px;
}
&.active {
background: #fff;
border-bottom-color: #00ccff;
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.12);
}
}
/* Content */
.industry-content {
margin-top: 60px;
display: flex;
justify-content: center;
gap: 24px;
}
.content-card {
display: flex;
width: 260px;
padding: 20px;
border: 1px solid #eee;
background: #fff;
text-align: center;
transition: 0.2s;
&:hover {
box-shadow: 0 8px 10px rgba(0, 0, 0, 0.08);
}
.card-img {
width: 50px;
height: 53px;
}
.card-title {
font-size: 16px;
font-weight: 500;
}
}
.banner-center {
width: 100%;
height: 400px;
padding: 70px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: url(@/assets/images/solution/banner-center-pc.png) center center no-repeat;
.banner-center-container {
width: 1200px;
text-align: start;
.banner-center-title {
width: 380px;
font-size: 38px;
font-weight: 400;
line-height: 56px;
color: #fff;
margin: 28px 0;
}
}
}
.con3-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(480px, 1fr));
gap: 110px;
}
.con3-list-link {
text-decoration: none;
color: inherit;
}
/* 卡片 */
.con3-list-box {
background: #fff;
border: 1px solid #eee;
transition: all 0.25s ease;
height: 100%;
display: flex;
flex-direction: column;
&:hover {
transform: translateY(-6px);
box-shadow: 0 14px 30px rgba(0, 0, 0, 0.12);
}
}
.con3-list-box-img {
width: 100%;
height: 220px;
object-fit: cover;
background: #f5f7fa;
}
/* 文本区 */
.con3-list-box-content {
padding: 24px;
flex: 1;
background-color: #F6F6F6;
}
.con3-list-content-title {
font-size: 16px;
font-weight: 600;
color: #222;
margin-bottom: 12px;
line-height: 1.4;
}
.con3-list-content-text {
font-size: 14px;
color: #666;
line-height: 1.7;
}
</style>

View File

@ -0,0 +1,7 @@
<template>
</template>
<script lang="ts" setup>
</script>
<style scoped></style>

Some files were not shown because too many files have changed in this diff Show More