@ -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? |
@ -0,0 +1,3 @@ |
|||
{ |
|||
"recommendations": ["Vue.volar"] |
|||
} |
@ -0,0 +1,9 @@ |
|||
# Vue 3 + TypeScript + Vite |
|||
|
|||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more. |
|||
|
|||
## Recommended Setup |
|||
|
|||
- [VS Code](https://code.visualstudio.com/) + [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously Volar) and disable Vetur |
|||
|
|||
- Use [vue-tsc](https://github.com/vuejs/language-tools/tree/master/packages/tsc) for performing the same type checking from the command line, or for generating d.ts files for SFCs. |
@ -0,0 +1,9 @@ |
|||
/* eslint-disable */ |
|||
/* prettier-ignore */ |
|||
// @ts-nocheck
|
|||
// noinspection JSUnusedGlobalSymbols
|
|||
// Generated by unplugin-auto-import
|
|||
export {} |
|||
declare global { |
|||
|
|||
} |
@ -0,0 +1,18 @@ |
|||
/* eslint-disable */ |
|||
// @ts-nocheck
|
|||
// Generated by unplugin-vue-components
|
|||
// Read more: https://github.com/vuejs/core/pull/3399
|
|||
export {} |
|||
|
|||
/* prettier-ignore */ |
|||
declare module 'vue' { |
|||
export interface GlobalComponents { |
|||
ElCol: typeof import('element-plus/es')['ElCol'] |
|||
ElDialog: typeof import('element-plus/es')['ElDialog'] |
|||
ElProgress: typeof import('element-plus/es')['ElProgress'] |
|||
ElRow: typeof import('element-plus/es')['ElRow'] |
|||
HelloWorld: typeof import('./src/components/HelloWorld.vue')['default'] |
|||
RouterLink: typeof import('vue-router')['RouterLink'] |
|||
RouterView: typeof import('vue-router')['RouterView'] |
|||
} |
|||
} |
After Width: | Height: | Size: 293 KiB |
After Width: | Height: | Size: 132 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 268 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,18 @@ |
|||
<!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>Vite + Vue + TS</title> |
|||
<script type="module" crossorigin src="./assets/index-DOfL5DGB.js"></script> |
|||
<script type="module">import.meta.url;import("_").catch(()=>1);(async function*(){})().next();if(location.protocol!="file:"){window.__vite_is_modern_browser=true}</script> |
|||
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script> |
|||
</head> |
|||
<body> |
|||
<div id="app"></div> |
|||
<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script> |
|||
<script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-BoP4WWJT.js"></script> |
|||
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-BceoyPKk.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script> |
|||
</body> |
|||
</html> |
After Width: | Height: | Size: 1.5 KiB |
@ -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>Vite + Vue + TS</title> |
|||
</head> |
|||
<body> |
|||
<div id="app"></div> |
|||
<script type="module" src="/src/main.ts"></script> |
|||
</body> |
|||
</html> |
@ -0,0 +1,38 @@ |
|||
{ |
|||
"name": "hukou", |
|||
"private": true, |
|||
"version": "0.0.0", |
|||
"type": "module", |
|||
"scripts": { |
|||
"dev": "vite", |
|||
"build": "vue-tsc && vite build", |
|||
"preview": "vite preview", |
|||
"build:no-vue-tsc": "vite build" |
|||
}, |
|||
"dependencies": { |
|||
"axios": "^1.7.2", |
|||
"echarts": "^5.5.1", |
|||
"echarts-gl": "^2.0.9", |
|||
"echarts-wordcloud": "^2.1.0", |
|||
"element-plus": "^2.7.5", |
|||
"element-ui": "^2.15.14", |
|||
"vue": "^3.4.21", |
|||
"vue-count-to": "^1.0.13", |
|||
"vue-router": "^4.3.2", |
|||
"vue3-seamless-scroll": "^2.0.1" |
|||
}, |
|||
"devDependencies": { |
|||
"@types/node": "^20.14.2", |
|||
"@vitejs/plugin-legacy": "^5.4.1", |
|||
"@vitejs/plugin-vue": "^5.0.4", |
|||
"less": "^4.2.0", |
|||
"terser": "^5.31.1", |
|||
"typescript": "^5.2.2", |
|||
"unplugin-auto-import": "^0.17.6", |
|||
"unplugin-vue-components": "^0.27.0", |
|||
"vite": "^5.2.12", |
|||
"vite-plugin-svg-icons": "^2.0.1", |
|||
"vite-plugin-windicss": "^1.9.3", |
|||
"vue-tsc": "^2.0.6" |
|||
} |
|||
} |
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,13 @@ |
|||
<script setup lang="ts"> |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<router-view></router-view> |
|||
</div> |
|||
</template> |
|||
|
|||
<style> |
|||
</style> |
|||
<style scoped> |
|||
</style> |
@ -0,0 +1,207 @@ |
|||
import axios, { AxiosInstance } from 'axios'; |
|||
import { ElMessage } from 'element-plus'; |
|||
import { Local, Session } from './storage'; |
|||
|
|||
// 配置新建一个 axios 实例
|
|||
export const service = axios.create({ |
|||
baseURL: 'http://127.0.0.1:5000', |
|||
timeout: 10000, |
|||
headers: { 'Content-Type': 'application/json' }, |
|||
}) |
|||
|
|||
// token 键定义
|
|||
export const accessTokenKey = 'access-token'; |
|||
export const refreshAccessTokenKey = `x-${accessTokenKey}`; |
|||
|
|||
// 获取 token
|
|||
export const getToken = () => { |
|||
return Local.get(accessTokenKey); |
|||
}; |
|||
|
|||
// 清除 token
|
|||
export const clearAccessTokens = () => { |
|||
Local.remove(accessTokenKey); |
|||
Local.remove(refreshAccessTokenKey); |
|||
|
|||
// 清除其他
|
|||
Session.clear(); |
|||
|
|||
// 刷新浏览器
|
|||
window.location.reload(); |
|||
}; |
|||
|
|||
// axios 默认实例
|
|||
export const axiosInstance: AxiosInstance = axios; |
|||
|
|||
// 添加请求拦截器
|
|||
service.interceptors.request.use( |
|||
(config: any) => { |
|||
// // 在发送请求之前做些什么 token
|
|||
// if (Session.get('token')) {
|
|||
// (<any>config.headers).common['Authorization'] = `${Session.get('token')}`;
|
|||
// }
|
|||
|
|||
// 获取本地的 token
|
|||
const accessToken = Local.get(accessTokenKey); |
|||
if (accessToken) { |
|||
// 将 token 添加到请求报文头中
|
|||
config.headers!['Authorization'] = `Bearer ${accessToken}`; |
|||
|
|||
// 判断 accessToken 是否过期
|
|||
const jwt: any = decryptJWT(accessToken); |
|||
const exp = getJWTDate(jwt.exp as number); |
|||
|
|||
// token 已经过期
|
|||
if (new Date() >= exp) { |
|||
// 获取刷新 token
|
|||
const refreshAccessToken = Local.get(refreshAccessTokenKey); |
|||
|
|||
// 携带刷新 token
|
|||
if (refreshAccessToken) { |
|||
config.headers!['X-Authorization'] = `Bearer ${refreshAccessToken}`; |
|||
} |
|||
} |
|||
// debugger
|
|||
// get请求映射params参数
|
|||
if (config.method?.toLowerCase() === 'get' && config.data) { |
|||
let url = config.url + '?' + tansParams(config.data); |
|||
url = url.slice(0, -1); |
|||
config.data = {}; |
|||
config.url = url; |
|||
} |
|||
} |
|||
return config; |
|||
}, |
|||
(error: any) => { |
|||
// 对请求错误做些什么
|
|||
return Promise.reject(error); |
|||
} |
|||
); |
|||
|
|||
// 添加响应拦截器
|
|||
service.interceptors.response.use( |
|||
(res: any) => { |
|||
// 获取状态码和返回数据
|
|||
var status = res.status; |
|||
var serve = res.data; |
|||
|
|||
// 处理 401
|
|||
if (status === 401) { |
|||
clearAccessTokens(); |
|||
} |
|||
|
|||
// 处理未进行规范化处理的
|
|||
if (status >= 400) { |
|||
throw new Error(res.statusText || 'Request Error.'); |
|||
} |
|||
|
|||
// 处理规范化结果错误
|
|||
if (serve && serve.hasOwnProperty('errors') && serve.errors) { |
|||
throw new Error(JSON.stringify(serve.errors || 'Request Error.')); |
|||
} |
|||
|
|||
// 读取响应报文头 token 信息
|
|||
var accessToken = res.headers[accessTokenKey]; |
|||
var refreshAccessToken = res.headers[refreshAccessTokenKey]; |
|||
|
|||
// 判断是否是无效 token
|
|||
if (accessToken === 'invalid_token') { |
|||
clearAccessTokens(); |
|||
} |
|||
// 判断是否存在刷新 token,如果存在则存储在本地
|
|||
else if (refreshAccessToken && accessToken && accessToken !== 'invalid_token') { |
|||
Local.set(accessTokenKey, accessToken); |
|||
Local.set(refreshAccessTokenKey, refreshAccessToken); |
|||
} |
|||
|
|||
// 响应拦截及自定义处理
|
|||
if (serve.code === 401) { |
|||
clearAccessTokens(); |
|||
} else if (serve.code === undefined) { |
|||
return Promise.resolve(res); |
|||
} else if (serve.code !== 200) { |
|||
var message; |
|||
// 判断 serve.message 是否为对象
|
|||
if (serve.message && typeof serve.message == 'object') { |
|||
message = JSON.stringify(serve.message); |
|||
} else { |
|||
message = serve.message; |
|||
} |
|||
ElMessage.error(message); |
|||
throw new Error(message); |
|||
} |
|||
|
|||
return res; |
|||
}, |
|||
(error: any) => { |
|||
// 处理响应错误
|
|||
if (error.response) { |
|||
if (error.response.status === 401) { |
|||
clearAccessTokens(); |
|||
} |
|||
} |
|||
|
|||
// console.log(99, error)
|
|||
// 对响应错误做点什么
|
|||
if (error.message.indexOf('timeout') != -1) { |
|||
ElMessage.error('网络超时'); |
|||
} else if (error.message == 'Network Error') { |
|||
ElMessage.error('网络连接错误'); |
|||
} else { |
|||
if (error) ElMessage.error(error); |
|||
else ElMessage.error('接口路径找不到'); |
|||
} |
|||
|
|||
return Promise.reject(error); |
|||
} |
|||
); |
|||
|
|||
/** |
|||
* 参数处理 |
|||
* @param {*} params 参数 |
|||
*/ |
|||
export function tansParams(params: any) { |
|||
let result = ''; |
|||
for (const propName of Object.keys(params)) { |
|||
const value = params[propName]; |
|||
var part = encodeURIComponent(propName) + '='; |
|||
if (value !== null && value !== '' && typeof value !== 'undefined') { |
|||
if (typeof value === 'object') { |
|||
for (const key of Object.keys(value)) { |
|||
if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') { |
|||
let params = propName + '[' + key + ']'; |
|||
var subPart = encodeURIComponent(params) + '='; |
|||
result += subPart + encodeURIComponent(value[key]) + '&'; |
|||
} |
|||
} |
|||
} else { |
|||
result += part + encodeURIComponent(value) + '&'; |
|||
} |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
/** |
|||
* 解密 JWT token 的信息 |
|||
* @param token jwt token 字符串 |
|||
* @returns <any>object |
|||
*/ |
|||
export function decryptJWT(token: string): any { |
|||
token = token.replace(/_/g, '/').replace(/-/g, '+'); |
|||
var json = decodeURIComponent(escape(window.atob(token.split('.')[1]))); |
|||
return JSON.parse(json); |
|||
} |
|||
|
|||
/** |
|||
* 将 JWT 时间戳转换成 Date |
|||
* @description 主要针对 `exp`,`iat`,`nbf` |
|||
* @param timestamp 时间戳 |
|||
* @returns Date 对象 |
|||
*/ |
|||
export function getJWTDate(timestamp: number): Date { |
|||
return new Date(timestamp * 1000); |
|||
} |
|||
|
|||
// 导出 axios 实例
|
|||
export default service; |
@ -0,0 +1,58 @@ |
|||
/** |
|||
* window.localStorage 浏览器永久缓存 |
|||
* @method set 设置永久缓存 |
|||
* @method get 获取永久缓存 |
|||
* @method remove 移除永久缓存 |
|||
* @method clear 移除全部永久缓存 |
|||
*/ |
|||
export const Local = { |
|||
// 查看 v2.4.3版本更新日志
|
|||
setKey(key: string) { |
|||
// @ts-ignore
|
|||
return `${key}`; |
|||
}, |
|||
// 设置永久缓存
|
|||
set<T>(key: string, val: T) { |
|||
window.localStorage.setItem(Local.setKey(key), JSON.stringify(val)); |
|||
}, |
|||
// 获取永久缓存
|
|||
get(key: string) { |
|||
let json = <string>window.localStorage.getItem(Local.setKey(key)); |
|||
return JSON.parse(json); |
|||
}, |
|||
// 移除永久缓存
|
|||
remove(key: string) { |
|||
window.localStorage.removeItem(Local.setKey(key)); |
|||
}, |
|||
// 移除全部永久缓存
|
|||
clear() { |
|||
window.localStorage.clear(); |
|||
}, |
|||
}; |
|||
|
|||
/** |
|||
* window.sessionStorage 浏览器临时缓存 |
|||
* @method set 设置临时缓存 |
|||
* @method get 获取临时缓存 |
|||
* @method remove 移除临时缓存 |
|||
* @method clear 移除全部临时缓存 |
|||
*/ |
|||
export const Session = { |
|||
// 设置临时缓存
|
|||
set<T>(key: string, val: T) { |
|||
window.sessionStorage.setItem(Local.setKey(key), JSON.stringify(val)); |
|||
}, |
|||
// 获取临时缓存
|
|||
get(key: string) { |
|||
let json = <string>window.sessionStorage.getItem(Local.setKey(key)); |
|||
return JSON.parse(json); |
|||
}, |
|||
// 移除临时缓存
|
|||
remove(key: string) { |
|||
window.sessionStorage.removeItem(Local.setKey(key)); |
|||
}, |
|||
// 移除全部临时缓存
|
|||
clear() { |
|||
window.sessionStorage.clear(); |
|||
}, |
|||
}; |
@ -0,0 +1,18 @@ |
|||
import request from './request'; |
|||
// import type { ResultData } from './common';
|
|||
|
|||
export function getInfo(data: any) { |
|||
return request({ |
|||
url: '/api/data', |
|||
method: 'post', |
|||
data, |
|||
}); |
|||
} |
|||
// export function list(params: any) {
|
|||
// return request({
|
|||
// eslint-disable-next-line no-irregular-whitespace
|
|||
// url: "/list",
|
|||
// method: "get",
|
|||
// params,
|
|||
// });
|
|||
// }
|
@ -0,0 +1,40 @@ |
|||
DS-Font's TrueType Fonts |
|||
Font name: DS-Digital (Normal, Bold, Italic, Bold Italic), Version 1.0 |
|||
Author: Dusit Supasawat |
|||
Web Site: http://ds-font.hypermart.net |
|||
Contact me: Dusit Supasawat, 325/38 Suksawat32 Ratburana Bangkok Thailand 10140 |
|||
Email address: dusit@mailcity.com |
|||
|
|||
Thanks for trying! We hope you really enjoy this my typeface. This font is |
|||
distributed as shareware. You can use this font for a long time as you want. |
|||
After all, when you think this font can be usefulness for you. You can send |
|||
me some money, that would be way cool. |
|||
|
|||
I'm only asking $20 US shareware fee per this typeface for personal use. |
|||
And $45 US is the usual amount per this typeface for commercial use. |
|||
|
|||
Distribution: You are free to distribute this archive so long as this text |
|||
file is distributed with the archive, the font file have not been modified, |
|||
and it is understood that the font's copyright remains with the original |
|||
author (Dusit Supasawat). |
|||
|
|||
To register send your payment to: |
|||
|
|||
Dusit Supasawat |
|||
325/38 Suksawat32 Ratburana |
|||
Bangkok Thailand 10140 |
|||
|
|||
And fill out something as this order form, and send it in with your payment. |
|||
|
|||
Font name:_________________________________________ |
|||
Your information |
|||
Name:______________________________________________ |
|||
Address:___________________________________________ |
|||
City, State : _____________________________________ |
|||
Zip Code:__________________________________________ |
|||
Country:___________________________________________ |
|||
E-MAIL address:____________________________________ |
|||
|
|||
|
|||
You will receive fonts which you order by Email after registration. These fonts |
|||
will be generated for you by specify your name in font information. |
After Width: | Height: | Size: 293 KiB |
After Width: | Height: | Size: 132 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 268 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 634 B |
After Width: | Height: | Size: 647 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,38 @@ |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue' |
|||
|
|||
defineProps<{ msg: string }>() |
|||
|
|||
const count = ref(0) |
|||
</script> |
|||
|
|||
<template> |
|||
<h1>{{ msg }}</h1> |
|||
|
|||
<div class="card"> |
|||
<button type="button" @click="count++">count is {{ count }}</button> |
|||
<p> |
|||
Edit |
|||
<code>components/HelloWorld.vue</code> to test HMR |
|||
</p> |
|||
</div> |
|||
|
|||
<p> |
|||
Check out |
|||
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank" |
|||
>create-vue</a |
|||
>, the official Vue + Vite starter |
|||
</p> |
|||
<p> |
|||
Install |
|||
<a href="https://github.com/vuejs/language-tools" target="_blank">Volar</a> |
|||
in your IDE for a better DX |
|||
</p> |
|||
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p> |
|||
</template> |
|||
|
|||
<style scoped> |
|||
.read-the-docs { |
|||
color: #888; |
|||
} |
|||
</style> |
@ -0,0 +1,5 @@ |
|||
import { createApp } from 'vue' |
|||
// import './style.css'
|
|||
import App from './App.vue' |
|||
import router from './router' |
|||
createApp(App).use(router).mount('#app') |
@ -0,0 +1,22 @@ |
|||
import { createRouter, createWebHashHistory } from "vue-router"; |
|||
|
|||
const routes = [ |
|||
{ |
|||
path: '/', |
|||
name: 'home', |
|||
component: () => |
|||
import(/* webpackChunkName: "about" */ '../views/home.vue'), |
|||
}, |
|||
{ |
|||
path: '/test', |
|||
name: 'test', |
|||
component: () => |
|||
import(/* webpackChunkName: "about" */ '../views/test.vue'), |
|||
}, |
|||
] |
|||
const router = createRouter({ |
|||
history: createWebHashHistory(import.meta.env.BASE_URL), |
|||
routes, |
|||
}); |
|||
|
|||
export default router; |
@ -0,0 +1,251 @@ |
|||
<template> |
|||
<div class="count-flop" :key="state.compKey"> |
|||
<div :class="item!='.'?'data_cage':'count-flop-point'" v-for="(item, index) in state.value" :key="index"> |
|||
<div v-if="item!='.'" class="count-flop-content" :class="['rolling_' + item]"> |
|||
<!-- <div v-if="item!='.'" class="count-flop-content" :style="{transform: `translateY(-${item}0%)`}"> --> |
|||
<div v-for="(item2,index2) in state.numberList" :key="index2" class="count-flop-num">{{item2}}</div> |
|||
</div> |
|||
<div v-else class="count-flop-content">.</div> |
|||
</div> |
|||
<div v-if="suffix" class="count-flop-unit">{{suffix}}</div> |
|||
</div> |
|||
<!-- <div class="count-flop" :key="state.compKey"> |
|||
<div :class="item!='.'?'count-flop-box':'count-flop-point'" v-for="(item, index) in state.value" :key="index"> |
|||
<div v-if="item!='.'" class="count-flop-content" :class="['rolling_' + item]"> |
|||
<div v-for="(item2,index2) in state.numberList" :key="index2" class="count-flop-num">{{item2}}</div> |
|||
</div> |
|||
<div v-else class="count-flop-content">.</div> |
|||
</div> |
|||
<div v-if="suffix" class="count-flop-unit">{{suffix}}</div> |
|||
</div> --> |
|||
</template> |
|||
<script lang="ts" setup name="CountFlop"> |
|||
// import { number } from 'echarts'; |
|||
import { reactive, onMounted, watch } from 'vue'; |
|||
// 定义父组件传过来的值 |
|||
const props = defineProps({ |
|||
val: { |
|||
type: Number, |
|||
default: () => 0, |
|||
}, |
|||
suffix: { |
|||
type: String, |
|||
default: () => '', |
|||
}, |
|||
}); |
|||
const state = reactive({ |
|||
value: [0,0,0,0] as any , |
|||
numberList: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], |
|||
compKey: 0 |
|||
}); |
|||
watch( |
|||
() => props.val, |
|||
() => { |
|||
init(); |
|||
} |
|||
); |
|||
onMounted(() => { |
|||
init(); |
|||
}); |
|||
const init = () => { |
|||
let arr = props.val.toString().split(''); |
|||
if(arr.length < 4) { |
|||
for(let i = arr.length; i < 4; i++) { |
|||
arr.unshift('0'); |
|||
} |
|||
} |
|||
state.value = arr; |
|||
// state.compKey += 1; |
|||
} |
|||
</script> |
|||
<style scoped> |
|||
@font-face{font-family:electronicFont;src:url(../assets/font/DS-DIGIT.TTF)} |
|||
.data_cage { |
|||
display: block; |
|||
background-image: url(../assets/img/data_bg.png); |
|||
height: 100%; |
|||
width: 38px; |
|||
float: left; |
|||
margin-left: 1px; |
|||
color: white; |
|||
text-align: center; |
|||
font-size: 40px; |
|||
line-height: 52px; |
|||
background-repeat: no-repeat; |
|||
background-size: 100%; |
|||
} |
|||
.count-flop-num { |
|||
font-family: 'electronicFont'; |
|||
} |
|||
.count-flop { |
|||
margin: 0 10px; |
|||
display: inline-block; |
|||
font-size: 0; |
|||
/* 可更改 */ |
|||
height: 50px; |
|||
line-height: 50px; |
|||
font-size: 36px; |
|||
color: #4898f1; |
|||
} |
|||
.count-flop > div { |
|||
position: relative; |
|||
display: inline-block; |
|||
overflow: hidden; |
|||
height: 100%; |
|||
} |
|||
.count-flop-box { |
|||
/* 可更改 */ |
|||
margin-right: 5px; |
|||
width: 36px; |
|||
border: 1px solid rgba(72, 152, 241, 0.3); |
|||
line-height: 48px; |
|||
border-radius: 6px; |
|||
} |
|||
|
|||
.count-flop-point { |
|||
/* 可更改 */ |
|||
margin-right: 5px; |
|||
width: 10px; |
|||
} |
|||
|
|||
.count-flop-content { |
|||
font-family: MicrosoftYaHei-Bold; |
|||
text-align: center; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 100%; |
|||
animation-fill-mode: forwards !important; |
|||
transition: transform 2s linear; |
|||
} |
|||
|
|||
.rolling_0 { |
|||
animation: rolling_0 2.1s ease; |
|||
} |
|||
|
|||
@keyframes rolling_0 { |
|||
from { |
|||
transform: translateY(-90%); |
|||
} |
|||
to { |
|||
transform: translateY(0); |
|||
} |
|||
} |
|||
|
|||
.rolling_1 { |
|||
animation: rolling_1 3s ease; |
|||
} |
|||
|
|||
@keyframes rolling_1 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-10%); |
|||
} |
|||
} |
|||
|
|||
.rolling_2 { |
|||
animation: rolling_2 2.1s ease; |
|||
} |
|||
|
|||
@keyframes rolling_2 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-20%); |
|||
} |
|||
} |
|||
|
|||
.rolling_3 { |
|||
animation: rolling_3 3s ease; |
|||
} |
|||
|
|||
@keyframes rolling_3 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-30%); |
|||
} |
|||
} |
|||
|
|||
.rolling_4 { |
|||
animation: rolling_4 2.1s ease; |
|||
} |
|||
|
|||
@keyframes rolling_4 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-40%); |
|||
} |
|||
} |
|||
|
|||
.rolling_5 { |
|||
animation: rolling_5 3s ease; |
|||
} |
|||
|
|||
@keyframes rolling_5 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-50%); |
|||
} |
|||
} |
|||
|
|||
.rolling_6 { |
|||
animation: rolling_6 2.1s ease; |
|||
} |
|||
|
|||
@keyframes rolling_6 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-60%); |
|||
} |
|||
} |
|||
|
|||
.rolling_7 { |
|||
animation: rolling_7 3.1s ease; |
|||
} |
|||
|
|||
@keyframes rolling_7 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-70%); |
|||
} |
|||
} |
|||
|
|||
.rolling_8 { |
|||
animation: rolling_8 2.1s ease; |
|||
} |
|||
|
|||
@keyframes rolling_8 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-80%); |
|||
} |
|||
} |
|||
|
|||
.rolling_9 { |
|||
animation: rolling_9 3.6s ease; |
|||
} |
|||
|
|||
@keyframes rolling_9 { |
|||
from { |
|||
transform: translateY(0); |
|||
} |
|||
to { |
|||
transform: translateY(-90%); |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,129 @@ |
|||
<template> |
|||
<div class="boxnav" ref="geneRef" style="padding: 0 10px;"> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts" name="gene"> |
|||
import { reactive, onMounted, ref} from 'vue'; |
|||
import * as echarts from 'echarts'; |
|||
// 定义变量内容 |
|||
const geneRef = ref() |
|||
const state = reactive({ |
|||
charts: { |
|||
theme: '', |
|||
bgColor: '', |
|||
color: '#303133', |
|||
}, |
|||
}); |
|||
// 数据 |
|||
const setPie = () => { |
|||
var myChart = echarts.init(geneRef.value); |
|||
let data1 = ['肝癌','肺癌','胃癌','结直肠癌','食管癌','胰腺癌','脑胶质瘤','肾癌','膀胱癌','前列腺癌'] |
|||
let data2 = ['肝癌','肺癌','胃癌','结直肠癌','食管癌','甲状腺癌','卵巢瘤','乳腺癌','宫颈癌','子宫内膜癌'] |
|||
var option = { |
|||
color: "#04CFE4", |
|||
grid: { |
|||
top: 20, |
|||
left: 10, |
|||
right: 0, |
|||
bottom: 40 |
|||
}, |
|||
xAxis: { |
|||
type: 'category', |
|||
axisTick: false, |
|||
axisLine: { |
|||
lineStyle: { |
|||
color: "rgba(255, 129, 109,.1)", |
|||
width: 1, //这里是为了突出显示加上的 |
|||
}, |
|||
}, |
|||
axisLabel: { |
|||
interval: 0, |
|||
color: '#08DFFE', |
|||
rotate: 30, |
|||
fontSize: 12 |
|||
}, |
|||
data: data1 |
|||
}, |
|||
yAxis: { |
|||
show: false, |
|||
type: 'value', |
|||
interval: 1, |
|||
axisLine: { |
|||
lineStyle: { |
|||
color: "rgba(255, 129, 109, 0.1)", |
|||
width: 1, //这里是为了突出显示加上的 |
|||
}, |
|||
}, |
|||
axisLabel: { |
|||
color: '#fff' |
|||
}, |
|||
splitArea: { |
|||
areaStyle: { |
|||
color: "rgba(255,255,255,.5)", |
|||
}, |
|||
}, |
|||
splitLine: { |
|||
show: true, |
|||
lineStyle: { |
|||
color: "rgba(255, 129, 109, 0.1)", |
|||
width: 0.5, |
|||
type: "dashed", |
|||
}, |
|||
}, |
|||
}, |
|||
series: [ |
|||
{ |
|||
data: [1.23, 0.86, 2.11, 1.23, 0.92, 1.92, 2.92, 0.32, 0.12, 2.92], |
|||
type: "pictorialBar", |
|||
barCategoryGap: "0%", |
|||
symbol: "path://M0,10 L10,10 C5.5,10 5.5,5 5,0 C4.5,5 4.5,10 0,10 z", |
|||
label: { |
|||
show: true, |
|||
position: "top", |
|||
// distance: 15, |
|||
color: "#08DFFE", |
|||
fontWeight: "bolder", |
|||
fontSize: 12, |
|||
formatter: (a:any)=> { |
|||
return a.data + '%' |
|||
} |
|||
}, |
|||
itemStyle: { |
|||
normal: { |
|||
color: { |
|||
type: "linear", |
|||
x: 0, |
|||
y: 0, |
|||
x2: 0, |
|||
y2: 1, |
|||
colorStops: [ |
|||
{ |
|||
offset: 0, |
|||
color: "#9A11FF", |
|||
}, |
|||
{ |
|||
offset: 1, |
|||
color: "#08DFFE", |
|||
}, |
|||
], |
|||
global: false, // 缺省为 false |
|||
}, |
|||
}, |
|||
emphasis: { |
|||
opacity: 1, |
|||
}, |
|||
}, |
|||
} |
|||
] |
|||
} |
|||
myChart.setOption(option); |
|||
}; |
|||
// 页面加载时 |
|||
onMounted(() => { |
|||
setPie(); |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
</style> |
@ -0,0 +1,615 @@ |
|||
<template> |
|||
<div class="videobg style1"></div> |
|||
<div class="mainbox" style="width: 100%; height: 100%"> |
|||
<div class="head fadeInDown"> |
|||
<h1><span>湖口县全民健康大数据平台</span></h1> |
|||
<div class="timebox"> |
|||
{{state.time}}<span>{{ state.weekday }}</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<ul style="height: calc(100vh - 85px); padding: 15px 15px 15px 15px"> |
|||
<li style="width: 27%"> |
|||
<div class="box card fadeIn delay06" style="height: calc(31% - 10px)"> |
|||
<div class="tit">湖口县概况</div> |
|||
<div class="boxnav" id=""> |
|||
<ul class="drqk clearfix"> |
|||
<li> |
|||
<div class="icon"><img src="../assets/img/icon1.png" /></div> |
|||
<div> |
|||
<span>总面积</span> |
|||
<p><em>673</em><i>平方公里</i></p> |
|||
</div> |
|||
</li> |
|||
<li> |
|||
<div class="icon"><img src="../assets/img/icon2.png" /></div> |
|||
<div> |
|||
<span>户籍人口</span> |
|||
<p><em>28.67</em><i>万人</i></p> |
|||
</div> |
|||
</li> |
|||
<li> |
|||
<div class="icon"><img src="../assets/img/icon3.png" /></div> |
|||
<div> |
|||
<span>常住人口</span> |
|||
<p><em>22.06</em><i>万人</i></p> |
|||
</div> |
|||
</li> |
|||
<li> |
|||
<div class="icon"><img src="../assets/img/icon4.png" /></div> |
|||
<div> |
|||
<span>邮政编码</span> |
|||
<p><em>332500</em><i></i></p> |
|||
</div> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="box card fadeIn delay06" style="height: calc(33.33% - 10px)"> |
|||
<div class="tit">居民构成</div> |
|||
<div class="boxnav"> |
|||
<People /> |
|||
</div> |
|||
</div> |
|||
<div class="box card fadeIn delay06" style="height: calc(34%)"> |
|||
<div class="tit">医院就诊监控</div> |
|||
<Hospital /> |
|||
</div> |
|||
</li> |
|||
<li style="width: 46%"> |
|||
<div class="fadeIn delay06" style="height: calc(100% - 10px)"> |
|||
<div class="linebox"> |
|||
<span class="line1"><img src="../assets/img/line1.png" /></span> |
|||
<span class="line2"><img src="../assets/img/line2.png" /></span> |
|||
<span class="line3"><img src="../assets/img/line3.png" /></span> |
|||
<span class="line4"><img src="../assets/img/line4.png" /></span> |
|||
<span class="line5"><img src="../assets/img/line5.png" /></span> |
|||
<span class="line6"><img src="../assets/img/line6.png" /></span> |
|||
<span class="line7"><img src="../assets/img/line7.png" /></span> |
|||
</div> |
|||
|
|||
<div class="maptabs"> |
|||
<ul> |
|||
<li :class="maptabsCurrent==1? 'active':''" @click="maptabsClick(1)"><a href="#">健康数据</a></li> |
|||
<li :class="maptabsCurrent==0? 'active':''" @click="maptabsClick(0)"><a href="#">人口分布</a></li> |
|||
</ul> |
|||
</div> |
|||
|
|||
<div style="position: absolute; top: 20px; width: 100%"> |
|||
<ul class="txtnum txtnum2 clearfix"> |
|||
<li> |
|||
<div> |
|||
<p>13153</p> |
|||
<span>癌症患者管理数</span> |
|||
</div> |
|||
</li> |
|||
<li> |
|||
<div> |
|||
<p>84.8%</p> |
|||
<span>癌症患者就诊率</span> |
|||
</div> |
|||
</li> |
|||
<li> |
|||
<div> |
|||
<p>13</p> |
|||
<span>服务医院(家)</span> |
|||
</div> |
|||
</li> |
|||
<li> |
|||
<div> |
|||
<p>71.15%</p> |
|||
<span>电子健康档案开发率</span> |
|||
</div> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<div class="mapbox" id="map" style="width: 100%; height: 100%"></div> |
|||
</div> |
|||
</li> |
|||
<li style="width: 27%"> |
|||
<div |
|||
class="box card fadeIn delay06" |
|||
style="height: calc(33.33% - 10px)" |
|||
> |
|||
<div class="tit">出生死亡人口监控</div> |
|||
<div class="boxnav" id="echarts2"> |
|||
<div class="born-box"> |
|||
<span class="p_a01">今日出生人口</span> |
|||
<CountFlop :val="state.born" /> |
|||
<div class="p_a01" style="font-size: 12px;"> |
|||
环比 |
|||
<img src="../assets/img/iconup.png" height="16" style="vertical-align: sub;" alt=""> |
|||
3% |
|||
</div> |
|||
</div> |
|||
<div class="born-box"> |
|||
<span class="p_a01">今日死亡人口</span> |
|||
<CountFlop :val="state.die" /> |
|||
<div class="p_a01" style="font-size: 12px;"> |
|||
环比 |
|||
<img src="../assets/img/icondown.png" height="16" style="vertical-align: sub;" alt=""> |
|||
3% |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div |
|||
class="box card fadeIn delay06" |
|||
style="height: calc(33.33% - 10px)" |
|||
> |
|||
<div class="tit">基因健康风险数据</div> |
|||
<Gene /> |
|||
</div> |
|||
<div |
|||
class="box card fadeIn delay06" |
|||
style="height: calc(33.33% - 10px)" |
|||
> |
|||
<div class="tit">高危疾病排名TOP10</div> |
|||
<Cancer /> |
|||
</div> |
|||
</li> |
|||
</ul> |
|||
<TownDialog ref="townRef" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import './style.css' |
|||
import { reactive, onMounted, ref } from 'vue'; |
|||
import * as echarts from 'echarts'; |
|||
import 'echarts-gl'; |
|||
import gdMap from './map.json' |
|||
import People from './people.vue'; |
|||
import Hospital from './hospital.vue'; |
|||
import TownDialog from './townDialog.vue'; |
|||
import Gene from './gene.vue'; |
|||
import Cancer from './cancer.vue'; |
|||
import CountFlop from './countFlop.vue'; |
|||
const timer = ref<NodeJS.Timeout | null>(null); |
|||
const townRef = ref(); |
|||
const chinaGeoCoordMap = ref<any> ({ |
|||
双钟镇: [116.23,29.7], |
|||
流泗镇: [116.36,29.73809724307942], |
|||
马影镇: [116.29,29.68], |
|||
武山镇: [116.34,29.55], |
|||
城山镇: [116.191,29.601], |
|||
大垅乡: [116.37,29.69], |
|||
凰村镇: [116.308,29.706], |
|||
张青乡: [116.33,29.652], |
|||
均桥镇: [116.31,29.592], |
|||
付垅乡: [116.34,29.61], |
|||
舜德乡: [116.19,29.52], |
|||
流芳乡: [116.248,29.52], |
|||
}); |
|||
const state = reactive({ |
|||
list: [], |
|||
born: 16, |
|||
die: 28, |
|||
time: '', |
|||
weekday: '', |
|||
mapdata1: [ |
|||
{ name: '双钟镇', value: 150 }, |
|||
{ name: '流泗镇', value: 190 }, |
|||
{ name: '马影镇', value: 120 }, |
|||
{ name: '武山镇', value: 40 }, |
|||
{ name: '城山镇', value: 110 }, |
|||
{ name: '均桥镇', value: 60 }, |
|||
{ name: '凰村镇', value: 70 }, |
|||
{ name: '大垅乡', value: 80 }, |
|||
{ name: '张青乡', value: 50 }, |
|||
{ name: '付垅乡', value: 30 }, |
|||
{ name: '舜德乡', value: 60 }, |
|||
{ name: '流芳乡', value: 90 }, |
|||
], |
|||
mapdata2: [ |
|||
{ name: '双钟镇', value: 210 }, |
|||
{ name: '流泗镇', value: 190 }, |
|||
{ name: '马影镇', value: 220 }, |
|||
{ name: '武山镇', value: 140 }, |
|||
{ name: '城山镇', value: 110 }, |
|||
{ name: '均桥镇', value: 160 }, |
|||
{ name: '凰村镇', value: 70 }, |
|||
{ name: '大垅乡', value: 180 }, |
|||
{ name: '张青乡', value: 50 }, |
|||
{ name: '付垅乡', value: 130 }, |
|||
{ name: '舜德乡', value: 90 }, |
|||
{ name: '流芳乡', value: 120 }, |
|||
], |
|||
}) |
|||
const maptabsCurrent = ref(0); |
|||
onMounted(() => { |
|||
init(); |
|||
timer.value = setTimeout(time, 1000);//開始运行 |
|||
setInterval(() => { |
|||
state.born++; |
|||
}, 20000); |
|||
setInterval(() => { |
|||
state.die++; |
|||
}, 21000); |
|||
}) |
|||
function time() { |
|||
clearTimeout(t);//清除定时器 |
|||
let dt = new Date(); |
|||
var y = dt.getFullYear(); |
|||
var mt = dt.getMonth() + 1; |
|||
// var weekday = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; |
|||
var weekday = ["星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]; |
|||
var day = dt.getDate(); |
|||
var h = dt.getHours();//获取时 |
|||
var m = dt.getMinutes();//获取分 |
|||
var s = dt.getSeconds();//获取秒 |
|||
var toady = dt.getDay() |
|||
// alert(toady) |
|||
var t = null; |
|||
state.time = y + "-" + mt + "-" + Appendzero(day) + " " + Appendzero(h) + ":" + Appendzero(m) + ":" + Appendzero(s); |
|||
state.weekday = weekday[toady]; |
|||
function Appendzero(obj: any) { |
|||
if (obj < 10) return "0" + "" + obj; |
|||
else return obj; |
|||
} |
|||
t = setTimeout(time, 1000); //设定定时器,循环运行 |
|||
} |
|||
const maptabsClick = (i: any) => { |
|||
maptabsCurrent.value = i; |
|||
if (i === 0) |
|||
map(state.mapdata1, gdMap) |
|||
else |
|||
map(state.mapdata2, gdMap) |
|||
} |
|||
const init = () => { |
|||
map(state.mapdata1, gdMap) //加载地图 |
|||
} |
|||
var convertData = function (data: any) { |
|||
var res = [] |
|||
for (var i = 0; i < data.length; i++) { |
|||
// console.log(data[i]) |
|||
var dataItem = data[i] |
|||
var fromCoord = chinaGeoCoordMap.value[dataItem[0].name] |
|||
var toCoord = [116.36,29.79] //中心点地理坐标 |
|||
if (fromCoord && toCoord) { |
|||
res.push({ |
|||
// 飞线去往哪里 |
|||
coords:[ |
|||
fromCoord,toCoord |
|||
], |
|||
}) |
|||
// res.push([ |
|||
// // 飞线去往哪里 |
|||
// fromCoord, |
|||
// // 飞线从哪里出发 |
|||
// toCoord, |
|||
// ]) |
|||
} |
|||
} |
|||
// console.log(9999, res) |
|||
return res |
|||
} |
|||
async function map(a: any, map: any) { |
|||
var myChartmap = echarts.init(document.getElementById("map")); |
|||
myChartmap.on('click', mapClick); |
|||
if(myChartmap){ |
|||
myChartmap.clear(); |
|||
|
|||
} |
|||
|
|||
var regions = [] |
|||
var colors = "" |
|||
for (let i = 0; i < a.length; i++) { |
|||
//颜色及数据范围 |
|||
if (a[i].value < 20) { |
|||
colors = "#41a9ed" |
|||
} |
|||
if (a[i].value >= 20) { |
|||
colors = "#3c8fda" |
|||
} |
|||
if (a[i].value >= 40) { |
|||
colors = "#397dce" |
|||
} |
|||
if (a[i].value >= 60) { |
|||
colors = "#366ec3" |
|||
} |
|||
if (a[i].value >= 80) { |
|||
colors = "#335eb8" |
|||
} |
|||
if (a[i].value >= 100) { |
|||
colors = "#304ead" |
|||
} |
|||
if (a[i].value >= 120) { |
|||
colors = "#2e40a3" |
|||
} |
|||
if (a[i].value >= 140) { |
|||
colors = "#2b339a" |
|||
} |
|||
regions.push( |
|||
{ |
|||
name: a[i].name, |
|||
height: a[i].value / 15, |
|||
// height: 0, |
|||
itemStyle: { |
|||
borderWidth: 0, |
|||
// borderColor:"#00873A", |
|||
// opacity:0.95, |
|||
color: colors, |
|||
}, |
|||
} |
|||
) |
|||
|
|||
} |
|||
echarts.registerMap('湖口', map); |
|||
var viewControl = { |
|||
// autoRotate:true, |
|||
// minBeta:-3600, |
|||
// maxBeta:3600, |
|||
projection: 'perspective',// 投影方式,默认为透视投影'perspective',也支持设置为正交投影'orthographic'。 |
|||
// autoRotate: true, |
|||
autoRotateDirection: 'cw',//cw |
|||
distance: 165, |
|||
minDistance: 40, |
|||
maxDistance: 200,//最大距离 |
|||
alpha: 40, |
|||
beta: 0, |
|||
center: [-5, -5, 0], |
|||
} |
|||
let option = { |
|||
tooltip: { |
|||
}, |
|||
geo3D: { |
|||
// 地图样式 |
|||
type: 'map3D', |
|||
name: '地图', |
|||
shading: 'realistic', |
|||
regions: regions, |
|||
zlevel: 0, |
|||
regionHeight: 20, |
|||
map: '湖口', |
|||
label: { |
|||
show: false, |
|||
}, |
|||
itemStyle: { |
|||
color: '#fff', |
|||
borderWidth: 1, |
|||
borderColor: '#005eda' |
|||
}, |
|||
// 控制鼠标悬浮上去的效果 |
|||
emphasis: { |
|||
label: { |
|||
show: false, |
|||
}, |
|||
itemStyle: { |
|||
color: 'rgb(0, 192, 255)',// 鼠标移动上去的颜色 |
|||
} |
|||
}, |
|||
|
|||
light: { |
|||
main: { |
|||
color: '#00d2ff', |
|||
intensity: 1.1, |
|||
shadow: true, |
|||
shadowQuality: 'high', // 阴影的质量。可选'low', 'medium', 'high', 'ultra' [ default: 'medium' ] |
|||
alpha: 55, |
|||
beta: 30 |
|||
}, |
|||
ambient: { // 全局的环境光设置。 |
|||
color: '#fff', |
|||
intensity: 0.5 // 环境光的强度。[ default: 0.2 ] |
|||
} |
|||
}, |
|||
|
|||
viewControl: viewControl, |
|||
// data: a |
|||
}, |
|||
series: [ |
|||
{ |
|||
// 隐藏地图样式 |
|||
type: 'map3D', |
|||
name: '模拟数据', |
|||
shading: 'realistic', |
|||
zlevel: 5, |
|||
regionHeight: 5, |
|||
map: '湖口', |
|||
label: { |
|||
show: true, |
|||
formatter: function (e: any) { |
|||
if (e.data.value) { |
|||
return e.name + ":" + e.data.value |
|||
|
|||
} else { |
|||
return e.name + ":" + 0 |
|||
} |
|||
}, |
|||
distance: 0, |
|||
textStyle: { |
|||
color: '#fff', |
|||
fontFamily: "苹方", |
|||
background: 'rgba(0,0,0,0.4)', |
|||
fontSize: 14, |
|||
}, |
|||
}, |
|||
itemStyle: { |
|||
color: 'transparent', |
|||
}, |
|||
emphasis: { |
|||
label: { |
|||
show: true, |
|||
}, |
|||
itemStyle: { |
|||
color: 'transparent', |
|||
} |
|||
}, |
|||
viewControl: viewControl, |
|||
data: a |
|||
}, |
|||
] |
|||
} |
|||
option.series = option.series.concat(await setMap()); |
|||
myChartmap.setOption(option); |
|||
window.addEventListener("resize", function () { |
|||
myChartmap.resize(); |
|||
}); |
|||
} |
|||
const setMap = async () => { |
|||
let formdata = '流泗镇' // 中心点 |
|||
var series = [] as any; |
|||
var chinaDatas = [ |
|||
[{name: '双钟镇', value: 0}], |
|||
[{name: '流泗镇', value: 0}], |
|||
[{name: '马影镇', value: 0}], |
|||
[{name: '武山镇', value: 0}], |
|||
[{name: '城山镇', value: 0}], |
|||
[{name: '大垅乡', value: 0}], |
|||
[{name: '凰村镇', value: 0}], |
|||
[{name: '张青乡', value: 0}], |
|||
[{name: '均桥镇', value: 0}], |
|||
[{name: '付垅乡', value: 0}], |
|||
[{name: '舜德乡', value: 0}], |
|||
[{name: '流芳乡', value: 0}], |
|||
]; |
|||
[[formdata, chinaDatas]].forEach(function (item, i) { |
|||
series.push( |
|||
{ |
|||
type: 'lines3D', |
|||
coordinateSystem: 'geo3D', |
|||
regionHeight: 10, |
|||
effect: { |
|||
show: true, |
|||
period: 2, //箭头指向速度,值越小速度越快 |
|||
trailLength: 0.15, //特效尾迹长度[0,1]值越大,尾迹越长重 |
|||
// constantSpeed: 5, // 移动速度 |
|||
symbol: 'arrow', //箭头图标 |
|||
symbolSize: 9, //图标大小 |
|||
color: '#fcdd6e', // 图标颜色 |
|||
trailOpacity: 1, // 尾迹透明度 |
|||
trailColor: 'rgba(255, 255, 255, 0.5)' // 尾迹颜色 |
|||
}, |
|||
lineStyle: { |
|||
width: 1, // 线宽 |
|||
color: 'rgba(118 , 192, 234, 1)', // 线颜色 |
|||
opacity: 1, |
|||
normal: { |
|||
show: true, |
|||
width: 1, //尾迹线条宽度 |
|||
opacity: 1, //尾迹线条透明度 |
|||
curveness: 0.3, //尾迹线条曲直度 |
|||
color: '#fcdd6e', // 飞线颜色 |
|||
}, |
|||
// color: '#fcdd6e', |
|||
}, |
|||
blendMode: 'lighter', |
|||
data: convertData(item[1]), |
|||
}); |
|||
series.push( |
|||
{ |
|||
type: 'scatter3D', |
|||
coordinateSystem: 'geo3D', |
|||
zlevel: 1, // 控制图层深度 |
|||
rippleEffect: { |
|||
//涟漪特效 |
|||
period: 4, //动画时间,值越小速度越快 |
|||
brushType: 'stroke', //波纹绘制方式 stroke, fill |
|||
scale: 3, //波纹圆环最大限制,值越大波纹越大 |
|||
color: '#fcdd6e', |
|||
}, |
|||
label: { |
|||
normal: { |
|||
show: false, |
|||
position: 'right', //显示位置 |
|||
// offset: [5, 0], //偏移设置 |
|||
// formatter: function (params: any) { |
|||
// //圆环显示文字 |
|||
// return params.data.name |
|||
// }, |
|||
fontSize: 13, |
|||
}, |
|||
emphasis: { |
|||
show: false, |
|||
}, |
|||
}, |
|||
showEffectOn: 'render', // 动态效果在渲染时展示 |
|||
hoverAnimation: true, // 鼠标悬停时显示动画 |
|||
symbol: 'circle', |
|||
symbolSize: function (val: any) { |
|||
return 10 //圆环大小 |
|||
}, |
|||
itemStyle: { |
|||
normal: { |
|||
show: false, |
|||
color: '#fce182', |
|||
}, |
|||
}, |
|||
data: getEffectScatter(item[1]), |
|||
}, |
|||
//中心点 |
|||
{ |
|||
type: 'scatter3D', |
|||
coordinateSystem: 'geo3D', |
|||
zlevel: 2, |
|||
rippleEffect: { |
|||
period: 4, |
|||
brushType: 'stroke', |
|||
scale: 4, |
|||
color: '#38ff85', |
|||
}, |
|||
label: { |
|||
normal: { |
|||
show: false, |
|||
position: 'right', |
|||
//offset:[5, 0], |
|||
color: '#38ff85', |
|||
formatter: '{b}', |
|||
textStyle: { |
|||
color: '#38ff85', |
|||
}, |
|||
}, |
|||
emphasis: { |
|||
show: false, |
|||
color: '#38ff85', |
|||
}, |
|||
}, |
|||
symbol: 'circle', |
|||
symbolSize: 15, |
|||
itemStyle: { |
|||
color: '#38ff85', |
|||
}, |
|||
data: [ |
|||
{ |
|||
name: item[0], |
|||
value: [116.36,29.79].concat([10]), |
|||
}, |
|||
], |
|||
} |
|||
) |
|||
}) |
|||
return series |
|||
} |
|||
const getEffectScatter = (data: any) => { |
|||
var res = [] |
|||
for (var i = 0; i < data.length; i++) { |
|||
var dataItem = data[i] |
|||
res.push({ |
|||
name: dataItem[0].name, |
|||
value: chinaGeoCoordMap.value[dataItem[0].name].concat([dataItem[0].value]), |
|||
}) |
|||
} |
|||
|
|||
return res |
|||
} |
|||
const mapClick = (item:any) => { |
|||
// console.log(9999, item) |
|||
townRef.value.show(item); |
|||
} |
|||
</script> |
|||
<style scoped> |
|||
@font-face{font-family:electronicFont;src:url(../assets/font/DS-DIGIT.TTF)} |
|||
.born-box { |
|||
display: flex; |
|||
height: 45%; |
|||
line-height: 52px; |
|||
} |
|||
.p_a01 { |
|||
font-size: 15px; |
|||
color: #00aeff; |
|||
float: left; |
|||
margin-right: 1%; |
|||
} |
|||
</style> |
@ -0,0 +1,77 @@ |
|||
<template> |
|||
<div class="boxnav"> |
|||
<div class="listhead"> |
|||
<span>序号</span> |
|||
<span>医院名</span> |
|||
<span>床位数</span> |
|||
<span>就诊人数</span> |
|||
</div> |
|||
<div class="listnav scrollDiv"> |
|||
<!-- <ul> |
|||
<li v-for="(item, i) in state.hospitalList" :key="i"> |
|||
<span>{{item.index}}</span> |
|||
<span>{{item.name}}</span> |
|||
<span>{{item.bad}}</span> |
|||
<span>{{item.visit}}</span> |
|||
</li> |
|||
</ul> --> |
|||
<vue3-seamless-scroll |
|||
class="scroll" |
|||
v-model="isScroll" |
|||
:list="listData" |
|||
:step="0.3" |
|||
:hover="true" |
|||
:limit-scroll-num="3" |
|||
:wheel="true" |
|||
> |
|||
<ul> |
|||
<li v-for="item in listData" class="item"> |
|||
<span>{{item.index}}</span> |
|||
<span>{{item.name}}</span> |
|||
<span>{{item.bad}}</span> |
|||
<span>{{item.visit}}</span> |
|||
</li> |
|||
</ul> |
|||
</vue3-seamless-scroll> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts" name="hospital"> |
|||
import { reactive, onMounted, ref} from 'vue'; |
|||
import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'; |
|||
const isScroll=ref(true) |
|||
const listData = ref([ |
|||
{index: 1, name: '湖口县中医医院', bad: 854, visit: 242}, |
|||
{index: 2, name: '建民医院', bad: 854, visit: 242}, |
|||
{index: 3, name: '湖口县人民医院', bad: 854, visit: 242}, |
|||
{index: 4, name: '潘思宏诊所', bad: 854, visit: 242}, |
|||
{index: 5, name: '湖口县中医医院新园区', bad: 854, visit: 242}, |
|||
{index: 6, name: '湖口县人民医院新园区', bad: 854, visit: 242}, |
|||
{index: 7, name: '潘郭华诊所', bad: 854, visit: 242}, |
|||
{index: 8, name: '殷智诊所', bad: 854, visit: 242}, |
|||
{index: 9, name: '庐山市人民医院', bad: 854, visit: 242}, |
|||
]); |
|||
const state = reactive({ |
|||
hospitalList: [ |
|||
{index: 1, name: '湖口县中医医院', bad: 854, visit: 242}, |
|||
{index: 2, name: '建民医院', bad: 854, visit: 242}, |
|||
{index: 3, name: '湖口县人民医院', bad: 854, visit: 242}, |
|||
{index: 4, name: '潘思宏诊所', bad: 854, visit: 242}, |
|||
{index: 5, name: '湖口县中医医院新园区', bad: 854, visit: 242}, |
|||
{index: 6, name: '湖口县人民医院新园区', bad: 854, visit: 242}, |
|||
{index: 7, name: '潘郭华诊所', bad: 854, visit: 242}, |
|||
{index: 8, name: '殷智诊所', bad: 854, visit: 242}, |
|||
{index: 9, name: '庐山市人民医院', bad: 854, visit: 242}, |
|||
] |
|||
}); |
|||
// 页面加载时 |
|||
onMounted(() => { |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.user-container { |
|||
height: 100%; |
|||
} |
|||
</style> |
@ -0,0 +1,207 @@ |
|||
<template> |
|||
<div class="user-container layout-pd"> |
|||
<div style="height: 100%;" ref="peoplePie"></div> |
|||
<!-- <div style="height: 50%" ref="peopleBar"></div> --> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts" name="people"> |
|||
import { reactive, onMounted, ref} from 'vue'; |
|||
import * as echarts from 'echarts'; |
|||
// import { DataZoomComponent } from 'echarts/components'; |
|||
// echarts.use([DataZoomComponent]); |
|||
// 定义变量内容 |
|||
const peoplePie = ref() |
|||
const peopleBar = ref() |
|||
const state = reactive({ |
|||
charts: { |
|||
theme: '', |
|||
bgColor: '', |
|||
color: '#303133', |
|||
}, |
|||
}); |
|||
// 数据 |
|||
const city = reactive([ |
|||
{ value: 25835, name: '0-6岁' }, |
|||
{ value: 12335, name: '7-17岁' }, |
|||
{ value: 14835, name: '18-40岁' }, |
|||
{ value: 11935, name: '41-60岁' }, |
|||
{ value: 7335, name: '60岁以上' }, |
|||
]) |
|||
const cityName = reactive([]) // 城市-通过遍历将city的name放到cityName中 |
|||
const cityValue = reactive([]) // 值-通过遍历将city的value放到cityValue中\ |
|||
// option 配置项 |
|||
const axisAlign = () => { |
|||
var myChart = echarts.init(peopleBar.value, state.charts.theme); |
|||
var option = { |
|||
// 线性渐变,前四个参数分别是 x0, y0, x2, y2, 范围从 0 - 1,相当于在图形包围盒中的百分比,如果 globalCoord 为 `true`,则该四个值是绝对的像素位置 |
|||
color:{ |
|||
type: 'linear', |
|||
x: 0, |
|||
y: 0, |
|||
x2: 0, |
|||
y2: 1, |
|||
colorStops: [{ |
|||
offset: 0, color: '#00fefb' // 0% 处的颜色 |
|||
}, { |
|||
offset: 1, color: '#0063ce' // 100% 处的颜色 |
|||
}], |
|||
global: false // 缺省为 false |
|||
}, |
|||
/* 鼠标移入的工具提示 */ |
|||
// tooltip: { |
|||
// trigger: 'axis', |
|||
// axisPointer: { |
|||
// type: 'line' |
|||
// }, |
|||
// backgroundColor : 'rgba(0,0,0,0.4)', /* 背景色 */ |
|||
// borderColor: 'transparent', // 边框色 |
|||
// textStyle: { // 文字颜色 |
|||
// color : 'rgba(255,255,255,0.8)' |
|||
// } |
|||
// }, |
|||
/* x y 轴的文字样式 */ |
|||
textStyle:{ |
|||
color: '#4c9bfd' |
|||
}, |
|||
// 轴下方指向的颜色 |
|||
axisTick: { |
|||
lineStyle : { color : '#096b80' } |
|||
}, |
|||
/* 布局 */ |
|||
grid: { |
|||
left: '0%', |
|||
right: '0%', |
|||
bottom: '10%', |
|||
top: '4%', |
|||
show: true, // 为true时允许修改样式 |
|||
containLabel: true, |
|||
borderColor: '#096b80' /* 边框的颜色 */ |
|||
}, |
|||
/* 直角坐标系 grid 中的 x 轴 */ |
|||
xAxis: [ |
|||
{ |
|||
type: 'category', |
|||
data: cityName, /* 数据 */ |
|||
axisLabel: { |
|||
interval: 0, |
|||
// rotate: 30 |
|||
}, |
|||
axisTick: { |
|||
alignWithLabel: true |
|||
}, |
|||
} |
|||
], |
|||
/* 直角坐标系 grid 中的 y 轴 */ |
|||
yAxis: [ |
|||
{ |
|||
type: 'value', |
|||
splitLine: { // y轴分割线配置 |
|||
show:true, |
|||
lineStyle: { |
|||
color: "#096b80", |
|||
} |
|||
} |
|||
}, |
|||
], |
|||
/* 整体配置 */ |
|||
series: [ |
|||
{ |
|||
name: '人数', |
|||
type: 'bar', |
|||
barWidth: '40%', |
|||
label: { |
|||
show: true, |
|||
position: 'top' |
|||
}, |
|||
data: cityValue, |
|||
}, |
|||
] |
|||
}; |
|||
|
|||
myChart.setOption(option); |
|||
} |
|||
const setPie = () => { |
|||
var myChart = echarts.init(peoplePie.value); |
|||
var option = { |
|||
// color: ['#A0CE3A', '#31C5C0', '#1E9BD1', '#0F347B', '#585247', '#7F6AAD', '#009D85', "rgba(250,250,250,0.3)"], |
|||
grid: { |
|||
bottom: 0, |
|||
left: 0, |
|||
right: '0', |
|||
}, |
|||
series: [ |
|||
{ |
|||
radius: ['30%', '60%'], |
|||
center: ['50%', '50%'], |
|||
type: 'pie', |
|||
roseType: 'area', |
|||
label: { |
|||
normal: { |
|||
show: true, |
|||
formatter: ['{b|{b}}', '{c|{c}%}'].join('\n'), |
|||
//formatter: ['{b|{b}}','{c|{c}次}', '{d|同比:{d}%}'].join('\n'), |
|||
rich: { |
|||
c: { |
|||
color: 'yellow', |
|||
fontSize: 18, |
|||
fontFamily: '等线', |
|||
fontWeight: 'bold', |
|||
}, |
|||
b: { |
|||
color: 'rgba(255,255,255,.75)', |
|||
fontSize: 14, |
|||
// fontFamily: fontFamily, |
|||
height: 20, |
|||
}, |
|||
}, |
|||
position: 'outside', |
|||
}, |
|||
emphasis: { |
|||
show: true, |
|||
}, |
|||
}, |
|||
itemStyle: { |
|||
borderRadius: 3, |
|||
// borderColor: '#fff', |
|||
borderWidth: 2, |
|||
}, |
|||
labelLine: { |
|||
normal: { |
|||
show: true, |
|||
// length: 15, |
|||
//length2: 50 |
|||
}, |
|||
emphasis: { |
|||
show: true, |
|||
}, |
|||
}, |
|||
name: '饼图1', |
|||
data: [ |
|||
{ value: 20, name: '0-6岁' }, |
|||
{ value: 22, name: '7-17岁' }, |
|||
{ value: 28, name: '18-40岁' }, |
|||
{ value: 15, name: '41-60岁' }, |
|||
{ value: 15, name: '60岁以上' }, |
|||
] , |
|||
}, |
|||
], |
|||
} |
|||
myChart.setOption(option); |
|||
}; |
|||
// 页面加载时 |
|||
onMounted(() => { |
|||
city.map(city => { |
|||
cityName.push(city.name); |
|||
cityValue.push(city.value); |
|||
}) |
|||
// axisAlign(); |
|||
setPie(); |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.user-container { |
|||
height: 100%; |
|||
} |
|||
</style> |
@ -0,0 +1,236 @@ |
|||
@charset "utf-8";*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} |
|||
*,body{padding:0;margin:0;font-family:"PingFang SC","Lantinghei SC","Microsoft YaHei","HanHei SC","Helvetica Neue","Open Sans",Arial,"Hiragino Sans GB",微软雅黑,STHeiti,"WenQuanYi Micro Hei",SimSun,sans-serif,HYWenHei-GEW} |
|||
|
|||
body,html{height:100%} |
|||
li{list-style-type:none} |
|||
i{margin:0;padding:0;text-indent:0} |
|||
img{border:none;max-width:100%; |
|||
/* image-rendering: -webkit-optimize-contrast; */ |
|||
} |
|||
a{text-decoration:none;color:#fff} |
|||
a.active,a:focus{outline:0!important;text-decoration:none} |
|||
h1,h2,h3,h4,h5,h6,ol,p,ul{padding:0;margin:0} |
|||
a:hover{color:#06c;text-decoration:none!important} |
|||
i{font-style:normal} |
|||
|
|||
/* 滚动条 */ |
|||
::-webkit-scrollbar {width:3px;position:absolute;} |
|||
::-webkit-scrollbar-thumb {background:#ff0000} |
|||
::-webkit-scrollbar-track {background:#6c1a1a} |
|||
|
|||
body{color:#fff;font-size:14px;overflow-x:hidden; background: #000d4a url(../assets/img/bg.jpg) center center; |
|||
background-size: cover; |
|||
color: rgba(255,255,255,.75); overflow: hidden;} |
|||
|
|||
|
|||
.videobg{ position: fixed;; width: 100%; height: 100%; left: 0; top: 0; z-index: 1;left: 0; top: 0; |
|||
background: #000;background: -webkit-radial-gradient(50% 10%,farthest-corner, #2a4fa9 0%, #101e42 50%,#0b1024,#000);} |
|||
.videobg video{ object-fit: cover; filter:blur(2px); opacity: .05;filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius='5'); position: relative; } |
|||
|
|||
|
|||
|
|||
.style1,.style2{position:absolute;width:100%;height:100%;pointer-events:none;border-radius:3px} |
|||
.style2{border:none} |
|||
.style1:before{width:100%;height:1px;content:"";background:linear-gradient(to right,rgba(255,255,255,.02),rgba(108,176,255,.1),rgba(255,255,255,.02));position:absolute} |
|||
.style2::after,.style2:before{width:1px;height:100%;content:"";background:linear-gradient(to bottom,rgba(108,176,255,.04),rgba(255,255,255,0));position:absolute} |
|||
.style1:before{top:0} |
|||
.style2:before{left:-1px} |
|||
.style2:after{right:-1px} |
|||
|
|||
|
|||
|
|||
body::before{content:"";position:absolute;width:100%;opacity:1;transition:all .5s;height:100%;top:0;left:0;pointer-events:none;background-color:transparent;background-image:url(../assets/img/pattern.png);background-size:4.6875rem;background-repeat:repeat;background-attachment:initial;z-index:11;opacity:.8} |
|||
|
|||
body:after { |
|||
position: absolute; |
|||
top: 0; left: 0; |
|||
z-index: 1; |
|||
content: ""; |
|||
width: 100%; |
|||
height: 100%; |
|||
background: url(../assets/img/bg1.png) no-repeat center top; |
|||
opacity: 0.3; |
|||
pointer-events: none; |
|||
} |
|||
|
|||
.mainbox{ position: relative; z-index: 10;} |
|||
.mainbox>ul{display:flex;padding:10px 15px} |
|||
.mainbox>ul>li{width:25%;padding:0} |
|||
.mainbox>ul, |
|||
.mainbox>ul>li{ height: 100%;} |
|||
/* 标题 */ |
|||
.tit{padding:10px 10px 0 30px;font-size:16px;font-weight:500;color:#bcdcff;position:relative;font-weight:bolder;display:flex} |
|||
.tit:before{transform:rotate(45deg);border-radius:3px;position:absolute;content:"";width:6px;height:6px;border:2px solid #81bcff;left:12px;top:16px} |
|||
|
|||
/* .card{height:26vh;margin-bottom:10px;border-radius:5px;backdrop-filter:blur(3px);background:linear-gradient(135deg,rgba(247,111,0,.2),transparent,transparent);box-shadow:0 0 20px rgba(0,0,0,.1);position:relative;border:none} |
|||
.card:after{position:absolute;left:0;top:0;z-index:1;pointer-events:none;content:"";width:100%;height:100%;background:linear-gradient(315deg,rgba(255,47,47,.5),transparent,transparent)} */ |
|||
|
|||
|
|||
/* 边框&背景 */ |
|||
.card{position:relative;height:300px; margin-bottom:10px; backdrop-filter:blur(3px);background:linear-gradient(135deg,rgba(0, 169, 247, 0.2),transparent,transparent,rgba(0, 169, 247, 0.1));box-shadow:0 0 20px rgba(0,0,0,.1);} |
|||
.card::before{position:absolute;right:0;top:0;pointer-events:none;content:"";border-right:2px solid #0793ff;border-top:2px solid #0793ff;width:calc(100% - 200px);height:calc(100% - 20px); } |
|||
.card:after{position:absolute;left:190px;top:0;pointer-events:none;content:"";background:url(../assets/img/line01.png);width:70px;height:11px;} |
|||
.boxnav{padding:10px 15px;height:calc(100% - 33px);position:relative;z-index:10} |
|||
.boxnav::before{position:absolute;left:0;bottom:0;pointer-events:none;content:"";border-left:2px solid #0793ff;border-bottom:2px solid #0793ff;width:calc(100% - 100px);height:calc(100% - 50px);} |
|||
.boxnav:after{position:absolute;right:0;bottom:0;pointer-events:none;content:"";background:url(../assets/img/line02.png);width:75px;height:11px;} |
|||
.boxnav:after, |
|||
.boxnav::before, |
|||
.card:after, |
|||
.card::before{opacity: .15;} |
|||
|
|||
/* 动画 */ |
|||
.fadeIn{opacity:0;animation:fadeIn 1.5s forwards} |
|||
.fadeInDown{opacity:0;transform:translate3d(0,-100%,0);animation:fadeInDown .6s forwards} |
|||
.fadeInUp{animation:fadeInUp 1s forwards;opacity:0} |
|||
.fadeInLeft{animation:fadeInLeft .6s forwards} |
|||
.bounceIn{transform:scale(0,1);animation:bounceIn .6s forwards} |
|||
@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)} |
|||
to{opacity:1;-webkit-transform:none;transform:none} |
|||
} |
|||
@keyframes fadeIn{0%{opacity:0;transform:scale(.8)} |
|||
to{opacity:1;transform:scale(1)} |
|||
} |
|||
@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)} |
|||
to{opacity:1;-webkit-transform:none;transform:none} |
|||
} |
|||
@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)} |
|||
to{opacity:1;-webkit-transform:none;transform:none} |
|||
} |
|||
.delay02{animation-delay:.2s} |
|||
.delay04{animation-delay:.4s} |
|||
.delay06{animation-delay:.6s} |
|||
.delay08{animation-delay:.8s} |
|||
.delay1{animation-delay:1s} |
|||
.delay12{animation-delay:1.2s} |
|||
.delay14{animation-delay:1.4s} |
|||
.delay16{animation-delay:1.6s} |
|||
.delay18{animation-delay:1.8s} |
|||
.delay2{animation-delay:2s} |
|||
|
|||
/* 滚动所需 */ |
|||
.str_wrap{overflow:hidden;width:100%;position:relative;-moz-user-select:none;-khtml-user-select:none;user-select:none;white-space:nowrap} |
|||
.str_move{white-space:nowrap;position:absolute;top:0;left:0;cursor:move} |
|||
.str_move_clone{display:inline-block;vertical-align:top;position:absolute;left:100%;top:0} |
|||
.str_vertical .str_move_clone{left:0;top:100%} |
|||
.str_down .str_move_clone{left:0;bottom:100%} |
|||
.str_down .str_move,.str_vertical .str_move{white-space:normal;width:100%} |
|||
.noStop .str_move,.no_drag .str_move,.str_static .str_move{cursor:inherit} |
|||
.str_wrap img{max-width:none!important} |
|||
|
|||
.listhead{display:flex;justify-content:space-between;color:rgba(255,255,255,.5);border-bottom:1px solid rgba(255,255,255,.1)} |
|||
.listnav{height:calc(100% - 30px);border-bottom:1px solid rgba(255,255,255,.1);overflow-y: hidden;} |
|||
.listnav ul li{height:100%;display:flex;justify-content:space-between} |
|||
.listhead span,.listnav li span{padding:8px 0;text-align:center;font-size:13px;} |
|||
.listhead span{padding-top:0} |
|||
|
|||
|
|||
.listhead span:nth-child(1), |
|||
.listnav li span:nth-child(1){width: 8%; white-space: nowrap;} |
|||
|
|||
.listhead span:nth-child(2), |
|||
.listnav li span:nth-child(2){width: 52%; text-align: left; padding-right: 10px;} |
|||
.listhead span:nth-child(3), |
|||
.listnav li span:nth-child(3){width: 23%;text-align: left;} |
|||
.listhead span:nth-child(4), |
|||
.listnav li span:nth-child(4){width: 12%;white-space: nowrap;} |
|||
|
|||
.listnav ul li:nth-child(odd){background:rgba(255,255,255,.05)} |
|||
.listnav ul li{border:1px solid rgba(255,255,255,.1);border-top:none;border-bottom:none} |
|||
|
|||
|
|||
/* 数字类 */ |
|||
.txtnum{height:100%;display:flex;align-items:center; justify-content: center;} |
|||
.txtnum li{text-align:center;position:relative; padding:0 30px;} |
|||
.txtnum li>div{position: relative; z-index: 10;;} |
|||
.txtnum span{color:rgba(255,255,255,.75); display: block; padding-top: 5px; white-space: nowrap;} |
|||
.txtnum p{font-size:24px;font-style:normal;font-weight:bolder; color: #fff; display: inline; white-space: nowrap; |
|||
background:linear-gradient(0deg,#f2f9ff,#bfe0ff);font-style:normal;background-size:cover;font-family:"等线";font-weight:bolder;font-size:30px;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;text-fill-color:transparent |
|||
} |
|||
.txtnum li:after{height:100%;width:100%;content:"";left:0;top:-2px;position:absolute;background:-webkit-radial-gradient(50% 50%,farthest-corner,#0076d1 0,transparent,transparent);opacity:.4} |
|||
.txtnum li::before{height:120%;width:1px;content:"";right:0;top:-10%;position:absolute;background:linear-gradient(to bottom,transparent,#a8d6ff,transparent);opacity:.5} |
|||
.txtnum li:last-child::before{display:none} |
|||
|
|||
|
|||
.maptabs{position: absolute; left:-30px; top: 120px; z-index: 11; padding: 10px 20px;} |
|||
.maptabs li a{ display: block; transition: all .5s; color: rgba(255,255,255,.75); text-align: center; height: 48px; background: url(../assets/img/btn1.png) right top no-repeat; width: 140px; padding: 6px 0 0 10px ; |
|||
font-size: 15px; |
|||
margin: 10px 0;} |
|||
|
|||
.maptabs li.active a{ background: url(../assets/img/btn2.png) right top no-repeat; color: #fff; font-weight: bold;} |
|||
.maptabs li a:hover{ transform: translateX(10px); color: rgba(0, 191, 255, 0.85);} |
|||
.maptabs p{ padding: 15px 30px; color: #07e5ff; } |
|||
|
|||
|
|||
/* 头部大标题 */ |
|||
.head{display:flex;justify-content:center;align-items:center;} |
|||
.head h1{flex-shrink:0;background:url(../assets/img/headcenter.png) no-repeat center bottom; background-size:100% auto ;height:85px;line-height: 85px;} |
|||
.head h1 span{font-size:46px;background:linear-gradient(to bottom,#00fff7,#37cdff); padding: 0 20px; background-size:cover;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;text-fill-color:transparent;font-weight:bold; font-family:"Microsoft YaHei"; line-height: 1; letter-spacing: 2px;} |
|||
.head::after,.head::before{height:85px;content:"";width:100%} |
|||
.head::before{background:url(../assets/img/headleft.png) no-repeat right bottom;} |
|||
.head::after{background:url(../assets/img/headright.png) no-repeat left bottom; } |
|||
|
|||
.timebox{ position: absolute; right: 30px; font-size: 16px; color: #50c2ff; padding-bottom: 42px;} |
|||
.timebox span{ color: #fff; padding-left: 10px;} |
|||
|
|||
|
|||
/* .time{ position:absolute; right:15px; top:0; line-height: 66px;color:rgba(255,255,255,.7); font-size: 18px; padding-right: 15px;} */ |
|||
.map{display: flex; justify-content: center; align-items: center;} |
|||
.mapbox{width: 90%; position: relative;} |
|||
.mapbox img{width: 100%;} |
|||
|
|||
/* .others{position: absolute;width: 1920px; left: calc(50% - 960px); top: 0;} */ |
|||
.others{position: relative; height: 100%; display: flex; align-items: center; } |
|||
.others>span{ position: absolute;} |
|||
.others .img1{ top: 5px; width: 200px; right: 50px;} |
|||
.others .img2{ width: 180px; left: 130px; top: -10px} |
|||
.others .img3{ width: 100px; left: 30px; transform: rotate(45deg); top: 0px;} |
|||
|
|||
/* 图标类 */ |
|||
.drqk{height:100%;display:flex;align-items:center;flex-wrap:wrap; justify-content: center;} |
|||
.drqk li{width:50%;display:flex;align-items:center; } |
|||
.icon{display:flex;position:relative;justify-content:center;align-items:center;flex-shrink:0;margin-right:15px;padding:15px;width:60px;height:60px} |
|||
.icon::before{position:absolute;content:"";background:url(../assets/img/iconbg.png) no-repeat center center;background-size:auto 100%;width:100%;height:100%;left:0;top:0} |
|||
.drqk li span{} |
|||
.drqk li em{background:linear-gradient(0deg,#f2f9ff,#bfe0ff);font-style:normal;background-size:cover;font-family:"等线";font-weight:bolder;font-size:24px;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;text-fill-color:transparent} |
|||
|
|||
/* 背景动画类 更多模板下载:http://www.bootstrapmb.com*/ |
|||
.linebox{ position: absolute; width: 100%; transform: scale(1.3,0.65); overflow: hidden; height: 100%; left: 0; top: 15%; display: flex; justify-content: center; align-items: center;} |
|||
.linebox>span{ position: absolute; opacity: .1; width: 100%; height: 100%;} |
|||
.linebox>span img{width: 100%; height: 100%; object-fit: contain;} |
|||
.linebox .line1{ width: 30%; animation:scales1 60s linear infinite} |
|||
.linebox .line2{ width: 40%; animation:scales2 55s linear infinite} |
|||
.linebox .line3{ width: 47%; animation:scales1 50s linear infinite} |
|||
.linebox .line4{ width: 60%; animation:scales2 45s linear infinite} |
|||
.linebox .line5{ width: 20%; animation:scales1 40s linear infinite} |
|||
.linebox .line6{ width: 70%; animation:scales2 35s linear infinite} |
|||
.linebox .line7{ width: 75%; animation:scales1 30s linear infinite} |
|||
|
|||
@keyframes scales1{ |
|||
0%{transform: rotate(0deg);} |
|||
100%{transform: rotate(360deg);} |
|||
} |
|||
|
|||
@keyframes scales2{ |
|||
0%{transform: rotate(0deg);} |
|||
100%{transform: rotate(-360deg);} |
|||
} |
|||
|
|||
|
|||
.marker{animation:fadeInDown 1s forwards; cursor: pointer;position: absolute; transition: all .5s; align-items: center; |
|||
display: flex; justify-content: center; } |
|||
.marker:before{ width: 8px; height: 8px; border-radius: 5px; background: rgb(0, 255, 255); position: absolute; content: ""; transform: scale(1,.75);} |
|||
.marker:hover span{display: block;} |
|||
.marker>i{ width: 20px; height: 20px;position: absolute; display: flex; align-items: center; justify-content: center; transform: scale(1,.75);} |
|||
.marker>i::after, |
|||
.marker>i::before{ position: absolute; content: "";background: rgba(0, 179, 255, 0.7); border: 1px solid rgb(161, 203, 255);; border-radius: 100px; transform: scale(0);opacity: 0;} |
|||
.marker>i::after{ width: 150%; height: 150%;animation: fadein 2s infinite linear; } |
|||
.marker>i::before{width:200%; height:200%;animation: fadein 2s 1s infinite linear;} |
|||
|
|||
|
|||
@keyframes fadein { |
|||
0%{transform: scale(0); opacity: 0;} |
|||
50%{transform: scale(.5); opacity: 1;} |
|||
100%{transform: scale(1); opacity: 0;} |
|||
} |
|||
|
|||
|
@ -0,0 +1,217 @@ |
|||
<template> |
|||
<section class="cloud-bed"> |
|||
<div class="cloud-box"> |
|||
<span |
|||
v-for="(item, index) in listData" |
|||
:key="index" :style="item" |
|||
@click="getDataInfo(item)" |
|||
> |
|||
{{ item.name }} |
|||
</span> |
|||
</div> |
|||
</section> |
|||
</template> |
|||
<script lang="ts" setup> |
|||
import { onMounted, reactive, nextTick, ref } from 'vue'; |
|||
const listData = ref([ |
|||
{name: '缺血性心脏病', top: '40%', left: '50%', fontSize: '29px', color: 'rgb(255, 78, 105)'}, |
|||
{ name: '中风', top: '46%', left: '80%', fontSize: '20px', color: 'rgb(255, 123, 2)'}, |
|||
{name: '慢性阻塞性肺病', top: '57%', left: '59%', fontSize: '20px', color: 'rgb(92, 39, 254)'}, |
|||
{name: '下呼吸道感染', top: '23%', left: '50%', fontSize: '20px', color: 'rgb(59, 196, 199)'}, |
|||
{name: '新生儿疾病', top: '61%', left: '23%', fontSize: '20px', color: 'rgb(255, 123, 2)'}, |
|||
{name: '气管癌、支气管癌、肺癌', top: '74%', left: '53%', fontSize: '15px', color: 'rgb(29, 229, 226)'}, |
|||
{name: '阿尔兹海默症', top: '86%', left: '59%', fontSize: '15px', color: '#aaa'}, |
|||
{name: '腹泻', top: '25%', left: '26%', fontSize: '15px', color: 'rgb(8, 199, 146)'}, |
|||
{name: '糖尿病', top: '10%', left: '50%', fontSize: '12px', color: 'rgb(92, 39, 254)'}, |
|||
{name: '肾病', top: '11%', left: '40%', fontSize: '12px', color: '#58D5FF'}, |
|||
]); |
|||
const state = reactive({ |
|||
timer: 10, // 球体转动速率 |
|||
radius: 0, // 词云球体面积大小 |
|||
dtr: Math.PI/380, //鼠标滑过球体转动速度 |
|||
active: false, // 默认加载是否开启转动 |
|||
lasta: 0, // 上下转动 |
|||
lastb: 0.5, // 左右转动 |
|||
distr: true, |
|||
tspeed: 0, // 鼠标移动上去时球体转动 |
|||
mouseX: 0, |
|||
mouseY: 0, |
|||
tagAttrList: [], |
|||
tagContent: null, |
|||
cloudContent: null as any , |
|||
sinA: '', |
|||
cosA: '', |
|||
sinB: '', |
|||
cosB: '', |
|||
sinC: '', |
|||
cosC: '', |
|||
}) |
|||
onMounted(() => { |
|||
nextTick(() => { |
|||
state.radius = document.querySelector('.cloud-box').offsetWidth / 2 |
|||
initWordCloud() |
|||
}) |
|||
}) |
|||
// 获取点击文本信息 |
|||
const getDataInfo = (item:any) => { |
|||
console.log(item, 'item') |
|||
}; |
|||
const initWordCloud = () => { |
|||
state.cloudContent = document.querySelector('.cloud-box'); |
|||
state.tagContent = state.cloudContent.getElementsByTagName('span'); |
|||
for (let i = 0; i < state.tagContent.length; i++) { |
|||
let tagObj = {}; |
|||
tagObj.offsetWidth = state.tagContent[i].offsetWidth; |
|||
tagObj.offsetHeight = state.tagContent[i].offsetHeight; |
|||
state.tagAttrList.push(tagObj); |
|||
} |
|||
sineCosine(0, 0, 0); |
|||
positionAll(); |
|||
state.cloudContent.onmouseover = () => { |
|||
state.active=true; |
|||
}; |
|||
state.cloudContent.onmouseout = () => { |
|||
state.active=false; |
|||
}; |
|||
state.cloudContent.onmousemove = (ev: any) => { |
|||
let oEvent = window.event || ev; |
|||
state.mouseX = oEvent.clientX - (state.cloudContent.offsetLeft + state.cloudContent.offsetWidth/2); |
|||
state.mouseY = oEvent.clientY - (state.cloudContent.offsetTop + state.cloudContent.offsetHeight/2); |
|||
state.mouseX/= 5; |
|||
state.mouseY/= 5; |
|||
}; |
|||
setInterval(update, state.timer); |
|||
}; |
|||
const positionAll = () => { |
|||
let phi = 0; |
|||
let theta = 0; |
|||
let max = state.tagAttrList.length; |
|||
let aTmp = []; |
|||
let oFragment = document.createDocumentFragment(); |
|||
//随机排序 |
|||
for (let i=0; i < state.tagContent.length; i++) { |
|||
aTmp.push(state.tagContent[i]); |
|||
} |
|||
aTmp.sort(() => { |
|||
return Math.random() < 0.5 ? 1 : -1; |
|||
}); |
|||
for (let i = 0; i < aTmp.length; i++) { |
|||
oFragment.appendChild(aTmp[i]); |
|||
} |
|||
state.cloudContent.appendChild(oFragment); |
|||
for(let i = 1; i < max + 1; i++){ |
|||
if (state.distr) { |
|||
phi = Math.acos(-1 + (2 * i - 1) / max); |
|||
theta = Math.sqrt(max * Math.PI) * phi; |
|||
} else { |
|||
phi = Math.random() * (Math.PI); |
|||
theta = Math.random() * (2 * Math.PI); |
|||
} |
|||
//坐标变换 |
|||
state.tagAttrList[i-1].cx = state.radius * Math.cos(theta) * Math.sin(phi); |
|||
state.tagAttrList[i-1].cy = state.radius * Math.sin(theta) * Math.sin(phi); |
|||
state.tagAttrList[i-1].cz = state.radius * Math.cos(phi); |
|||
state.tagContent[i-1].style.left = state.tagAttrList[i-1].cx + state.cloudContent.offsetWidth / 2 - state.tagAttrList[i-1].offsetWidth / 2 + 'px'; |
|||
state.tagContent[i-1].style.top = state.tagAttrList[i-1].cy + state.cloudContent.offsetHeight / 2 - state.tagAttrList[i-1].offsetHeight / 2 + 'px'; |
|||
} |
|||
}; |
|||
const update = () => { |
|||
let angleBasicA; |
|||
let angleBasicB; |
|||
|
|||
if (state.active) { |
|||
angleBasicA = (-Math.min(Math.max(-state.mouseY, -200 ), 200) / state.radius) * state.tspeed; |
|||
angleBasicB = (Math.min(Math.max(-state.mouseX, -200 ), 200) / state.radius) * state.tspeed; |
|||
} else { |
|||
angleBasicA = state.lasta * 0.98; |
|||
angleBasicB = state.lastb * 0.98; |
|||
} |
|||
|
|||
//默认转动是后是否需要停下 |
|||
// lasta=a; |
|||
// lastb=b; |
|||
|
|||
// if(Math.abs(a)<=0.01 && Math.abs(b)<=0.01) |
|||
// { |
|||
// return; |
|||
// } |
|||
sineCosine(angleBasicA, angleBasicB, 0); |
|||
for(let j = 0; j < state.tagAttrList.length; j++) { |
|||
let rx1 = state.tagAttrList[j].cx; |
|||
let ry1 = state.tagAttrList[j].cy * state.cosA + state.tagAttrList[j].cz * (-state.sinA); |
|||
let rz1 = state.tagAttrList[j].cy * state.sinA + state.tagAttrList[j].cz * state.cosA; |
|||
|
|||
let rx2 = rx1 * state.cosB + rz1 * state.sinB; |
|||
let ry2 = ry1; |
|||
let rz2 = rx1 * (-state.sinB) + rz1 * state.cosB; |
|||
|
|||
let rx3 = rx2 * state.cosC + ry2 * (-state.sinC); |
|||
let ry3 = rx2 * state.sinC + ry2 * state.cosC; |
|||
let rz3 = rz2; |
|||
state.tagAttrList[j].cx = rx3; |
|||
state.tagAttrList[j].cy = ry3; |
|||
state.tagAttrList[j].cz = rz3; |
|||
|
|||
let per = 350 / (350 + rz3); |
|||
|
|||
state.tagAttrList[j].x = rx3 * per - 2; |
|||
state.tagAttrList[j].y = ry3 * per; |
|||
state.tagAttrList[j].scale = per; |
|||
state.tagAttrList[j].alpha = per; |
|||
|
|||
state.tagAttrList[j].alpha = (state.tagAttrList[j].alpha - 0.6) * (10/6); |
|||
} |
|||
doPosition(); |
|||
depthSort(); |
|||
} |
|||
const doPosition =() => { |
|||
let len = state.cloudContent.offsetWidth/2; |
|||
let height = state.cloudContent.offsetHeight/2; |
|||
for (let i=0;i < state.tagAttrList.length;i++) { |
|||
state.tagContent[i].style.left = state.tagAttrList[i].cx + len - state.tagAttrList[i].offsetWidth/2 + 'px'; |
|||
state.tagContent[i].style.top = state.tagAttrList[i].cy + height - state.tagAttrList[i].offsetHeight/2 + 'px'; |
|||
state.tagContent[i].style.fontSize = Math.ceil(12 * state.tagAttrList[i].scale/2) + 8 + 'px'; |
|||
state.tagContent[i].style.filter = "alpha(opacity="+100 * state.tagAttrList[i].alpha+")"; |
|||
state.tagContent[i].style.opacity = state.tagAttrList[i].alpha; |
|||
} |
|||
}; |
|||
const depthSort = () => { |
|||
let aTmp = []; |
|||
for (let i = 0; i < state.tagContent.length; i++) { |
|||
aTmp.push(state.tagContent[i]); |
|||
} |
|||
aTmp.sort((item1, item2) => item2.cz - item1.cz); |
|||
for (let i = 0; i < aTmp.length; i++) { |
|||
aTmp[i].style.zIndex=i; |
|||
} |
|||
} |
|||
const sineCosine = (a, b, c) => { |
|||
state.sinA = Math.sin(a * state.dtr); |
|||
state.cosA = Math.cos(a * state.dtr); |
|||
state.sinB = Math.sin(b * state.dtr); |
|||
state.cosB = Math.cos(b * state.dtr); |
|||
state.sinC = Math.sin(c * state.dtr); |
|||
state.cosC = Math.cos(c * state.dtr); |
|||
} |
|||
</script> |
|||
<style scoped lang="less"> |
|||
.cloud-bed { |
|||
width: 380px; |
|||
height: 170px; |
|||
.cloud-box{ |
|||
position:relative; |
|||
margin:20px auto 0px; |
|||
width: 100%; |
|||
height: 100%; |
|||
background: #00000000; |
|||
span{ |
|||
position: absolute; |
|||
padding: 3px 6px; |
|||
top: 0px; |
|||
font-weight: bold; |
|||
text-decoration:none; |
|||
left:0px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,450 @@ |
|||
<template> |
|||
<el-dialog |
|||
v-model="dialogVisible" |
|||
:title="choseItem?.name + '健康大数据'" |
|||
class="hukou-dialog" |
|||
width="60%" |
|||
><div> |
|||
<el-row :gutter="20"> |
|||
<el-col :span="15" class="box card fadeIn delay06" style=" height: 200px;"> |
|||
<div class="tit">{{choseItem?.name}}人更高了</div> |
|||
<div class="boxnav people-content"> |
|||
<div> |
|||
<div>18-44岁平均身高</div> |
|||
<div class="man-box"> |
|||
<div class="man-box-item"> |
|||
<img src="../assets/img/man.png" alt=""> |
|||
<div>169.7厘米</div> |
|||
</div> |
|||
<div class="man-box-item"> |
|||
<img src="../assets/img/woman.png" alt=""> |
|||
<div>158.1厘米</div> |
|||
</div> |
|||
</div> |
|||
<div>与2015年相比分别增加</div> |
|||
<div><span class="largText">1.2厘米</span> 和 <span class="largText">0.8厘米</span></div> |
|||
</div> |
|||
<div> |
|||
<div>6-17岁平均身高</div> |
|||
<div style="margin-top: 15px;">与2015年相比分别增加</div> |
|||
<div class="man-box"> |
|||
<div class="man-box-item"> |
|||
<img src="../assets/img/man_cld.png" alt=""> |
|||
<div class="largText">1.6厘米</div> |
|||
</div> |
|||
<div class="man-box-item"> |
|||
<img src="../assets/img/woman_cld.png" alt=""> |
|||
<div class="largText">1厘米</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</el-col> |
|||
<el-col :span="8" class="box card fadeIn delay06" style="margin-left: 20px; height: 200px;position:relative;"> |
|||
<div class="tit">{{choseItem?.name}}人更胖了</div> |
|||
<div class="weight-text"> |
|||
<span>超重肥胖率继续上升</span> |
|||
<img src="../assets/img/weight.png" alt=""> |
|||
</div> |
|||
<div class="user-container layout-pd" ref="weightRef" style="height: 200px;"></div> |
|||
</el-col> |
|||
</el-row> |
|||
<div |
|||
class="box card fadeIn delay06" |
|||
style="height: calc(33.33% - 10px)" |
|||
> |
|||
<div class="tit">{{choseItem?.name}}人更健康了</div> |
|||
<div class="user-container layout-pd" ref="geneRef" style="height: 200px;"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<template #footer> |
|||
</template> |
|||
</el-dialog> |
|||
</template> |
|||
<script lang="ts" setup> |
|||
import { ref } from 'vue'; |
|||
const dialogVisible = ref(false); |
|||
const choseItem = ref<any>({}); |
|||
import * as echarts from 'echarts'; |
|||
const show = (item: any) => { |
|||
dialogVisible.value = true; |
|||
choseItem.value = item; |
|||
setTimeout(() => { |
|||
setPie(); |
|||
setCharts(); |
|||
}, 100); |
|||
} |
|||
const weightRef = ref(); |
|||
const geneRef = ref(); |
|||
const setPie = () => { |
|||
var myChart = echarts.init(weightRef.value); |
|||
let data = ['成年居民','6-17岁','6岁以下'] |
|||
// let data1 = ['肝癌','肺癌','胃癌','结直肠癌','食管癌','胰腺癌','脑胶质瘤','肾癌','膀胱癌','前列腺癌'] |
|||
// let data2 = ['肝癌','肺癌','胃癌','结直肠癌','食管癌','甲状腺癌','卵巢瘤','乳腺癌','宫颈癌','子宫内膜癌'] |
|||
var option = { |
|||
// color: "#04CFE4", |
|||
color:{ |
|||
type: 'linear', |
|||
x: 0, |
|||
y: 0, |
|||
x2: 0, |
|||
y2: 1, |
|||
colorStops: [{ |
|||
offset: 0, color: '#00fefb' // 0% 处的颜色 |
|||
}, { |
|||
offset: 1, color: '#0063ce' // 100% 处的颜色 |
|||
}], |
|||
global: false // 缺省为 false |
|||
}, |
|||
grid: { |
|||
top: '30%', |
|||
left: 10, |
|||
right: 0, |
|||
bottom: '30%' |
|||
}, |
|||
xAxis: { |
|||
type: 'category', |
|||
axisTick: false, |
|||
axisLine: { |
|||
lineStyle: { |
|||
color: "rgba(255, 129, 109,.1)", |
|||
width: 1, //这里是为了突出显示加上的 |
|||
}, |
|||
}, |
|||
axisLabel: { |
|||
interval: 0, |
|||
color: '#08DFFE', |
|||
// rotate: 30, |
|||
fontSize: 12 |
|||
}, |
|||
data: data |
|||
}, |
|||
yAxis: { |
|||
show: false, |
|||
type: 'value', |
|||
interval: 1, |
|||
axisLine: { |
|||
lineStyle: { |
|||
color: "rgba(255, 129, 109, 0.1)", |
|||
width: 1, //这里是为了突出显示加上的 |
|||
}, |
|||
}, |
|||
axisLabel: { |
|||
color: '#fff' |
|||
}, |
|||
splitArea: { |
|||
areaStyle: { |
|||
color: "rgba(255,255,255,.5)", |
|||
}, |
|||
}, |
|||
splitLine: { |
|||
show: true, |
|||
lineStyle: { |
|||
color: "rgba(255, 129, 109, 0.1)", |
|||
width: 0.5, |
|||
type: "dashed", |
|||
}, |
|||
}, |
|||
}, |
|||
series: [ |
|||
{ |
|||
data: [50, 19, 10.4], |
|||
type: 'bar', |
|||
barWidth: '40%', |
|||
label: { |
|||
show: true, |
|||
color: "#08DFFE", |
|||
fontWeight: "bolder", |
|||
fontSize: 12, |
|||
position: 'top' |
|||
}, |
|||
} |
|||
] |
|||
} |
|||
myChart.setOption(option); |
|||
}; |
|||
const setCharts = () => { |
|||
var myChart = echarts.init(geneRef.value); |
|||
let color = ["#0090FF", "#36CE9E", "#FFC005", "#FF515A", "#8B5CFF", "#00CA69"]; |
|||
let option = { |
|||
backgroundColor: 'rgba(0,0,0,0.2)', |
|||
color: color, |
|||
legend: { |
|||
right: 10, |
|||
left: 0, |
|||
top: 10, |
|||
textStyle: { |
|||
color: "#fff", |
|||
}, |
|||
}, |
|||
tooltip: { |
|||
trigger: "axis", |
|||
formatter: function (params: any) { |
|||
let html = ""; |
|||
params.forEach((v: any) => { |
|||
html += `<div style="color: #666;font-size: 14px;line-height: 24px"> |
|||
<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${ |
|||
color[v.componentIndex] |
|||
};"></span> |
|||
${v.seriesName}.${v.name} |
|||
<span style="color:${ |
|||
color[v.componentIndex] |
|||
};font-weight:700;font-size: 18px">${v.value}</span> |
|||
${v.componentIndex===1?'岁':'%'}`; |
|||
}); |
|||
|
|||
return html; |
|||
}, |
|||
extraCssText: |
|||
"background: #fff; border-radius: 0;box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);color: #333;", |
|||
axisPointer: { |
|||
type: "shadow", |
|||
shadowStyle: { |
|||
color: "rgba(0,0,0,.2)", |
|||
shadowColor: "rgba(225,225,225,1)", |
|||
shadowBlur: 5, |
|||
}, |
|||
}, |
|||
}, |
|||
grid: { |
|||
top: '10%', |
|||
bottom: 0, |
|||
containLabel: true, |
|||
}, |
|||
xAxis: [ |
|||
{ |
|||
type: "category", |
|||
boundaryGap: false, |
|||
axisLabel: { |
|||
formatter: "{value}年", |
|||
rotate: 30, |
|||
textStyle: { |
|||
color: "#fff", |
|||
}, |
|||
}, |
|||
axisLine: { |
|||
lineStyle: { |
|||
color: "#fff", |
|||
}, |
|||
}, |
|||
data: ["2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023"], |
|||
}, |
|||
], |
|||
yAxis: [ |
|||
{ |
|||
type: "value", |
|||
name: "单位:万千瓦时", |
|||
axisLabel: { |
|||
textStyle: { |
|||
color: "#fff", |
|||
}, |
|||
}, |
|||
nameTextStyle: { |
|||
color: "#fff", |
|||
fontSize: 12, |
|||
lineHeight: 40, |
|||
}, |
|||
splitLine: { |
|||
show: false |
|||
}, |
|||
axisLine: { |
|||
show: false, |
|||
}, |
|||
axisTick: { |
|||
show: false, |
|||
}, |
|||
}, |
|||
], |
|||
series: [ |
|||
{ |
|||
name: "疫苗接种率", |
|||
type: "line", |
|||
// smooth: true, |
|||
// showSymbol: false,/ |
|||
symbolSize: 8, |
|||
zlevel: 3, |
|||
lineStyle: { |
|||
normal: { |
|||
color: color[0], |
|||
shadowBlur: 3, |
|||
shadowColor: hexToRgba(color[0], 0.5), |
|||
shadowOffsetY: 8, |
|||
}, |
|||
}, |
|||
areaStyle: { |
|||
normal: { |
|||
color: new echarts.graphic.LinearGradient( |
|||
0, |
|||
0, |
|||
0, |
|||
1, |
|||
[ |
|||
{ |
|||
offset: 0, |
|||
color: hexToRgba(color[0], 0.3), |
|||
}, |
|||
{ |
|||
offset: 1, |
|||
color: hexToRgba(color[0], 0.1), |
|||
}, |
|||
], |
|||
false |
|||
), |
|||
shadowColor: hexToRgba(color[0], 0.1), |
|||
shadowBlur: 10, |
|||
}, |
|||
}, |
|||
data: [72.6, 78.8, 71.3, 83.2, 64.2, 79.2, 85.2, 86.2,84.5, 82.6, 87.2, 88.2, 89.2, 90.2], |
|||
}, |
|||
{ |
|||
name: "居民人均寿命", |
|||
type: "line", |
|||
// smooth: true, |
|||
// showSymbol: false, |
|||
symbolSize: 8, |
|||
zlevel: 3, |
|||
lineStyle: { |
|||
normal: { |
|||
color: color[1], |
|||
shadowBlur: 3, |
|||
shadowColor: hexToRgba(color[1], 0.5), |
|||
shadowOffsetY: 8, |
|||
}, |
|||
}, |
|||
areaStyle: { |
|||
normal: { |
|||
color: new echarts.graphic.LinearGradient( |
|||
0, |
|||
0, |
|||
0, |
|||
1, |
|||
[ |
|||
{ |
|||
offset: 0, |
|||
color: hexToRgba(color[1], 0.3), |
|||
}, |
|||
{ |
|||
offset: 1, |
|||
color: hexToRgba(color[1], 0.1), |
|||
}, |
|||
], |
|||
false |
|||
), |
|||
shadowColor: hexToRgba(color[1], 0.1), |
|||
shadowBlur: 10, |
|||
}, |
|||
}, |
|||
data: [65.4, 68.6, 70.58, 73.2, 73.3, 73.4, 75.6, 73.5, 73.6,76.8, 73.7, 73.8, 73.9, 83.8], |
|||
}, |
|||
{ |
|||
name: "重大疾病发病率", |
|||
type: "line", |
|||
// smooth: true, |
|||
// showSymbol: false, |
|||
symbolSize: 8, |
|||
zlevel: 3, |
|||
lineStyle: { |
|||
normal: { |
|||
color: color[2], |
|||
shadowBlur: 3, |
|||
shadowColor: hexToRgba(color[2], 0.5), |
|||
shadowOffsetY: 8, |
|||
}, |
|||
}, |
|||
areaStyle: { |
|||
normal: { |
|||
color: new echarts.graphic.LinearGradient( |
|||
0, |
|||
0, |
|||
0, |
|||
1, |
|||
[ |
|||
{ |
|||
offset: 0, |
|||
color: hexToRgba(color[2], 0.3), |
|||
}, |
|||
{ |
|||
offset: 1, |
|||
color: hexToRgba(color[2], 0.1), |
|||
}, |
|||
], |
|||
false |
|||
), |
|||
shadowColor: hexToRgba(color[2], 0.1), |
|||
shadowBlur: 10, |
|||
}, |
|||
}, |
|||
data: [45.4, 28.6, 20.58, 13.2, 13.3, 13.4, 25.6, 23.5, 13.6,16.8, 43.7, 3.8, 3.9, 13.8], |
|||
}, |
|||
], |
|||
} |
|||
myChart.setOption(option); |
|||
}; |
|||
const hexToRgba = (hex: any, opacity: any) => { |
|||
let rgbaColor = ""; |
|||
let reg = /^#[\da-f]{6}$/i; |
|||
if (reg.test(hex)) { |
|||
rgbaColor = `rgba(${parseInt("0x" + hex.slice(1, 3))},${parseInt( |
|||
"0x" + hex.slice(3, 5) |
|||
)},${parseInt("0x" + hex.slice(5, 7))},${opacity})`; |
|||
} |
|||
return rgbaColor; |
|||
}; |
|||
// 导出对象 |
|||
defineExpose({ show }); |
|||
</script> |
|||
<style> |
|||
.hukou-dialog{ |
|||
background-color: transparent; |
|||
background-image: url(../assets/img/eath.png) ; |
|||
background-size: 100% 100%; |
|||
} |
|||
.hukou-dialog .el-dialog__header { |
|||
background: transparent; |
|||
color: #00fff7; |
|||
} |
|||
.hukou-dialog .el-dialog__header .el-dialog__title { |
|||
color: #00fff7; |
|||
} |
|||
.hukou-dialog .el-dialog__footer { |
|||
padding: 0; |
|||
} |
|||
</style> |
|||
<style scoped> |
|||
.drqk { |
|||
display: block; |
|||
margin-top: 4%; |
|||
} |
|||
.weight-text { |
|||
position: absolute; |
|||
right: 8%; |
|||
top: 12%; |
|||
color: #bfe0ff; |
|||
} |
|||
.weight-text img { |
|||
width: 40px; |
|||
} |
|||
.drqk li { |
|||
display: inline-block; |
|||
margin-top: 10px; |
|||
} |
|||
.people-content { |
|||
display: flex; |
|||
justify-content: space-around; |
|||
} |
|||
.man-box { |
|||
display: flex; |
|||
justify-content: space-around; |
|||
} |
|||
.boxnav { |
|||
text-align: center; |
|||
color: #bfe0ff; |
|||
} |
|||
.man-box-item img { |
|||
width: 50px; |
|||
} |
|||
.largText { |
|||
font-size: 1.2rem; |
|||
} |
|||
</style> |
@ -0,0 +1 @@ |
|||
/// <reference types="vite/client" />
|
@ -0,0 +1,32 @@ |
|||
{ |
|||
"compilerOptions": { |
|||
"target": "ES2020", |
|||
"useDefineForClassFields": true, |
|||
"module": "ESNext", |
|||
"lib": ["ES2020", "DOM", "DOM.Iterable"], |
|||
"skipLibCheck": true, |
|||
"moduleResolution": "node", |
|||
// "paths": { |
|||
// "@/*": [ |
|||
// "src/*" |
|||
// ] |
|||
// }, |
|||
// "baseUrl": ".", |
|||
|
|||
/* Bundler mode */ |
|||
// "moduleResolution": "bundler", |
|||
"allowImportingTsExtensions": true, |
|||
"resolveJsonModule": true, |
|||
"isolatedModules": true, |
|||
"noEmit": true, |
|||
"jsx": "preserve", |
|||
|
|||
/* Linting */ |
|||
"strict": true, |
|||
"noUnusedLocals": true, |
|||
"noUnusedParameters": true, |
|||
"noFallthroughCasesInSwitch": true |
|||
}, |
|||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"], |
|||
"references": [{ "path": "./tsconfig.node.json" }] |
|||
} |
@ -0,0 +1,11 @@ |
|||
{ |
|||
"compilerOptions": { |
|||
"composite": true, |
|||
"skipLibCheck": true, |
|||
"module": "ESNext", |
|||
"moduleResolution": "bundler", |
|||
"allowSyntheticDefaultImports": true, |
|||
"strict": true |
|||
}, |
|||
"include": ["vite.config.ts"] |
|||
} |
@ -0,0 +1,56 @@ |
|||
import path from 'path' |
|||
import { defineConfig } from 'vite' |
|||
import type { Plugin, PluginOption } from 'vite' |
|||
import vue from '@vitejs/plugin-vue' |
|||
import AutoImport from 'unplugin-auto-import/vite' |
|||
import Components from 'unplugin-vue-components/vite' |
|||
import legacy from '@vitejs/plugin-legacy' |
|||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' |
|||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' |
|||
import WindiCSS from 'vite-plugin-windicss' |
|||
export default defineConfig(({ mode, command }) => { |
|||
const isBuild = command === 'build' // 是否是打包环境的判断
|
|||
const plugins: (Plugin | Plugin[] | PluginOption[])[] = [ |
|||
vue(), |
|||
WindiCSS(), |
|||
AutoImport({ |
|||
resolvers: [ElementPlusResolver()], |
|||
}), |
|||
Components({ |
|||
resolvers: [ElementPlusResolver()], |
|||
directoryAsNamespace: true, |
|||
}), |
|||
|
|||
createSvgIconsPlugin({ |
|||
// 指定需要缓存的图标文件夹
|
|||
iconDirs: [path.resolve(process.cwd(), 'src/assets/svgicons')], |
|||
// 指定symbolId格式
|
|||
symbolId: 'icon-[dir]-[name]', |
|||
}), |
|||
] |
|||
isBuild && plugins.push(legacy()) // 是打包环境,就把legacy()加入到plugins中
|
|||
return { |
|||
plugins, |
|||
server: { |
|||
host: '0.0.0.0' |
|||
}, |
|||
publicPath: './', |
|||
base: './', |
|||
build: { |
|||
outDir: 'hukou', |
|||
assetsDir: 'assets', |
|||
}, |
|||
resolve: { |
|||
alias: { |
|||
'@': path.resolve(__dirname, './src'), |
|||
}, |
|||
}, |
|||
css: { |
|||
preprocessorOptions: { |
|||
less: { |
|||
javascriptEnabled: true, |
|||
}, |
|||
}, |
|||
}, |
|||
} |
|||
}) |