封装函数,随机背景
This commit is contained in:
@@ -1,10 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="bigscreen">
|
<div class="bigscreen" :style="{
|
||||||
|
backgroundImage: bgimg ? `url(${bgimg})` : '',
|
||||||
|
backgroundSize: 'cover',
|
||||||
|
backgroundPosition: 'center',
|
||||||
|
transition: 'background-image 0.5s',
|
||||||
|
}">
|
||||||
<header>
|
<header>
|
||||||
<h2>全国GDP</h2>
|
<h2>全国GDP</h2>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<left class="left">
|
<div class="left">
|
||||||
<div class="first">
|
<div class="first">
|
||||||
<chartContainer>
|
<chartContainer>
|
||||||
<div class="data" v-if="GDPgrowth && GDPtotal">
|
<div class="data" v-if="GDPgrowth && GDPtotal">
|
||||||
@@ -12,7 +17,6 @@
|
|||||||
<p>同比增长:{{ GDPgrowth }}%</p>
|
<p>同比增长:{{ GDPgrowth }}%</p>
|
||||||
</div>
|
</div>
|
||||||
</chartContainer>
|
</chartContainer>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="top_five">
|
<div class="top_five">
|
||||||
<chart-container>
|
<chart-container>
|
||||||
@@ -22,38 +26,73 @@
|
|||||||
<!-- //人均 -->
|
<!-- //人均 -->
|
||||||
|
|
||||||
<div class="peopleGDP" ref="PoepleTop5Ref"></div>
|
<div class="peopleGDP" ref="PoepleTop5Ref"></div>
|
||||||
</left>
|
</div>
|
||||||
<middle>
|
<div class="middle">
|
||||||
<div class="china_map" ref="chinaMapRef">
|
<div class="china_map" ref="chinaMapRef"></div>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<div class="weather">
|
||||||
|
<!-- 简单天气组件 -->
|
||||||
|
<chartContainer>
|
||||||
|
<div class="weather-info" v-if="weather">
|
||||||
|
<span style="color: red">我tm真是为了一碟醋 包了一盘饺子</span>
|
||||||
|
<p>城市:{{ weather.city }}</p>
|
||||||
|
<p>天气:{{ weather.weather }}</p>
|
||||||
|
<p>当前温度:{{ weather.temperature }}°C</p>
|
||||||
|
<p>湿度:{{ weather.humidity }}%</p>
|
||||||
|
<p>风向:{{ weather.winddirection }}</p>
|
||||||
|
<p>风力:{{ weather.windpower }}级</p>
|
||||||
|
</div>
|
||||||
|
</chartContainer>
|
||||||
</div>
|
</div>
|
||||||
</middle>
|
|
||||||
<right class="right">
|
|
||||||
<div class="weather"></div>
|
|
||||||
<div class="CountryGDP"></div>
|
<div class="CountryGDP"></div>
|
||||||
|
|
||||||
<div class="message"></div>
|
<div class="message"></div>
|
||||||
|
</div>
|
||||||
</right>
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="container"></div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||||
import { initChinaMap } from './ts/initChinaMap';
|
import { initChinaMap } from "./ts/initChinaMap";
|
||||||
import { getData } from '@/utils/getData';
|
import { getData } from "@/utils/getData";
|
||||||
import { useCityGDPStore } from '@/stores/cityGDP';
|
import { useCityGDPStore } from "@/stores/cityGDP";
|
||||||
import { get } from '@/utils/request';
|
import { get } from "@/utils/request";
|
||||||
import chartContainer from './components/chartContainer.vue';
|
import chartContainer from "./components/chartContainer.vue";
|
||||||
import { initTop5 } from './ts/initTop5';
|
import { initTop5 } from "./ts/initTop5";
|
||||||
import AMapLoader from "@amap/amap-jsapi-loader";
|
import getweather from "./ts/getweather";
|
||||||
// 全局状态
|
// 全局状态
|
||||||
const cityGDPStore = useCityGDPStore();
|
const cityGDPStore = useCityGDPStore();
|
||||||
// dom节点
|
// dom节点
|
||||||
const chinaMapRef = ref<HTMLDivElement>();
|
const chinaMapRef = ref<HTMLDivElement>();
|
||||||
const CityTop5Ref = ref<HTMLDivElement>();
|
const CityTop5Ref = ref<HTMLDivElement>();
|
||||||
const PoepleTop5Ref = ref<HTMLDivElement>();
|
const PoepleTop5Ref = ref<HTMLDivElement>();
|
||||||
//经纬度变量
|
const weather = ref<any>(sessionStorage.getItem("weather_cache_v1"));
|
||||||
let lng: number, lat: number, city: number;
|
// 随机背景图相关
|
||||||
|
const bgimg = ref<string>("");
|
||||||
|
const bgtime = ref<number>(0);
|
||||||
|
const BG_CACHE_KEY = "bgimg";
|
||||||
|
const BG_TIME_KEY = "bgtime";
|
||||||
|
const BG_TTL = 2 * 60 * 1000; // 2分钟
|
||||||
|
|
||||||
|
function getBg() {
|
||||||
|
const now = Date.now();
|
||||||
|
fetch(
|
||||||
|
"http://jycdt.cn:54321/?token=ZxoWsYjxVWqb69jHLadvaAnZ8F38U6t35ALuuXF7wQwm9UtCuhCypc6z0997oit0qCkppWZqbffjqeVTCnsoE5twzhx0MVfz68p9"
|
||||||
|
)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((res) => {
|
||||||
|
bgimg.value = res.img;
|
||||||
|
bgtime.value = now;
|
||||||
|
try {
|
||||||
|
localStorage.setItem(BG_CACHE_KEY, res.img);
|
||||||
|
localStorage.setItem(BG_TIME_KEY, String(now));
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("localStorage 写入失败", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
// 为高德地图安全配置添加类型声明
|
// 为高德地图安全配置添加类型声明
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@@ -66,155 +105,82 @@ declare global {
|
|||||||
const GDPtotal = ref<number>(0);
|
const GDPtotal = ref<number>(0);
|
||||||
const GDPtotalLast = ref<number>(0);
|
const GDPtotalLast = ref<number>(0);
|
||||||
const GDPgrowth = ref<number>(0);
|
const GDPgrowth = ref<number>(0);
|
||||||
//计算GDP
|
|
||||||
|
// 计算GDP
|
||||||
const calcGDP = () => {
|
const calcGDP = () => {
|
||||||
GDPtotal.value = cityGDPStore.cityGDP!.reduce((add, item: any) => {
|
GDPtotal.value = cityGDPStore.cityGDP!.reduce((add, item: any) => {
|
||||||
return add + item.gdp
|
return add + item.gdp;
|
||||||
}, 0);
|
}, 0);
|
||||||
GDPtotalLast.value = cityGDPStore.cityGDP!.reduce((add, item: any) => {
|
GDPtotalLast.value = cityGDPStore.cityGDP!.reduce((add, item: any) => {
|
||||||
return add + item.last
|
return add + item.last;
|
||||||
}, 0);
|
}, 0);
|
||||||
const GDPgrowthTmp = (GDPtotal.value - GDPtotalLast.value) / GDPtotalLast.value * 10000;
|
const GDPgrowthTmp =
|
||||||
|
((GDPtotal.value - GDPtotalLast.value) / GDPtotalLast.value) * 10000;
|
||||||
GDPgrowth.value = Math.ceil(GDPgrowthTmp) / 100;
|
GDPgrowth.value = Math.ceil(GDPgrowthTmp) / 100;
|
||||||
|
|
||||||
};
|
|
||||||
//地理位置逆编码
|
|
||||||
const getLocation = async (lng: number, lat: number, key: string) => {
|
|
||||||
const url: string = "https://restapi.amap.com"
|
|
||||||
const checkTime = (): boolean => {
|
|
||||||
const now = new Date().getTime();
|
|
||||||
const cd = 1000 * 60
|
|
||||||
//会话存储取出json
|
|
||||||
const location: { time: number, citycode: string } = JSON.parse(sessionStorage.getItem('location')!);
|
|
||||||
if (!location) {
|
|
||||||
console.log("开始请求");
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
const _time = now - location.time
|
|
||||||
if (_time > cd) {
|
|
||||||
console.log("开始请求");
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
console.log(_time, now, location);
|
|
||||||
|
|
||||||
console.log(`剩余cd:${(cd - _time) / 1000}s`);
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (lng && lat && checkTime()) {
|
|
||||||
const res = await get<any>(`${url}/v3/geocode/regeo?key=${key}&location=${lng},${lat}`);
|
|
||||||
console.log(res);
|
|
||||||
|
|
||||||
if (res.status === '1') {
|
|
||||||
const time = new Date().getTime()
|
|
||||||
let data = {}
|
|
||||||
data = {
|
|
||||||
time,
|
|
||||||
citycode: res.regeocode.addressComponent.adcode,
|
|
||||||
}
|
|
||||||
//转字符串存入会话存储
|
|
||||||
sessionStorage.setItem('location', JSON.stringify(data))
|
|
||||||
} else {
|
|
||||||
console.log("地理逆编码错误");
|
|
||||||
console.log(res);
|
|
||||||
}
|
|
||||||
let adcode: any = sessionStorage.getItem("location")
|
|
||||||
adcode = JSON.parse(adcode)
|
|
||||||
adcode = adcode.citycode
|
|
||||||
const weather = await get(`${url}/v3/weather/weatherInfo?key=${key}&city=${adcode}`)
|
|
||||||
console.log(weather);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
const initAMap = async (key1: string, key2: string, key3: string) => {
|
|
||||||
window._AMapSecurityConfig = {
|
|
||||||
securityJsCode: key2,
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Promise<void>((resolve) => {
|
|
||||||
AMapLoader.load({
|
|
||||||
key: key1,
|
|
||||||
version: "2.0",
|
|
||||||
plugins: ["AMap.Scale", "AMap.Geolocation"],
|
|
||||||
}).then((AMap) => {
|
|
||||||
function onComplete(data: any) {
|
|
||||||
console.log("定位成功!");
|
|
||||||
lng = data.position.lng;
|
|
||||||
lat = data.position.lat;
|
|
||||||
|
|
||||||
|
|
||||||
// 调用逆地理编码获取位置详情
|
|
||||||
getLocation(lng, lat, key3).then(() => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onError(data: any) {
|
|
||||||
console.log(`定位失败:${data.message}`);
|
|
||||||
resolve(); // 即使定位失败也继续执行
|
|
||||||
}
|
|
||||||
AMap.plugin('AMap.Geolocation', function () {
|
|
||||||
const geolocation = new AMap.Geolocation({
|
|
||||||
enableHighAccuracy: true,
|
|
||||||
timeout: 1000000,
|
|
||||||
buttonPosition: "RB",
|
|
||||||
});
|
|
||||||
geolocation.getCurrentPosition(function (status: any, result: any) {
|
|
||||||
if (status == 'complete') {
|
|
||||||
onComplete(result);
|
|
||||||
} else {
|
|
||||||
onError(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
resolve(); // 加载失败也继续执行
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
//地图传入key,安全密钥,定位服务key
|
// 背景图缓存逻辑
|
||||||
await initAMap("fe533a0fc1658158460a31b3ae0add51", "43029a44482fc7cdf66b0b590d138278", "48da806104e4bf77be4eeecf83f440aa"); // 初始化高德地图安全配置
|
const cachedImg = localStorage.getItem(BG_CACHE_KEY);
|
||||||
// getLocation(120.126893, 30.276614, "48da806104e4bf77be4eeecf83f440aa")
|
const cachedTime = Number(localStorage.getItem(BG_TIME_KEY) || 0);
|
||||||
|
if (cachedImg) bgimg.value = cachedImg;
|
||||||
|
if (cachedTime) bgtime.value = cachedTime;
|
||||||
|
// 判断是否过期
|
||||||
|
if (!bgimg.value || Date.now() - bgtime.value > BG_TTL) {
|
||||||
|
getBg();
|
||||||
|
}
|
||||||
|
|
||||||
|
await getweather(
|
||||||
|
"fe533a0fc1658158460a31b3ae0add51",
|
||||||
|
"43029a44482fc7cdf66b0b590d138278",
|
||||||
|
"48da806104e4bf77be4eeecf83f440aa"
|
||||||
|
); //天气,存储在sessionStorage
|
||||||
await getData(); // 获取数据
|
await getData(); // 获取数据
|
||||||
calcGDP(); // 计算GDP
|
calcGDP(); // 计算GDP
|
||||||
await initChinaMap(chinaMapRef.value!); // 初始化地图
|
await initChinaMap(chinaMapRef.value!); // 初始化地图
|
||||||
await initTop5(CityTop5Ref.value!, 1);
|
await initTop5(CityTop5Ref.value!, 1);
|
||||||
await initTop5(PoepleTop5Ref.value!, 2);
|
await initTop5(PoepleTop5Ref.value!, 2);
|
||||||
|
weather.value = JSON.parse(
|
||||||
|
sessionStorage.getItem("weather_cache_v1")!
|
||||||
|
).data!.weather!.lives[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
//control_min
|
@main-bg: #9fff7c;
|
||||||
@control-min-width: 800px;
|
@control-min-width: 800px;
|
||||||
//header
|
//header
|
||||||
@header-height: 10vh;
|
@header-height: 10vh;
|
||||||
// @header-bg: rgb(70, 244, 244);
|
@header-bg: @main-bg;
|
||||||
@header-bg: rgb(255, 255, 255);
|
// @header-bg: rgb(255, 255, 255);
|
||||||
//main
|
//main
|
||||||
@main-height: 90vh;
|
@main-height: 90vh;
|
||||||
// @main-bg: rgb(103, 255, 131);
|
// @main-bg: rgb(255, 255, 255);
|
||||||
@main-bg: rgb(255, 255, 255);
|
|
||||||
//left
|
//left
|
||||||
@left-width: 30vw;
|
@left-width: 30vw;
|
||||||
// @left-bg: rgb(237, 70, 70);
|
@left-bg: @main-bg;
|
||||||
@left-bg: rgb(255, 255, 255);
|
// @left-bg: rgb(255, 255, 255);
|
||||||
//middle
|
//middle
|
||||||
@middle-width: 40vw;
|
@middle-width: 40vw;
|
||||||
// @middle-bg: rgb(83, 123, 254);
|
@middle-bg: @main-bg;
|
||||||
@middle-bg: rgb(255, 255, 255);
|
// @middle-bg: rgb(255, 255, 255);
|
||||||
//right
|
//right
|
||||||
@right-width: 30vw;
|
@right-width: 30vw;
|
||||||
// @right-bg: rgb(255, 60, 213);
|
@right-bg: @main-bg;
|
||||||
@right-bg: rgb(255, 255, 255);
|
// @right-bg: rgb(255, 255, 255);
|
||||||
|
|
||||||
|
#container {
|
||||||
|
visibility: hidden;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.bigscreen {
|
.bigscreen {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
|
color: white;
|
||||||
|
|
||||||
header {
|
header {
|
||||||
height: @header-height;
|
height: @header-height;
|
||||||
background: @header-bg;
|
// background: @header-bg;
|
||||||
|
|
||||||
@media screen and (width<@control-min-width) {
|
@media screen and (width<@control-min-width) {
|
||||||
width: @control-min-width;
|
width: @control-min-width;
|
||||||
@@ -229,15 +195,13 @@ onMounted(async () => {
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
height: @main-height;
|
height: @main-height;
|
||||||
background-color: @main-bg;
|
/* background-color: @main-bg; */
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
left,
|
.left {
|
||||||
right {
|
|
||||||
width: @left-width;
|
width: @left-width;
|
||||||
background-color: @left-bg;
|
/* background-color: @left-bg; */
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -246,7 +210,6 @@ onMounted(async () => {
|
|||||||
>* {
|
>* {
|
||||||
height: 32%;
|
height: 32%;
|
||||||
width: calc(100% - 10px);
|
width: calc(100% - 10px);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.top5 {
|
.top5 {
|
||||||
@@ -255,14 +218,9 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
right {
|
.middle {
|
||||||
width: @right-width;
|
|
||||||
background-color: @right-bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
middle {
|
|
||||||
width: @middle-width;
|
width: @middle-width;
|
||||||
background-color: @middle-bg;
|
/* background-color: @middle-bg; */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-width: 320px;
|
min-width: 320px;
|
||||||
|
|
||||||
@@ -276,10 +234,19 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
right {
|
.right {
|
||||||
width: @right-width;
|
width: @right-width;
|
||||||
background-color: @right-bg;
|
/* background-color: @right-bg; */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
>* {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted } from "vue";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
width?: any;
|
width?: any;
|
||||||
@@ -24,5 +24,11 @@ const chart = ref(null);
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
|
box-shadow: 0 4px 24px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
border-radius: 18px;
|
||||||
|
background: rgba(0, 0, 0, 0.331);
|
||||||
|
backdrop-filter: blur(12px) saturate(180%);
|
||||||
|
-webkit-backdrop-filter: blur(12px) saturate(180%);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
115
src/page/ts/getweather.ts
Normal file
115
src/page/ts/getweather.ts
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* 获取天气信息:先使用高德 JSAPI 定位 -> 逆地理获取城市/行政区 -> 调用高德天气 WebAPI
|
||||||
|
* @param key1 JSAPI key (用于 AMapLoader)
|
||||||
|
* @param key2 安全码 securityJsCode
|
||||||
|
* @param key3 Web API key (用于天气接口)
|
||||||
|
* @returns Promise<{ position: {lng, lat}, address: string, weather: any }>
|
||||||
|
* 存储位置:sessionStorage.weather_cache_v1
|
||||||
|
*/
|
||||||
|
|
||||||
|
import AMapLoader from '@amap/amap-jsapi-loader'
|
||||||
|
|
||||||
|
const url = 'https://restapi.amap.com'
|
||||||
|
|
||||||
|
// 为高德地图安全配置添加类型声明
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
_AMapSecurityConfig: {
|
||||||
|
securityJsCode: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchJson(u: string) {
|
||||||
|
const res = await fetch(u)
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getweather(key1: string, key2: string, key3: string): Promise<any> {
|
||||||
|
// 缓存 key
|
||||||
|
const CACHE_KEY = 'weather_cache_v1'
|
||||||
|
const CACHE_TTL = 10 * 60 * 1000 // 10分钟
|
||||||
|
|
||||||
|
// 检查缓存
|
||||||
|
const cacheRaw = sessionStorage.getItem(CACHE_KEY)
|
||||||
|
if (cacheRaw) {
|
||||||
|
try {
|
||||||
|
const cache = JSON.parse(cacheRaw)
|
||||||
|
if (cache.time && Date.now() - cache.time < CACHE_TTL) {
|
||||||
|
return Promise.resolve(cache.data)
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise<any>(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
// 设置安全码
|
||||||
|
window._AMapSecurityConfig = { securityJsCode: key2 }
|
||||||
|
|
||||||
|
// 加载 AMap,并确保需要的插件:Geolocation + Geocoder
|
||||||
|
const AMap = await AMapLoader.load({
|
||||||
|
key: key1,
|
||||||
|
version: '2.0',
|
||||||
|
plugins: ['AMap.Geolocation', 'AMap.Geocoder'],
|
||||||
|
})
|
||||||
|
|
||||||
|
// 创建定位实例并获取当前位置
|
||||||
|
const geolocation = new AMap.Geolocation({
|
||||||
|
enableHighAccuracy: true,
|
||||||
|
timeout: 10000,
|
||||||
|
})
|
||||||
|
|
||||||
|
geolocation.getCurrentPosition(async (status: string, result: any) => {
|
||||||
|
if (status !== 'complete' || !result) {
|
||||||
|
return reject(new Error('定位失败'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// result.position 通常是 {lng, lat}
|
||||||
|
const pos =
|
||||||
|
result.position ||
|
||||||
|
result.lnglat ||
|
||||||
|
(result?.coords ? { lng: result.coords.lng, lat: result.coords.lat } : null)
|
||||||
|
if (!pos) return reject(new Error('无法获取坐标信息'))
|
||||||
|
|
||||||
|
// 使用 Geocoder 逆地理获取城市或 adcode
|
||||||
|
const geocoder = new AMap.Geocoder()
|
||||||
|
geocoder.getAddress([pos.lng, pos.lat], async (status2: string, res2: any) => {
|
||||||
|
if (status2 !== 'complete' || !res2 || !res2.regeocode) {
|
||||||
|
return reject(new Error('逆地理解析失败'))
|
||||||
|
}
|
||||||
|
|
||||||
|
const addrComp = res2.regeocode.addressComponent || {}
|
||||||
|
const city =
|
||||||
|
addrComp.city && addrComp.city.length ? addrComp.city : addrComp.province || ''
|
||||||
|
const adcode = addrComp.adcode || ''
|
||||||
|
|
||||||
|
// 优先使用 adcode(更加精确),否则使用 city 名称
|
||||||
|
const cityParam = adcode || city
|
||||||
|
|
||||||
|
// 调用高德天气接口(返回实时或预报信息,extensions=all 返回更多字段)
|
||||||
|
const weatherUrl = `${url}/v3/weather/weatherInfo?key=${encodeURIComponent(key3)}&city=${encodeURIComponent(
|
||||||
|
cityParam,
|
||||||
|
)}&extensions=base&output=json`
|
||||||
|
|
||||||
|
try {
|
||||||
|
const weather = await fetchJson(weatherUrl)
|
||||||
|
const data = {
|
||||||
|
position: { lng: pos.lng, lat: pos.lat },
|
||||||
|
address: res2.regeocode.formattedAddress,
|
||||||
|
weather,
|
||||||
|
}
|
||||||
|
// 写入缓存
|
||||||
|
sessionStorage.setItem(CACHE_KEY, JSON.stringify({ time: Date.now(), data }))
|
||||||
|
resolve(data)
|
||||||
|
} catch (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getweather
|
||||||
@@ -18,23 +18,22 @@ export const initTop5 = async (Top5Ref: HTMLDivElement, type: number) => {
|
|||||||
CityGDP.push(item.gdp)
|
CityGDP.push(item.gdp)
|
||||||
}
|
}
|
||||||
if (type == 2) {
|
if (type == 2) {
|
||||||
const r = Number(item.gdp) / Number(item.people)
|
const r = (Number(item.gdp) / Number(item.people)).toFixed(2)
|
||||||
CityGDP.push(String(r))
|
CityGDP.push(String(r))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
let option: EChartsOption = {
|
let option: EChartsOption = {
|
||||||
// grid: {
|
textStyle: { color: '#fff' },
|
||||||
// right: 80, // 为右侧标签留出足够空间
|
|
||||||
// left: 0, // 确保左侧城市名称有足够的显示空间
|
|
||||||
// top: 0,
|
|
||||||
// bottom: 0,
|
|
||||||
// },
|
|
||||||
title: {
|
title: {
|
||||||
text: '',
|
text: '',
|
||||||
left: 'center',
|
left: 'center',
|
||||||
|
textStyle: { color: '#fff' },
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
max: 'dataMax',
|
max: 'dataMax',
|
||||||
|
axisLabel: { color: '#fff' },
|
||||||
|
axisLine: { lineStyle: { color: '#fff' } },
|
||||||
|
splitLine: { lineStyle: { color: 'rgba(255,255,255,0.2)' } },
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
@@ -43,6 +42,8 @@ export const initTop5 = async (Top5Ref: HTMLDivElement, type: number) => {
|
|||||||
animationDuration: 300,
|
animationDuration: 300,
|
||||||
animationDurationUpdate: 300,
|
animationDurationUpdate: 300,
|
||||||
max: 4, // only the largest 3 bars will be displayed
|
max: 4, // only the largest 3 bars will be displayed
|
||||||
|
axisLabel: { color: '#fff' },
|
||||||
|
axisLine: { lineStyle: { color: '#fff' } },
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
@@ -55,16 +56,24 @@ export const initTop5 = async (Top5Ref: HTMLDivElement, type: number) => {
|
|||||||
position: 'right',
|
position: 'right',
|
||||||
valueAnimation: true,
|
valueAnimation: true,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
color: '#fff',
|
||||||
// 添加文本溢出处理
|
// 添加文本溢出处理
|
||||||
overflow: 'truncate',
|
overflow: 'truncate',
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
|
itemStyle: { color: '#74add1' },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
legend: {
|
legend: {
|
||||||
show: false,
|
show: false,
|
||||||
|
textStyle: { color: '#fff' },
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: true,
|
||||||
|
// backgroundColor: 'rgba(0,0,0,0.7)',
|
||||||
|
// borderColor: '#fff',
|
||||||
|
// textStyle: { color: '#fff' },
|
||||||
},
|
},
|
||||||
tooltip: { show: true },
|
|
||||||
animationDuration: 0,
|
animationDuration: 0,
|
||||||
animationDurationUpdate: 3000,
|
animationDurationUpdate: 3000,
|
||||||
animationEasing: 'linear',
|
animationEasing: 'linear',
|
||||||
|
|||||||
Reference in New Issue
Block a user