Merge branch 'yanyan_dev' into 'shenzhen-dev'

Yanyan dev

See merge request !5
This commit is contained in:
Jane 2023-05-21 15:15:49 +08:00
commit 987a279535
57 changed files with 8278 additions and 557 deletions

View File

@ -1,10 +1,10 @@
# 本地环境
NODE_ENV = 'development'
# 本地环境接口地址(/api/index.ts文件中使用)
VITE_API_URL = 'http://192.168.34.155:6688'
# VITE_API_URL = 'http://182.90.224.147'
# 上传
VITE_ULD_API_URL = 'http://192.168.34.155:8012/onlinePreview?url='
# 本地环境
NODE_ENV = 'development'
# 本地环境接口地址(/api/index.ts文件中使用)
VITE_API_URL = 'http://192.168.34.155:6688'
# VITE_API_URL = 'http://182.90.224.147'
# 上传
VITE_ULD_API_URL = 'http://192.168.34.155:8012/onlinePreview?url='

263
.vscode/settings.json vendored
View File

@ -1,131 +1,132 @@
{
"editor.formatOnSave": true,
"stylelint.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
},
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass", "html"],
"files.eol": "\n",
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"cSpell.words": [
"acroutes",
"adcode",
"Alipay",
"AMAP",
"Anglar",
"antd",
"apng",
"Biao",
"bottomleft",
"bottomright",
"breakline",
"browserslist",
"cascader",
"cnpm",
"commitize",
"commitlint",
"contentleft",
"contentright",
"CSDN",
"curveness",
"daterange",
"datetimerange",
"doclock",
"dragover",
"easymock",
"echarts",
"esbuild",
"fangda",
"fastmock",
"Geeker",
"Gitee",
"hexs",
"iconfont",
"Jheng",
"juejin",
"liquidfill",
"liutao",
"loglevel",
"longpress",
"malefemale",
"Mapchart",
"nprogress",
"officedocument",
"openxmlformats",
"pageable",
"Parens",
"persistedstate",
"Pinia",
"pjpeg",
"Prefixs",
"protable",
"singleline",
"sortablejs",
"sousuo",
"spreadsheetml",
"styl",
"stylelint",
"stylelintignore",
"stylelintrc",
"suoxiao",
"sysmbol",
"timerange",
"topleft",
"topright",
"truetype",
"Uncapitalize",
"unplugin",
"unref",
"vite",
"vuedraggable",
"vueuse",
"Vuex",
"wangeditor",
"Wechat",
"xianxingdaoyu",
"xianxingdiqiu",
"xianxingditu",
"xianxingfanchuan",
"xianxingfeiji",
"xianxinglvhangriji",
"xianxingtianqiyubao",
"xianxingxiangjipaizhao",
"xianxingxiarilengyin",
"xianxingyoulun",
"xianxingzijiayou",
"xiaoxi",
"yxxx",
"zhongyingwen",
"zhuti",
"zlevel"
]
}
{
"editor.formatOnSave": true,
"stylelint.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
},
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass", "html"],
"files.eol": "\n",
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"cSpell.words": [
"acroutes",
"adcode",
"Alipay",
"AMAP",
"Anglar",
"antd",
"apng",
"Biao",
"bottomleft",
"bottomright",
"breakline",
"browserslist",
"cascader",
"cnpm",
"commitize",
"commitlint",
"contentleft",
"contentright",
"CSDN",
"curveness",
"daterange",
"datetimerange",
"doclock",
"dragover",
"easymock",
"echarts",
"esbuild",
"fangda",
"fastmock",
"Geeker",
"Gitee",
"glgview",
"hexs",
"iconfont",
"Jheng",
"juejin",
"liquidfill",
"liutao",
"loglevel",
"longpress",
"malefemale",
"Mapchart",
"nprogress",
"officedocument",
"openxmlformats",
"pageable",
"Parens",
"persistedstate",
"Pinia",
"pjpeg",
"Prefixs",
"protable",
"singleline",
"sortablejs",
"sousuo",
"spreadsheetml",
"styl",
"stylelint",
"stylelintignore",
"stylelintrc",
"suoxiao",
"sysmbol",
"timerange",
"topleft",
"topright",
"truetype",
"Uncapitalize",
"unplugin",
"unref",
"vite",
"vuedraggable",
"vueuse",
"Vuex",
"wangeditor",
"Wechat",
"xianxingdaoyu",
"xianxingdiqiu",
"xianxingditu",
"xianxingfanchuan",
"xianxingfeiji",
"xianxinglvhangriji",
"xianxingtianqiyubao",
"xianxingxiangjipaizhao",
"xianxingxiarilengyin",
"xianxingyoulun",
"xianxingzijiayou",
"xiaoxi",
"yxxx",
"zhongyingwen",
"zhuti",
"zlevel"
]
}

View File

@ -1,111 +1,222 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%- title %></title>
</head>
<body>
<div id="app">
<style>
html,
body,
#app {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.loading-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.loading-box .loading-wrap {
display: flex;
align-items: center;
justify-content: center;
padding: 98px;
}
.dot {
position: relative;
box-sizing: border-box;
display: inline-block;
width: 32px;
height: 32px;
font-size: 32px;
transform: rotate(45deg);
animation: ant-rotate 1.2s infinite linear;
}
.dot i {
position: absolute;
display: block;
width: 14px;
height: 14px;
background-color: #409eff;
border-radius: 100%;
opacity: 0.3;
transform: scale(0.75);
transform-origin: 50% 50%;
animation: ant-spin-move 1s infinite linear alternate;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
animation-delay: 1.2s;
}
@keyframes ant-rotate {
to {
transform: rotate(405deg);
}
}
@keyframes ant-spin-move {
to {
opacity: 1;
}
}
</style>
<div class="loading-box">
<div class="loading-wrap">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
</div>
</div>
<script>
const globalState = JSON.parse(window.localStorage.getItem("GlobalState"));
if (globalState) {
const color = globalState.themeConfig.primary;
const isDark = globalState.themeConfig.isDark;
const dot = document.querySelectorAll(".dot i");
const html = document.querySelector("html");
dot.forEach(item => (item.style.background = color));
if (isDark) html.style.background = "#141414";
}
</script>
<script type="module" src="/src/main.ts"></script>
<script src="/jquery-1.12.4.min.js"></script>
<!-- 用于前端与插件交互 -->
<script src="/jsencrypt.min.js"></script>
<!-- 用于RSA加密 -->
<script src="/jsWebControl-1.0.0.min.js"></script>
<!-- 用于RSA加密 -->
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%- title %></title>
</head>
<body>
<div id="app">
<style>
html,
body,
#app {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.loading-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.loading-box .loading-wrap {
display: flex;
align-items: center;
justify-content: center;
padding: 98px;
}
.dot {
position: relative;
box-sizing: border-box;
display: inline-block;
width: 32px;
height: 32px;
font-size: 32px;
transform: rotate(45deg);
animation: ant-rotate 1.2s infinite linear;
}
.dot i {
position: absolute;
display: block;
width: 14px;
height: 14px;
background-color: #409eff;
border-radius: 100%;
opacity: 0.3;
transform: scale(0.75);
transform-origin: 50% 50%;
animation: ant-spin-move 1s infinite linear alternate;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
animation-delay: 1.2s;
}
@keyframes ant-rotate {
to {
transform: rotate(405deg);
}
}
@keyframes ant-spin-move {
to {
opacity: 1;
}
}
</style>
<div class="loading-box">
<div class="loading-wrap">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
</div>
</div>
<script>
const globalState = JSON.parse(window.localStorage.getItem("GlobalState"));
if (globalState) {
const color = globalState.themeConfig.primary;
const isDark = globalState.themeConfig.isDark;
const dot = document.querySelectorAll(".dot i");
const html = document.querySelector("html");
dot.forEach(item => (item.style.background = color));
if (isDark) html.style.background = "#141414";
}
</script>
<script type="module" src="/src/main.ts"></script>
<script
type="text/javascript"
src="<%= BASE_URL %>lib/include-lib.js?time=20210329"
libpath="<%= BASE_URL %>lib/"
include="jquery,jquery.range,bootstrap,bootstrap-checkbox,font-awesome,web-icons,layer,haoutil,nprogress,toastr,admui,turf,cesium,mars3d,mars3d-widget"
></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%- title %></title>
</head>
<body>
<div id="app">
<style>
html,
body,
#app {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.loading-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.loading-box .loading-wrap {
display: flex;
align-items: center;
justify-content: center;
padding: 98px;
}
.dot {
position: relative;
box-sizing: border-box;
display: inline-block;
width: 32px;
height: 32px;
font-size: 32px;
transform: rotate(45deg);
animation: ant-rotate 1.2s infinite linear;
}
.dot i {
position: absolute;
display: block;
width: 14px;
height: 14px;
background-color: #409eff;
border-radius: 100%;
opacity: 0.3;
transform: scale(0.75);
transform-origin: 50% 50%;
animation: ant-spin-move 1s infinite linear alternate;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
animation-delay: 1.2s;
}
@keyframes ant-rotate {
to {
transform: rotate(405deg);
}
}
@keyframes ant-spin-move {
to {
opacity: 1;
}
}
</style>
<div class="loading-box">
<div class="loading-wrap">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
</div>
</div>
<script>
const globalState = JSON.parse(window.localStorage.getItem("GlobalState"));
if (globalState) {
const color = globalState.themeConfig.primary;
const isDark = globalState.themeConfig.isDark;
const dot = document.querySelectorAll(".dot i");
const html = document.querySelector("html");
dot.forEach(item => (item.style.background = color));
if (isDark) html.style.background = "#141414";
}
</script>
<script type="module" src="/src/main.ts"></script>
<script src="/jquery-1.12.4.min.js"></script>
<!-- 用于前端与插件交互 -->
<script src="/jsencrypt.min.js"></script>
<!-- 用于RSA加密 -->
<script src="/jsWebControl-1.0.0.min.js"></script>
<!-- 用于RSA加密 -->
</body>
</html>

4715
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -28,19 +28,26 @@
"@vueuse/core": "^9.12.0",
"@wangeditor/editor": "^5.1.12",
"@wangeditor/editor-for-vue": "^5.1.12",
"amfe-flexible": "^2.2.1",
"axios": "^1.2.1",
"base-64": "^1.0.0",
"date-fns": "^2.29.3",
"driver.js": "^0.9.8",
"echarts": "^5.3.0",
"echarts-gl": "^2.0.9",
"echarts-liquidfill": "^3.1.0",
"element-china-area-data": "^5.0.2",
"element-plus": "^2.2.30",
"js-base64": "^3.7.5",
"js-md5": "^0.7.3",
"mars3d": "^3.5.6",
"mars3d-cesium": "^1.105.0",
"mitt": "^3.0.0",
"moment": "^2.29.4",
"nprogress": "^0.2.0",
"pinia": "^2.0.28",
"pinia-plugin-persistedstate": "^3.0.1",
"postcss-pxtorem": "^6.0.0",
"print-js": "^1.6.0",
"qs": "^6.11.0",
"sortablejs": "^1.15.0",
@ -59,7 +66,7 @@
"@typescript-eslint/parser": "^5.22.0",
"@vitejs/plugin-vue": "^3.1.0",
"@vitejs/plugin-vue-jsx": "^1.3.10",
"autoprefixer": "^10.4.7",
"autoprefixer": "^10.4.14",
"commitizen": "^4.2.4",
"cz-git": "^1.3.2",
"eslint": "^8.14.0",
@ -67,11 +74,12 @@
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.7.1",
"husky": "^8.0.1",
"lib-flexible": "^0.3.2",
"lint-staged": "^12.4.2",
"postcss": "^8.4.14",
"postcss-html": "^1.4.1",
"prettier": "^2.6.2",
"rollup-plugin-visualizer": "^5.5.4",
"rxjs": "^7.8.1",
"sass": "^1.49.7",
"standard-version": "^9.5.0",
"stylelint": "^14.8.5",
@ -90,6 +98,7 @@
"vite-plugin-compression": "^0.5.1",
"vite-plugin-eslint": "^1.6.0",
"vite-plugin-html": "^3.2.0",
"vite-plugin-mars3d": "^2.1.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend-plus": "^0.1.0",
"vue-tsc": "^1.0.24"

View File

@ -1,5 +1,20 @@
module.exports = {
plugins: {
autoprefixer: {}
}
};
module.exports = {
plugins: {
autoprefixer: {
overrideBrowserslist: [
"Android 4.1",
"iOS 7.1",
"Chrome > 31",
"ff > 31",
"ie >= 8",
"last 10 versions" // 所有主流浏览器最近10版本用
],
grid: true
},
"postcss-pxtorem": {
rootValue: 192, // 设计稿宽度的1/ 10
propList: ["*", "!border"], // 除 border 外所有px 转 rem
selectorBlackList: [".el-"] // 过滤掉.el-开头的class不进行rem转换
}
}
};

1133
public/config/config.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
import { ScreenResponse, ResponseSame } from "@/api/types/common";
import http from "@/api";
const BASEURL = import.meta.env.VITE_API_URL;
/**
* @name
*/
//企业资质统计
export const getCompanyAll = () => {
return http.get<ResponseSame<ScreenResponse.CompanyAllResponse>>(BASEURL + `/gov/api/index/enterpriseMainStat`);
};
//查询工程分类统计
export const getProjectAll = () => {
return http.get<ResponseSame<ScreenResponse.ProjectAllResponse>>(BASEURL + `/gov/api/index/engineeringTypeStat`);
};
//查询所有项目数
export const getProjectNumber = () => {
return http.get<ResponseSame<ScreenResponse.ProjectNumberResponse>>(BASEURL + `/gov/api/index/projectStat`);
};
//扬尘报警类型统计
export const getFugitiveDustAll = () => {
return http.get<ResponseSame<ScreenResponse.FugitiveDustAllResponse>>(BASEURL + `/gov/api/index/environmentAlarmStat`);
};
//实名制信息统计
export const getRealNameSystem = () => {
return http.get<ResponseSame<ScreenResponse.RealNameSystemResponse>>(BASEURL + `/gov/api/index/workerStat`);
};
//顶部查询工程统计信息
export const getEngineeringAll = () => {
return http.get<ResponseSame<ScreenResponse.EngineeringAllResponse>>(BASEURL + `/gov/api/index/engineeringStat`);
};
//顶部查询工程统计信息
export const getMapProject = () => {
return http.get<ResponseSame<ScreenResponse.mapProjectResponse>>(BASEURL + `/gov/api/index/engineeringList`);
};

View File

@ -1,45 +1,45 @@
import { Login } from "@/api/interface/index";
// import { BASEURL } from "@/api/config/servicePort";
import DynamicRouter from "@/assets/json/dynamicRouter.json";
import AuthButtons from "@/assets/json/authButtons.json";
import qs from "qs";
import http from "@/api";
import { GlobalStore } from "@/stores";
/**
* @name
*/
// * 用户登录
const BASEURL = import.meta.env.VITE_API_URL;
export const loginApi = (params: Login.ReqLoginForm) => {
return http.post<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login`, params, { headers: { noLoading: true } }); // 正常 post json 请求 ==> application/json
// return http.post<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login`, params, { headers: { noLoading: true } }); // 控制当前请求不显示 loading
// return http.post<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login`, {}, { params }); // post 请求携带 query 参数 ==> ?username=admin&password=123456
// return http.post<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login`, qs.stringify(params)); // post 请求携带表单参数 ==> application/x-www-form-urlencoded
// return http.get<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login?${qs.stringify(params, { arrayFormat: "repeat" })}`); // 如果是 get 请求可以携带数组等复杂参数
};
// * 获取按钮权限
export const getAuthButtonListApi = () => {
// return http.get<Login.ResAuthButtons>(BASEURL + `/auth/buttons`, {}, { headers: { noLoading: true } });
// 如果想让按钮权限变为本地数据,注释上一行代码,并引入本地 authButtons.json 数据
return AuthButtons;
};
// * 获取菜单列表
export const getAuthMenuListApi = (params?: any) => {
const globalStore = GlobalStore();
if (!params && !globalStore.moduleId) return DynamicRouter;
return http.post<Menu.MenuOptions[]>(BASEURL + `/xmgl/baseMenu/queryBySelf`, params || { moduleId: globalStore.moduleId }, {
headers: { noLoading: true }
});
// 如果想让菜单变为本地数据,注释上一行代码,并引入本地 dynamicRouter.json 数据
// return DynamicRouter;
};
// * 用户退出登录
export const logoutApi = () => {
return http.post(BASEURL + `/xmgl/systemUser/logout`);
};
import { Login } from "@/api/interface/index";
// import { BASEURL } from "@/api/config/servicePort";
import DynamicRouter from "@/assets/json/dynamicRouter.json";
import AuthButtons from "@/assets/json/authButtons.json";
import qs from "qs";
import http from "@/api";
import { GlobalStore } from "@/stores";
/**
* @name
*/
// * 用户登录
const BASEURL = import.meta.env.VITE_API_URL;
export const loginApi = (params: Login.ReqLoginForm) => {
return http.post<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login`, params, { headers: { noLoading: true } }); // 正常 post json 请求 ==> application/json
// return http.post<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login`, params, { headers: { noLoading: true } }); // 控制当前请求不显示 loading
// return http.post<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login`, {}, { params }); // post 请求携带 query 参数 ==> ?username=admin&password=123456
// return http.post<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login`, qs.stringify(params)); // post 请求携带表单参数 ==> application/x-www-form-urlencoded
// return http.get<Login.ResLogin>(BASEURL + `/xmgl/systemUser/login?${qs.stringify(params, { arrayFormat: "repeat" })}`); // 如果是 get 请求可以携带数组等复杂参数
};
// * 获取按钮权限
export const getAuthButtonListApi = () => {
// return http.get<Login.ResAuthButtons>(BASEURL + `/auth/buttons`, {}, { headers: { noLoading: true } });
// 如果想让按钮权限变为本地数据,注释上一行代码,并引入本地 authButtons.json 数据
return AuthButtons;
};
// * 获取菜单列表
export const getAuthMenuListApi = (params?: any) => {
const globalStore = GlobalStore();
if (!params && !globalStore.moduleId) return DynamicRouter;
return http.post<Menu.MenuOptions[]>(BASEURL + `/xmgl/baseMenu/queryBySelf`, params || { moduleId: globalStore.moduleId }, {
headers: { noLoading: true }
});
// 如果想让菜单变为本地数据,注释上一行代码,并引入本地 dynamicRouter.json 数据
// return DynamicRouter;
};
// * 用户退出登录
export const logoutApi = () => {
return http.post(BASEURL + `/xmgl/systemUser/logout`);
};

View File

@ -1,3 +1,5 @@
import { number } from "echarts";
// * 请求响应参数(不包含data)
export declare interface Result {
code: string;
@ -122,3 +124,82 @@ export declare namespace User {
children?: ResDepartment[];
}
}
// * 政务大屏响应参数
export declare interface ResponseSame<T> {
forEach(arg0: (item: { dict_value: any; num: any }) => void);
[x: string]: any;
forEach(arg0: (item: any, index: any, array: any) => void): unknown;
result: T[];
code: number;
success: boolean;
message: string;
timestamp: string;
}
export declare namespace ScreenResponse {
interface CompanyAllResponse {
dict_value: string;
num: string;
}
interface ProjectAllResponse {
dict_value: string;
num: string;
}
interface ProjectNumberResponse {
total: number;
}
interface FugitiveDustAllResponse {
type: string;
num: string;
}
interface RealNameSystemResponse {
total: number; //实名制人员
manager: number; //管理人员
worker: number; //建筑工人
}
interface EngineeringAllResponse {
total: number; //工程数
newBuild: number; //今年新增工程
finish: number; //今年竣工工程
important: number; //重点工程
}
interface mapProjectResponse {
id: string;
project_sn: string;
engineering_sn: string;
engineering_name: string; //工程名称
engineering_code: string;
engineering_type: number;
engineering_use: number;
engineering_cost: string; //工程造价(万元)
engineering_area: string; //工程总面积(㎡)
engineering_length: string;
is_important: boolean;
longitude: string;
latitude: string;
province: string; //省
city: string; //市
district: string; //区
address: string; //详细地址
license_key: string;
license_create_time: string;
safety_supervision: string;
safety_supervision_person: string;
safety_supervision_code: string;
safety_supervision_state: string;
safety_supervision_plan: string;
quality_supervision: string;
quality_supervision_person: string;
quality_supervision_code: string;
quality_supervision_state: string;
quality_supervision_plan: string;
start_time: string;
end_time: string;
create_time: string;
examine_state: number;
reject_reason: string;
state: number; //工程状态(1:未开工;2:在建;3:在建.普通停工;4:在建.处罚停 工;5:在建.完工;6:待竣工;7:竣工)
update_time: string;
ai_alarm_stat: string;
enterprise_name: string; //建设单位
}
}

View File

@ -1,37 +1,75 @@
@font-face {
font-family: siyuan;
font-style: normal;
// src: url("./");
font-weight: normal;
src: url("./SourceHanSansCN-Regular.otf");
font-display: auto;
}
@font-face {
font-family: "siyuan_Medium";
font-style: normal;
// src: url("./");
font-weight: normal;
src: url("./SourceHanSansCN-Medium.otf");
font-display: auto;
}
@font-face {
font-family: "siyuan_Bold";
font-style: normal;
// src: url("./");
font-weight: normal;
src: url("./SourceHanSansCN-Bold.otf");
font-display: auto;
}
// @font-face {
// font-family: SourceHanSansCN-Regular_0;
// src: url("./SourceHanSansCN-Regular_0.otf");
// }
// @font-face {
// font-family: SourceHanSansCN-Regular_0;
// src: url("./SourceHanSansCN-Regular_0.otf");
// }
@font-face {
font-family: siyuan;
font-style: normal;
// src: url("./");
font-weight: normal;
src: url("./SourceHanSansCN-Regular.otf");
font-display: auto;
}
@font-face {
font-family: "siyuan_Medium";
font-style: normal;
// src: url("./");
font-weight: normal;
src: url("./SourceHanSansCN-Medium.otf");
font-display: auto;
}
@font-face {
font-family: "siyuan_Bold";
font-style: normal;
// src: url("./");
font-weight: normal;
src: url("./SourceHanSansCN-Bold.otf");
font-display: auto;
}
// @font-face {
// font-family: SourceHanSansCN-Regular_0;
// src: url("./SourceHanSansCN-Regular_0.otf");
// }
// @font-face {
// font-family: SourceHanSansCN-Regular_0;
// src: url("./SourceHanSansCN-Regular_0.otf");
// }
// 大屏字体
@font-face {
font-family: OPPOSansB;
font-weight: normal;
src: url("./screenFonts/OPPOSans-B.ttf");
}
@font-face {
font-family: OPPOSansH;
font-weight: normal;
src: url("./screenFonts/OPPOSans-H.ttf");
}
@font-face {
font-family: DigitalRegular;
font-weight: normal;
src: url("./screenFonts/DigitalRegular.ttf");
}
@font-face {
font-family: title;
font-weight: normal;
src: url("./screenFonts/title.ttf");
}
@font-face {
font-family: YouSheBiaoTiHei;
font-weight: normal;
src: url("./screenFonts/YouSheBiaoTiHei-2.ttf");
}
@font-face {
font-family: SourceHanSansCNR;
font-weight: normal;
src: url("./screenFonts/SourceHanSansCN-Regular.otf");
}
@font-face {
font-family: SourceHanSansCNH;
font-weight: normal;
src: url("./screenFonts/SourceHanSansCN-Heavy.otf");
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

View File

@ -30,16 +30,11 @@ import I18n from "@/languages/index";
import pinia from "@/stores/index";
// svg icons
import "virtual:svg-icons-register";
// import "@/assets/js/jquery-1.12.4.min.js";
// import "@/assets/js/jsencrypt.min.js";
// import "@/assets/js/jsWebControl-1.0.0.min.js";
// rem自适应
import "amfe-flexible/index.js";
// errorHandler
// import errorHandler from "@/utils/errorHandler";
const app = createApp(App);
// app.config.errorHandler = errorHandler;
// 注册element Icons组件

View File

@ -0,0 +1,98 @@
<template>
<div class="ordersizeCenter">
<div v-for="(item, index) in list" :key="index" :class="item.bgimg">
<div class="listItem">
<div class="listNumber">{{ item.number }}</div>
<div class="listName">{{ item.name }}</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { getEngineeringAll } from "@/api/modules/largeSreen";
onMounted(() => {
projectNumber();
});
//
const list = ref([
{ bgimg: "bgImgOne", number: "60348", name: "今年新增工程" },
{ bgimg: "bgImgTwo", number: "19374", name: "今年竣工工程" },
{ bgimg: "bgImgThree", number: "2479", name: "重点工程" }
]);
const projectNumber = async () => {
const { result } = await getEngineeringAll();
list.value[0].number = result.newBuild;
list.value[1].number = result.finish;
list.value[2].number = result.important;
};
</script>
<style lang="scss" scoped>
.ordersizeCenter {
position: fixed;
top: 15%;
left: 50%;
display: flex;
justify-content: space-evenly;
width: 48%;
height: 100%;
transform: translate(-50%);
.bgImgOne {
width: 232px;
height: 82px;
background: url("/src/assets/images/screenImg/add.png") no-repeat center center;
background-size: 100%;
.listItem {
padding: 15px 0 0 85px;
color: white;
.listNumber {
font-family: DigitalRegular;
font-size: 36px;
}
.listName {
font-family: SourceHanSansCNR;
font-size: 12px;
}
}
}
.bgImgTwo {
width: 232px;
height: 82px;
background: url("/src/assets/images/screenImg/completed.png") no-repeat center center;
background-size: 100%;
.listItem {
padding: 15px 0 0 85px;
color: white;
.listNumber {
font-family: DigitalRegular;
font-size: 36px;
}
.listName {
font-family: SourceHanSansCNR;
font-size: 12px;
}
}
}
.bgImgThree {
width: 232px;
height: 82px;
background: url("/src/assets/images/screenImg/importent.png") no-repeat center center;
background-size: 100%;
.listItem {
padding: 15px 0 0 85px;
color: white;
.listNumber {
font-family: DigitalRegular;
font-size: 36px;
}
.listName {
font-family: SourceHanSansCNR;
font-size: 12px;
}
}
}
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<div class="orderSide">
<div class="weather">
<div>{{ currentDate }}&nbsp;&nbsp;&nbsp;{{ currentTime }}</div>
<div>
{{ weatherInfo.weather }}&nbsp;&nbsp;&nbsp;{{ weatherInfo.temperature }}
<img class="img" @click="goBack" src="@/assets/images/screenImg/off.png" alt="" />
</div>
</div>
<div class="bigTitle">智慧工地可视化平台</div>
</div>
</template>
<script lang="ts" setup>
import axios from "axios";
import moment from "moment";
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
const currentDate = ref("");
const currentTime = ref("");
onMounted(() => {
getWeather();
setInterval(() => {
getTime();
}, 600);
});
const getTime = () => {
//
currentDate.value = moment().format("yyyy-MM-DD");
//
currentTime.value = moment().format("HH:mm:ss");
};
const weatherInfo = ref({});
const getWeather = () => {
let url = "https://restapi.amap.com/v3/weather/weatherInfo?city=440000&key=ad31e514e7e740179d6d8f182720bcf5";
axios({ method: "get", url }).then(({ data: res }) => {
console.log(res);
weatherInfo.value = res.lives[0];
});
};
const router = useRouter();
const goBack = () => {
//
router.go(-1);
};
</script>
<style lang="scss" scoped>
.orderSide {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url("@/assets/images/screenImg/topBorder.png") no-repeat;
background-size: 100%;
.bigTitle {
position: fixed;
top: 0.17rem;
left: 3.95rem;
font-family: title;
font-size: 0.21rem;
color: white;
text-shadow: 4px 4px 4px rgba($color: white, $alpha: 40%);
letter-spacing: 0.025rem;
}
.weather {
display: flex;
justify-content: space-between;
padding: 10px 10px 0;
font-family: SourceHanSansCNR;
font-size: 12px;
background-image: -webkit-linear-gradient(bottom, #4b5e84, #ffffff);
background-clip: text;
-webkit-text-fill-color: transparent;
}
.img {
margin-left: 5px;
}
}
</style>

View File

@ -0,0 +1,419 @@
<template>
<div class="leftBorder">
<div class="title">
<div class="text">项目数</div>
</div>
<div class="projectNum">
<div v-for="(item, index) in projectNum.newNum" :key="index">
<div class="numItem">{{ item }}</div>
</div>
</div>
<div class="title">
<div class="text">实名制统计</div>
</div>
<div class="realNameSystem">
<div :class="realNameBlue.bgimg">
<img :src="realNameBlue.img" alt="" />
<div class="centerTitle">
<div class="titleNumber">{{ realNameBlue.number }}</div>
<div class="titleName">{{ realNameBlue.name }}</div>
</div>
</div>
<div :class="realNameGreen.bgimg">
<img :src="realNameGreen.img" alt="" />
<div class="centerTitle">
<div class="titleNumber">{{ realNameGreen.number }}</div>
<div class="titleName">{{ realNameGreen.name }}</div>
</div>
<div class="percent">{{ realNameGreen.percent }}</div>
</div>
<div :class="realNameRed.bgimg">
<img :src="realNameRed.img" alt="" />
<div class="centerTitle">
<div class="titleNumber">{{ realNameRed.number }}</div>
<div class="titleName">{{ realNameRed.name }}</div>
</div>
<div class="percent">{{ realNameRed.percent }}</div>
</div>
</div>
<div class="title">
<div class="text">企业统计</div>
</div>
<div class="companyAll">
<div>
<div v-for="(item, index) in companyLeft" :key="index" class="companyItemLeft">
<div class="flex">
<div class="leftIcon">
<img :src="item.img" />
</div>
<div class="rightMessage">
<div class="unitName">{{ item.name }}</div>
<div class="unitNumber">{{ item.number }}</div>
</div>
</div>
</div>
</div>
<div>
<div v-for="(item, index) in companyRight" :key="index" class="companyItemRight">
<div class="flex">
<div class="leftIcon">
<img :src="item.img" />
</div>
<div class="rightMessage">
<div class="unitName">{{ item.name }}</div>
<div class="unitNumber">{{ item.number }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from "vue";
import { getCompanyAll, getProjectNumber, getRealNameSystem } from "@/api/modules/largeSreen";
onMounted(() => {
projectNumber();
realName();
conmpanyList();
});
//
const projectNum = reactive({
num: "000000",
newNum: ["0", "0", "0", "0", "0", "0"]
});
const projectNumber = async () => {
const { result } = await getProjectNumber();
const stringNum = String(result.total / 1000000);
const newNum = stringNum.split(".");
if (newNum[1].length < 6) {
const a = 6 - newNum[1].length;
for (let i = 0; i <= a; i++) {
projectNum.num = newNum[1] + "0";
}
} else {
projectNum.num = newNum[1];
}
projectNum.newNum = projectNum.num.split("");
};
//
const realNameBlue = ref({
img: "/src/assets/images/screenImg/blueCircle.gif",
bgimg: "bluebg",
name: "实名制人员",
number: "0"
});
const realNameGreen = ref({
img: "/src/assets/images/screenImg/greenCircle.gif",
bgimg: "greenbg",
name: "建筑工人",
number: "0",
percent: "92%"
});
const realNameRed = ref({
img: "/src/assets/images/screenImg/redCircle.gif",
bgimg: "redbg",
name: "管理人员",
number: "0",
percent: "8%"
});
const realName = async () => {
const { result } = await getRealNameSystem();
realNameBlue.value.number = result.total;
realNameGreen.value.number = result.worker;
realNameRed.value.number = result.manager;
realNameGreen.value.percent = result.workerRatio + "%";
realNameRed.value.percent = result.managerRatio + "%";
};
//
const companyLeft = ref([
{
name: "施工",
img: "/src/assets/images/screenImg/shigong.png",
number: "0",
bgImg: "blue"
},
{
name: "监理",
img: "/src/assets/images/screenImg/jianli.png",
number: "0",
bgImg: "blue"
},
{ name: "设计", img: "/src/assets/images/screenImg/sheji.png", number: "0", bgImg: "blue" }
]);
const companyRight = ref([
{
name: "建设",
img: "/src/assets/images/screenImg/jianshe.png",
number: "0",
bgImg: "green"
},
{
name: "勘察",
img: "/src/assets/images/screenImg/kancha.png",
number: "0",
bgImg: "green"
},
{ name: "其他", img: "/src/assets/images/screenImg/qita.png", number: "0", bgImg: "green" }
]);
const conmpanyList = async () => {
const { result } = await getCompanyAll();
result.forEach((item: { dict_value: any; num: any }) => {
if (item.dict_value == companyLeft.value[0].name) {
companyLeft.value[0].number = item.num;
} else if (item.dict_value == companyLeft.value[1].name) {
companyLeft.value[1].number = item.num;
} else if (item.dict_value == companyLeft.value[2].name) {
companyLeft.value[2].number = item.num;
} else if (item.dict_value == companyRight.value[0].name) {
companyRight.value[0].number = item.num;
} else if (item.dict_value == companyRight.value[1].name) {
companyRight.value[1].number = item.num;
} else if (item.dict_value == companyRight.value[2].name) {
companyRight.value[2].number = item.num;
}
});
};
</script>
<style lang="scss" scoped>
.leftBorder {
position: fixed;
top: 15%;
left: 0;
width: 25%;
height: 100%;
background: url("@/assets/images/screenImg/leftBorder.png") no-repeat left center;
background-size: 100% 100%;
.title {
width: 100%;
height: 50px;
margin: 0 0 0 40px;
font-family: YouSheBiaoTiHei;
color: white;
background: url("@/assets/images/screenImg/littleTitle.png") no-repeat left center;
background-size: 75%;
.text {
padding: 0 0 0 50px;
font-size: 18px;
}
}
.projectNum {
display: flex;
width: 90%;
height: 100px;
margin-left: 50px;
.numItem {
width: 56px;
height: 62px;
margin-left: 10px;
font-family: DigitalRegular;
font-size: 48px;
line-height: 62px;
color: white;
text-align: center;
background: url("@/assets/images/screenImg/frame.png") no-repeat;
background-size: 100%;
}
}
.companyAll {
display: flex;
justify-content: space-evenly;
width: 90%;
margin: 0 0 20px 45px;
.companyItemLeft {
width: 190px;
height: 75px;
margin: 0 0 15px;
background: url("@/assets/images/screenImg/blueSquare.png") no-repeat center center;
background-size: 100%;
.flex {
display: flex;
.leftIcon {
flex: 4;
img {
width: 70px;
height: 70px;
margin-top: 3px;
}
}
.rightMessage {
flex: 6;
margin-top: 11px;
.unitName {
font-family: SourceHanSansCNR;
font-size: 16px;
color: white;
}
.unitNumber {
font-family: DigitalRegular;
font-size: 28px;
color: #558adb;
}
}
}
}
.companyItemRight {
width: 190px;
height: 75px;
margin: 0 0 15px;
background: url("@/assets/images/screenImg/greenSquare.png") no-repeat;
background-size: 100%;
.flex {
display: flex;
.leftIcon {
flex: 4;
img {
width: 70px;
height: 70px;
}
}
.rightMessage {
flex: 6;
margin-top: 11px;
.unitName {
font-family: SourceHanSansCNR;
font-size: 16px;
color: white;
}
.unitNumber {
font-family: DigitalRegular;
font-size: 28px;
color: #30ac7c;
}
}
}
}
}
.realNameSystem {
position: relative;
height: 290px;
.bluebg {
position: relative;
width: 161px;
height: 161px;
margin: 0 0 0 50px;
text-align: center;
background: url("@/assets/images/screenImg/blueCirclebg.png") no-repeat center center;
background-size: 100%;
img {
width: 130px;
height: 130px;
margin: 16px 0 0 -2px;
}
.centerTitle {
position: absolute;
top: 55px;
left: 50px;
.titleNumber {
font-family: DigitalRegular;
font-size: 32px;
color: white;
text-align: center;
}
.titleName {
font-family: SourceHanSansCNR;
font-size: 12px;
color: #558adb;
text-align: centerb;
}
}
}
.greenbg {
position: relative;
position: absolute;
top: 10%;
left: 43%;
width: 150px;
height: 140px;
margin: 0 0 0 35px;
background: url("@/assets/images/screenImg/greenCirclebg.png") no-repeat center center;
background-size: 100%;
img {
width: 120px;
height: 120px;
margin: 10px 0 0 15px;
}
.centerTitle {
position: absolute;
top: 45px;
left: 50px;
.titleNumber {
font-family: DigitalRegular;
font-size: 32px;
color: white;
text-align: center;
}
.titleName {
font-family: SourceHanSansCNR;
font-size: 12px;
color: #558adb;
text-align: center;
}
}
.percent {
position: absolute;
top: 37px;
left: 155px;
width: 76px;
height: 30px;
font-family: OPPOSansH;
font-size: 17px;
color: rgb(48 172 124);
text-align: center;
border-bottom: 5px solid #dddddd;
border-image: linear-gradient(to right, rgb(48 172 124 / 0%), rgb(48 172 124 / 100%)) 30 30;
}
}
.redbg {
position: relative;
position: absolute;
top: 55%;
left: 25%;
width: 130px;
height: 120px;
margin: 0 0 0 35px;
background: url("@/assets/images/screenImg/redCirclebg.png") no-repeat center center;
background-size: 100%;
img {
width: 100px;
height: 100px;
margin: 10px 0 0 15px;
}
.centerTitle {
position: absolute;
top: 35px;
left: 40px;
.titleNumber {
font-family: DigitalRegular;
font-size: 32px;
color: white;
text-align: center;
}
.titleName {
font-family: SourceHanSansCNR;
font-size: 12px;
color: #558adb;
text-align: center;
}
}
.percent {
position: absolute;
top: 32px;
left: 135px;
width: 76px;
height: 30px;
font-family: OPPOSansH;
font-size: 17px;
color: rgb(238 80 30);
text-align: center;
border-bottom: 5px solid #dddddd;
border-image: linear-gradient(to right, rgb(238 80 30 / 0%), rgb(238 80 30 / 100%)) 30 30;
}
}
}
}
</style>

View File

@ -0,0 +1,218 @@
<template>
<div class="app-container">
<div id="container"></div>
</div>
</template>
<script lang="ts" setup>
import AMapLoader from "@amap/amap-jsapi-loader";
/*Vue3使,Vue3shallowRef(使shallowRef,
因为在Vue3中所使用的Proxy拦截操作会改变JSAPI原生对象,所以此处需要区别Vue2使用方式对地图对象进行非深度监听,
否则会出现问题,建议JSAPI相关对象采用非响应式的普通对象来存储)*/
// import { shallowRef } from "@vue/reactivity";
import { ref, onMounted } from "vue";
import { getMapProject } from "@/api/modules/largeSreen";
onMounted(() => {
getProjectList();
});
// const map = shallowRef(null);
const path = ref([]);
const current_position = ref([]);
const projectStatusEnum = ref({
1: "开工前准备",
2: "在建工程",
3: "停工工程",
4: "完工待验收",
5: "已验收(安全评价)",
6: "已验收未备案",
7: "已竣工验收备案"
});
const mapProjectList = ref([]);
const getProjectList = async () => {
const { result } = await getMapProject();
mapProjectList.value = result;
console.log(mapProjectList.value, "aaa");
initMap();
};
const initMap = () => {
window._AMapSecurityConfig = {
securityJsCode: "6caf6429e4b98cf7f39db9bf7014a78b"
};
AMapLoader.load({
key: "ee87cfd8354d3ff2a898036bacc4b8a2", // WebKey load
version: "1.4.15" // JSAPI 1.4.15
// plugins:[''], // 使'AMap.Scale'
})
.then(AMap => {
const map = new AMap.Map("container", {
//id
viewMode: "3D", //3D
zoom: 10, //
center: [114.085947, 22.547], //
mapStyle: "amap://styles/67570a93d67b07a02ee522a2c1180be4"
});
//
AMap.plugin(
["AMap.ToolBar", "AMap.Scale", "AMap.HawkEye", "AMap.Geolocation", "AMap.MapType", "AMap.MouseTool"],
function () {
//
//
map.addControl(new AMap.ToolBar()); // ;
map.addControl(new AMap.Scale()); //
map.addControl(new AMap.HawkEye()); //
map.addControl(new AMap.Geolocation()); //
map.addControl(new AMap.MapType()); // ,
//
const mouseTool = new AMap.MouseTool(map);
// mouseTool.rule();// 线,
mouseTool.measureArea(); //
}
);
//
// map.on("click", e => {
// // lng ==> lat =>
// current_position.value = [e.lnglat.lng, e.lnglat.lat];
// path.value.push([e.lnglat.lng, e.lnglat.lat]);
// // addMarker();
// // addPolyLine();
// });
// //
// // ()
// function addMarker() {
// const marker = new AMap.Marker({
// icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
// position: current_position.value, // ,
// // offset
// offset: new AMap.Pixel(-26, -54)
// });
// console.log("", current_position.value);
// marker.setMap(map);
// }
// position
mapProjectList.value.forEach((item, index, array) => {
const marker = new AMap.Marker({
icon: "/src/assets/images/screenImg/mapImg/dian.png",
position: [`${item.longitude}`, `${item.latitude}`],
// offset
offset: new AMap.Pixel(-26, -24)
});
//
const infoWindow = new window.AMap.InfoWindow({
offset: new window.AMap.Pixel(0, -31)
});
// // -
// const postponeImage = require("@/assets/images/screenImg/mapImg/iconPostpone.png");
// // -
// const shutdownRectificationImage = require("@/assets/images/screenImg/mapImg/iconShutdownRectification.png");
// // -
// const stagnateImage = require("@/assets/images/screenImg/mapImg/iconStagnate.png");
// // -
// const completedImage = require("@/assets/images/screenImg/mapImg/iconCompleted.png");
// // -
// const normalConstruction = require("@/assets/images/screenImg/mapImg/iconNormalConstruction.png");
// const statusIcons = {
// projectDelay: createIcon(postponeImage), //
// suspensionandrectification: createIcon(shutdownRectificationImage), //
// projectStagnation: createIcon(stagnateImage), //
// completionAcceptance: createIcon(completedImage), //
// normalConstruction: createIcon(normalConstruction) //
// };
// /**
// *
// * @param {string} image icon
// */
// function createIcon(image) {
// return new window.AMap.Icon({
// size: new window.AMap.Size(28, 40), //
// image, //
// imageSize: new window.AMap.Size(28, 40), //
// imageOffset: new window.AMap.Pixel(0, 0) //
// });
// }
marker.content = `<div class="info-window" style="font-size: 14px">
<div class="info">
<span class="label" style="font-weight: 600">项目名称</span>
<span class="value">${item.engineering_name}</span>
</div>
<div class="info">
<span class="label" style="font-weight: 600">项目状态</span>
<span class="value">${projectStatusEnum.value[item.state] ? projectStatusEnum.value[item.state] : "暂无"}</span>
</div>
<div class="info">
<span class="label" style="font-weight: 600">项目造价</span>
<span class="value">${item.engineering_cost || 0}万元</span>
</div>
<div class="info">
<span class="label" style="font-weight: 600">工程面积</span>
<span class="value">${item.engineering_area || 0}</span>
</div>
<div class="info">
<span class="label" style="font-weight: 600">建设单位</span>
<span class="value">${item.enterprise_name || "暂无"}</span>
</div>
<span class="info">
<span class="label" style="font-weight: 600">项目地址</span>
<span class="value">${item.province + item.city + item.district + item.address || "暂无"}</span>
</div>
</div>`;
marker.on("mousemove", markerMousemove);
//
marker.on("mouseout", markerMouseout);
// df
function markerMousemove(e) {
infoWindow.setContent(e.target.content);
infoWindow.open(map, e.target.getPosition());
}
//
function markerMouseout(e) {
infoWindow.setContent(e.target.content);
infoWindow.close(map, e.target.getPosition());
}
marker.setMap(map);
});
//
// // 线
// function addPolyLine() {
// const polyline = new AMap.Polyline({
// path: path.value,
// isOutline: true,
// outlineColor: "#ffeeff",
// borderWeight: 1,
// strokeColor: "#3366FF",
// strokeOpacity: 0.6,
// strokeWeight: 5,
// // 线 'dashed'
// strokeStyle: "solid",
// // strokeStyledashed
// // strokeDasharray: [10, 5],
// lineJoin: "round",
// lineCap: "round",
// zIndex: 50
// });
// map.add([polyline]);
// }
})
.catch(e => {
console.log(e);
});
};
</script>
<style>
.app-container {
width: 100%;
height: 100%;
}
#container {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,9 @@
<template>
<main-view />
</template>
<script setup lang="ts">
import MainView from "./mapView.vue";
</script>
<style></style>

View File

@ -0,0 +1,56 @@
<template>
<div id="mars3dContainer" class="mars3d-container"></div>
</template>
<script lang="ts" setup>
import { onMounted } from "vue";
import * as mars3d from "mars3d";
onMounted(() => {
const configUrl = "http://182.90.224.147:6080/file/config/config.json";
mars3d.Util.fetchJson({ url: configUrl }).then(data => {
initMars3d(data.map3d);
});
});
// const router = useRouter()
let map: any;
const initMars3d = (option: any) => {
map = new mars3d.Map("mars3dContainer", option);
//
// map.openFlyAnimation();
//
if (mars3d.Util.isPCBroswer()) {
map.zoomFactor = 2.0; //
// IE
if (window.navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
map.viewer.targetFrameRate = 20; //
map.scene.requestRenderMode = false; //
}
} else {
map.zoomFactor = 5.0; //
//
map.scene.requestRenderMode = false; //
map.scene.fog.enabled = false;
map.scene.skyAtmosphere.show = false;
map.scene.globe.showGroundAtmosphere = false;
}
// //
if (map.viewer.sceneModePicker) {
map.viewer.sceneModePicker.viewModel.duration = 0.0;
}
};
</script>
<style lang="scss" scoped>
.mars3d-container {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>

View File

@ -0,0 +1,773 @@
<template>
<div class="leftBorder">
<div class="title">
<div class="text">工程数</div>
</div>
<div class="projectNum">
<div v-for="(item, index) in projectNum.newNum" :key="index">
<div class="numItem">{{ item }}</div>
</div>
</div>
<div class="title">
<div class="text">在建工程分类</div>
</div>
<div id="mainCenter"></div>
<div v-for="(item, index) in percentList" :key="index" class="allPercent">
<div :class="item.css">{{ item.number }}</div>
</div>
<div class="title">
<div class="text">扬尘今日预警</div>
</div>
<div class="pieBg">
<div class="imgbg">
<img src="@/assets/images/screenImg/blueCircleBig.gif" alt="" />
</div>
<div id="mainBottom"></div>
</div>
</div>
</template>
<script lang="ts" setup>
import { nextTick, ref, reactive, onMounted } from "vue";
import { getEngineeringAll, getProjectAll, getFugitiveDustAll } from "@/api/modules/largeSreen";
import * as echarts from "echarts";
import "echarts-gl";
import { result } from "lodash";
import { ResponseSame, ScreenResponse } from "@/api/types/common";
onMounted(() => {
projectNumber();
ProjectAll();
FugitiveDustAll();
});
//
const projectNum = reactive({
num: "000000",
newNum: ["0", "0", "0", "0", "0", "0"]
});
const projectNumber = async () => {
const { result } = await getEngineeringAll();
const stringNum = String(result.total / 1000000);
const newNum = stringNum.split(".");
if (newNum[1].length < 6) {
const a = 6 - newNum[1].length;
for (let i = 0; i <= a; i++) {
projectNum.num = newNum[1] + "0";
}
} else {
projectNum.num = newNum[1];
}
projectNum.newNum = projectNum.num.split("");
};
//
const percentList = ref([
{ number: "0", css: "greenPercent", name: "市政公用" },
{ number: "0", css: "bluePercent", name: "房屋建筑" },
{ number: "0", css: "yellowPercent", name: "其他" }
]);
const ProjectAll = async () => {
const { result } = await getProjectAll();
result.forEach((item: { dict_value: string; ratio: string }, index: number) => {
percentList.value.forEach((item2, index: number) => {
if (item.dict_value == item2.name) {
item2.number = item.ratio + "%";
}
});
});
threeDOption(result);
};
const threeDOption = (val: any[] | ResponseSame<ScreenResponse.ProjectAllResponse> | undefined) => {
const chartDom = document.getElementById("mainCenter") as HTMLElement;
const myChart = echarts.init(chartDom);
window.addEventListener("resize", function () {
myChart.resize();
});
//
let nowClientWidth = document.documentElement.clientWidth;
//
function nowSize(val: number, initWidth = 1920) {
return val * (nowClientWidth / initWidth);
}
let allNumber = 0;
const data = [
{
name: "房屋建筑",
value: 0,
itemStyle: {
color: "#3c6fb6"
}
},
{
name: "市政公用",
value: 0,
itemStyle: {
color: "#53d5a3"
}
},
{
name: "其他",
value: 0,
itemStyle: {
color: "#f6bc05"
}
}
];
let temp = 0;
val.forEach((item2: { dict_value: string; num: number }, index: number) => {
temp += Number(item2.num);
data.forEach((item, index) => {
if (item.name == item2.dict_value) {
item.value = Number(item2.num);
}
});
});
allNumber = temp;
console.log(allNumber, data);
function array2obj(array: [], key: string) {
let resObj = {};
for (let i = 0; i < array.length; i++) {
resObj[array[i][key]] = array[i];
}
return resObj;
}
const objData = array2obj(data, "name");
// series-surface.parametricEquation
function getParametricEquation(
startRatio: number,
endRatio: number,
isSelected: boolean,
isHovered: boolean,
k: number,
h: number
) {
//
let midRatio = (startRatio + endRatio) / 2;
let startRadian = startRatio * Math.PI * 2;
let endRadian = endRatio * Math.PI * 2;
let midRadian = midRatio * Math.PI * 2;
//
if (startRatio === 0 && endRatio === 1) {
isSelected = false;
}
// / k 1/3
k = typeof k !== "undefined" ? k : 1 / 3;
// x y 0
let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
// 1
let hoverRate = isHovered ? 1.05 : 1;
//
return {
u: {
min: -Math.PI,
max: Math.PI * 3,
step: Math.PI / 32
},
v: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20
},
x: function (u: number, v: number) {
if (u < startRadian) {
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
},
y: function (u: number, v: number) {
if (u < startRadian) {
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
},
z: function (u: number, v: number) {
if (u < -Math.PI * 0.5) {
return Math.sin(u);
}
if (u > Math.PI * 2.5) {
return Math.sin(u) * h * 0.1;
}
return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
}
};
}
// 3D
function getPie3D(pieData: string | any[], internalDiameterRatio: number) {
let series = [];
let sumValue = 0;
let startValue = 0;
let endValue = 0;
let legendData = [];
let k = typeof internalDiameterRatio !== "undefined" ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio) : 1 / 3;
// series-surface
for (let i = 0; i < pieData.length; i++) {
sumValue += pieData[i].value;
let seriesItem = {
name: typeof pieData[i].name === "undefined" ? `series${i}` : `${pieData[i].name}`,
type: "surface",
parametric: true,
wireframe: {
show: false
},
pieData: pieData[i],
pieStatus: {
selected: false,
hovered: false,
k: k
}
};
if (typeof pieData[i].itemStyle != "undefined") {
let itemStyle = {};
typeof pieData[i].itemStyle.color != "undefined" ? (itemStyle.color = pieData[i].itemStyle.color) : null;
typeof pieData[i].itemStyle.opacity != "undefined" ? (itemStyle.opacity = pieData[i].itemStyle.opacity) : null;
seriesItem.itemStyle = itemStyle;
}
series.push(seriesItem);
}
// 使 sumValue getParametricEquation
// series-surface series-surface.parametricEquation
for (let i = 0; i < series.length; i++) {
endValue = startValue + series[i].pieData.value;
series[i].pieData.startRatio = startValue / sumValue;
series[i].pieData.endRatio = endValue / sumValue;
series[i].parametricEquation = getParametricEquation(
series[i].pieData.startRatio,
series[i].pieData.endRatio,
false,
false,
k,
series[i].pieData.value
);
startValue = endValue;
legendData.push(series[i].name);
}
//
series.push({
// name: "mouseoutSeries",
type: "surface",
parametric: true,
wireframe: {
show: false
},
itemStyle: {
opacity: 0
},
parametricEquation: {
u: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20
},
v: {
min: 0,
max: Math.PI,
step: Math.PI / 20
},
x: function (u: number, v: number) {
return Math.sin(v) * Math.sin(u) + Math.sin(u);
},
y: function (u: number, v: number) {
return Math.sin(v) * Math.cos(u) + Math.cos(u);
},
z: function (u: any, v: number) {
return Math.cos(v) > 0 ? 0.1 : -0.1;
}
}
});
// legendDataseries
let option = {
//animation: false,
legend: {
// orient 'horizontal' | 'vertical'
orient: "horizontal",
x: "center",
y: "left",
itemWidth: nowSize(18),
itemHeight: nowSize(18),
// itemGapitempx10
itemGap: nowSize(30),
formatter: function (name: string) {
return "{title|" + name + "}{value| " + `${objData[name].value}` + "}";
},
textStyle: {
rich: {
title: {
fontSize: nowSize(13),
lineHeight: nowSize(15),
color: "white",
fontFamily: "DigitalRegular"
},
value: {
fontSize: nowSize(19),
lineHeight: nowSize(20),
color: "white",
fontFamily: "YouSheBiaoTiHei"
}
}
}
},
tooltip: {
formatter: (params: { seriesName: string; color: any; seriesIndex: string | number }) => {
if (params.seriesName !== "mouseoutSeries") {
return `${
params.seriesName
}<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
params.color
};"></span>${((option.series[params.seriesIndex].pieData.value / allNumber) * 100).toFixed(1)}%`;
}
}
},
xAxis3D: {
min: -1,
max: 1
},
yAxis3D: {
min: -1,
max: 1
},
zAxis3D: {
min: -1,
max: 1
},
grid3D: {
show: false,
boxHeight: 10,
viewControl: {
//3d
alpha: 40,
// beta: 40,
rotateSensitivity: 0,
zoomSensitivity: 0,
panSensitivity: 0,
autoRotate: false
},
//SSAO
postEffect: {
//齿
enable: true,
bloom: {
enable: true,
bloomIntensity: 0.1
},
SSAO: {
enable: true,
quality: "medium",
radius: 2
}
}
},
series: series
};
return option;
}
// option
let option = getPie3D(data, 0.65);
option && myChart.setOption(option);
};
//
const FugitiveDustAll = async () => {
const { result } = await getFugitiveDustAll();
pieOption(result);
};
const pieOption = (val: ResponseSame<ScreenResponse.FugitiveDustAllResponse> | undefined) => {
const chartDomPie = document.getElementById("mainBottom") as HTMLElement;
const myChartPie = echarts.init(chartDomPie);
window.addEventListener("resize", function () {
myChartPie.resize();
});
//
let nowClientWidth = document.documentElement.clientWidth;
//
function nowSize(val: number, initWidth = 1920) {
return val * (nowClientWidth / initWidth);
}
let scale = 1;
let echartData = [
{
value: 0,
name: "PM10",
itemStyle: {
normal: {
//
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#1d2f31" },
{ offset: 1, color: "#30ab7b" }
])
}
},
labelLine: {
lineStyle: {
color: "#2fa678"
}
},
label: {
normal: {
rich: {
b: {
height: 5,
width: 5,
lineHeight: 15,
marginBottom: 10,
padding: [0, -2.5],
borderRadius: 5,
backgroundColor: "#2fa678" //
}
}
}
}
},
{
value: 0,
name: "噪音",
itemStyle: {
normal: {
//
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#2c2e29" },
{ offset: 1, color: "#f9bd02" }
])
}
},
labelLine: {
lineStyle: {
color: "#e2ad06"
}
},
label: {
normal: {
rich: {
b: {
height: 5,
width: 5,
lineHeight: 15,
marginBottom: 10,
padding: [0, -2.5],
borderRadius: 5,
backgroundColor: "#e2ad06" //
}
}
}
}
},
{
value: 0,
name: "TSP",
itemStyle: {
normal: {
//
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#f04b17" },
{ offset: 1, color: "#2b242b" }
])
}
},
labelLine: {
lineStyle: {
color: "#e94a18"
}
},
label: {
normal: {
rich: {
b: {
height: 5,
width: 5,
lineHeight: 15,
marginBottom: 10,
padding: [0, -2.5],
borderRadius: 5,
backgroundColor: "#e94a18" //
}
}
}
}
},
{
value: 0,
name: "PM2.5",
itemStyle: {
normal: {
//
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#5488d8" },
{ offset: 1, color: "#222c3a" }
])
}
},
labelLine: {
lineStyle: {
color: "#5183cf"
}
},
label: {
normal: {
rich: {
b: {
height: 5,
width: 5,
lineHeight: 15,
marginBottom: 10,
padding: [0, -2.5],
borderRadius: 5,
backgroundColor: "#5183cf" //
}
}
}
}
}
];
let total_datas = 0;
let temp = 0;
val.forEach((item2: { total: any; type: string; num: any }, index: number) => {
temp += Number(item2.num);
echartData.forEach((item, index) => {
if (item.name == item2.type) {
item.value = Number(item2.num);
}
});
});
total_datas = temp;
console.log(total_datas, echartData);
let rich = {
top: {
color: "white",
fontSize: nowSize(13),
left: nowSize(20),
padding: [nowSize(-20), nowSize(-50), nowSize(-20), nowSize(-50)],
fontFamily: "SourceHanSansCNH"
},
total: {
color: "#ffc72b",
fontSize: nowSize(40) * scale,
align: "center"
},
bottom: {
color: "white",
fontSize: nowSize(14),
height: nowSize(5),
width: nowSize(5),
lineHeight: nowSize(5),
marginBottom: nowSize(10),
padding: [nowSize(0), nowSize(-80), nowSize(-15), nowSize(-75)],
borderRadius: nowSize(5),
fontFamily: "OPPOSansB"
},
hr: {
borderColor: "#0b5263",
width: "100%",
borderWidth: nowSize(1),
height: nowSize(0)
}
},
optionPie = {
title: {
text: total_datas,
subtext: "今日报警次数",
itemGap: 5,
top: "top",
padding: [nowSize(108), nowSize(100)],
textStyle: {
color: "#f2f2f2",
fontSize: nowSize(48),
fontFamily: "DigitalRegular"
},
subtextStyle: {
fontSize: nowSize(14),
color: ["#f2f2f2"],
fontFamily: "SourceHanSansCNR"
},
x: "center",
y: "center"
},
series: [
{
name: "违纪总次数",
type: "pie",
radius: ["38%", "50%"],
hoverAnimation: false,
label: {
normal: {
formatter: function (params: { value: number; name: string }) {
let total = 0; //
echartData.forEach(function (value) {
total += value.value;
});
let percent = ((params.value / total) * 100).toFixed(0);
if (percent == "NaN") {
return "{top|" + params.name + "}\n{b| }\n{bottom|" + params.value + "次 / " + 0 + "%}";
} else {
return "{top|" + params.name + "}\n{b| }\n{bottom|" + params.value + "次 / " + percent + "%}";
}
},
rich: rich
}
},
labelLine: {
normal: {
length: nowSize(20),
length2: nowSize(100),
align: "right",
lineStyle: {
width: nowSize(1)
},
emphasis: {
show: true
}
}
},
data: echartData
}
]
};
optionPie && myChartPie.setOption(optionPie);
};
// nextTick(() => {
// });
</script>
<style lang="scss" scoped>
.leftBorder {
position: fixed;
top: 15%;
right: 0;
width: 27%;
height: 100%;
background: url("@/assets/images/screenImg/rightBorder.png") no-repeat right center;
background-size: 100% 100%;
.title {
width: 100%;
height: 50px;
font-family: YouSheBiaoTiHei;
color: white;
background: url("@/assets/images/screenImg/littleTitle.png") no-repeat left center;
background-size: 75%;
.text {
padding: 0 0 0 50px;
font-size: 18px;
}
}
.projectNum {
display: flex;
width: 90%;
height: 100px;
margin-left: 22px;
.numItem {
width: 56px;
height: 62px;
margin-right: 10px;
font-family: DigitalRegular;
font-size: 48px;
line-height: 62px;
color: white;
text-align: center;
background: url("@/assets/images/screenImg/frame.png") no-repeat;
background-size: 100%;
}
}
}
/* stylelint-disable-next-line selector-id-pattern */
#mainCenter {
width: 100%;
height: 290px;
}
.pieBg {
position: relative;
width: 90%;
height: 250px;
.imgbg {
width: 245px;
height: 245px;
margin: 0 auto;
background: url("@/assets/images/screenImg/blueCircleBigbg.png") no-repeat center center;
background-size: 100%;
img {
position: absolute;
top: 14.5%;
left: 31.5%;
width: 174px;
height: 174px;
}
}
/* stylelint-disable-next-line selector-id-pattern */
#mainBottom {
position: absolute;
top: -8.5%;
left: 0;
width: 100%;
height: 290px;
}
}
.allPercent {
// position: relative;
.greenPercent {
position: absolute;
top: 350px;
left: 70px;
width: 76px;
height: 30px;
font-family: OPPOSansH;
font-size: 17px;
color: rgb(48 172 124);
text-align: center;
border-bottom: 5px solid #dddddd;
border-image: linear-gradient(to right, rgb(48 172 124 / 0%), rgb(48 172 124 / 100%)) 30 30;
}
.bluePercent {
position: absolute;
top: 265px;
left: 350px;
width: 76px;
height: 30px;
font-family: OPPOSansH;
font-size: 17px;
color: rgb(49 123 196);
text-align: center;
border-bottom: 5px solid #dddddd;
border-image: linear-gradient(to right, rgb(49 123 196 / 20%), rgb(49 123 196 / 80%)) 30 30;
}
.yellowPercent {
position: absolute;
top: 430px;
left: 320px;
width: 76px;
height: 30px;
font-family: OPPOSansH;
font-size: 17px;
color: rgb(252 191 2);
text-align: center;
border-bottom: 5px solid #dddddd;
border-image: linear-gradient(to right, rgb(252 191 2 / 0%), rgb(252 191 2 / 100%)) 30 30;
}
}
</style>

View File

@ -0,0 +1,65 @@
<template>
<div class="orderBgc">
<!-- <Map3D class="mapStyle"></Map3D> -->
<Map2D class="mapStyle"></Map2D>
<headerScreen class="topHeader"></headerScreen>
<div class="bottomContent">
<leftScreen class="leftScreen"></leftScreen>
<centerScreen class="centerScreen"></centerScreen>
<rightScreen class="rightScreen"></rightScreen>
</div>
<div class="borderBottom"></div>
</div>
</template>
<script lang="ts" setup>
import { onMounted } from "vue";
import headerScreen from "./components/header.vue";
import centerScreen from "./components/center.vue";
import leftScreen from "./components/left.vue";
import rightScreen from "./components/right.vue";
import Map3D from "./components/map3D.vue";
import Map2D from "./components/map2D.vue";
</script>
<style lang="scss" scoped>
.orderBgc {
width: 100%;
height: 100%;
.mapStyle {
position: absolute;
}
.topHeader {
width: 100%;
height: 15%;
// background: linear-gradient(to right, rgb(17 20 25 / 60%), rgb(17 20 25 / 20%), rgb(17 20 25 / 60%));
}
.bottomContent {
display: flex;
width: 100%;
height: 79%;
.leftScreen {
flex: 2.5;
height: 100%;
}
.centerScreen {
flex: 5;
height: 100px;
}
.rightScreen {
flex: 2.5;
height: 100%;
}
}
.borderBottom {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 6%;
background: url("@/assets/images/screenImg/bottomBorder.png") no-repeat center bottom;
background-size: 100%;
}
}
</style>

View File

@ -1,136 +1,150 @@
import { defineConfig, loadEnv, ConfigEnv, UserConfig } from "vite";
import { createHtmlPlugin } from "vite-plugin-html";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import { wrapperEnv } from "./src/utils/getEnv";
import { visualizer } from "rollup-plugin-visualizer";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import viteCompression from "vite-plugin-compression";
import vueSetupExtend from "vite-plugin-vue-setup-extend-plus";
import eslintPlugin from "vite-plugin-eslint";
import vueJsx from "@vitejs/plugin-vue-jsx";
import importToCDN from "vite-plugin-cdn-import";
// import AutoImport from "unplugin-auto-import/vite";
// import Components from "unplugin-vue-components/vite";
// import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
// @see: https://vitejs.dev/config/
// export const BASE_IMAGE_URL = import.meta.env.NODE_ENV === "development" ? "./src" : "";
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
const env = loadEnv(mode, process.cwd());
const viteEnv = wrapperEnv(env);
return {
base: "./",
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
"vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js"
}
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/var.scss";`
}
}
},
server: {
// 服务器主机名,如果允许外部访问,可设置为 "0.0.0.0"
host: "0.0.0.0",
port: viteEnv.VITE_PORT,
open: viteEnv.VITE_OPEN,
cors: true,
// 跨域代理配置
proxy: {
"/api": {
target: viteEnv.VITE_API_URL, // easymock
// target: "https://www.fastmock.site/mock/f81e8333c1a9276214bcdbc170d9e0a0", // fastmock
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, "")
}
}
},
plugins: [
vue(),
createHtmlPlugin({
inject: {
data: {
title: viteEnv.VITE_GLOB_APP_TITLE
}
}
}),
// * 使用 svg 图标
createSvgIconsPlugin({
iconDirs: [resolve(process.cwd(), "src/assets/icons")],
symbolId: "icon-[dir]-[name]"
}),
// * EsLint 报错信息显示在浏览器界面上
// eslintPlugin(),
// * vite 可以使用 jsx/tsx 语法
vueJsx(),
// * name 可以写在 script 标签上
vueSetupExtend(),
// * 是否生成包预览(分析依赖包大小,方便做优化处理)
viteEnv.VITE_REPORT && visualizer(),
// * gzip compress
viteEnv.VITE_BUILD_GZIP &&
viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: "gzip",
ext: ".gz"
}),
// * cdn 引入vue按需引入会导致依赖vue的插件出现问题(列如:pinia/vuex)
importToCDN({
modules: [
// {
// name: "vue",
// var: "Vue",
// path: "https://unpkg.com/vue@next"
// },
// 使用cdn引入element-plus时,开发环境还是需要在main.js中引入element-plus,可以不用引入css
// {
// name: "element-plus",
// var: "ElementPlus",
// path: "https://unpkg.com/element-plus",
// css: "https://unpkg.com/element-plus/dist/index.css"
// }
]
})
// * demand import element
// AutoImport({
// resolvers: [ElementPlusResolver()]
// }),
// Components({
// resolvers: [ElementPlusResolver()]
// }),
],
// * 打包去除 console.log && debugger
esbuild: {
pure: viteEnv.VITE_DROP_CONSOLE ? ["console.log", "debugger"] : []
},
build: {
outDir: "dist",
minify: "esbuild",
// esbuild 打包更快,但是不能去除 console.logterser打包慢但能去除 console.log
// minify: "terser",
// terserOptions: {
// compress: {
// drop_console: viteEnv.VITE_DROP_CONSOLE,
// drop_debugger: true
// }
// },
chunkSizeWarningLimit: 2500,
rollupOptions: {
output: {
// Static resource classification and packaging
chunkFileNames: "assets/js/[name]-[hash].js",
entryFileNames: "assets/js/[name]-[hash].js",
assetFileNames: "assets/[ext]/[name]-[hash].[ext]"
}
}
}
};
});
import { defineConfig, loadEnv, ConfigEnv, UserConfig } from "vite";
import { createHtmlPlugin } from "vite-plugin-html";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import { wrapperEnv } from "./src/utils/getEnv";
import { visualizer } from "rollup-plugin-visualizer";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import viteCompression from "vite-plugin-compression";
import vueSetupExtend from "vite-plugin-vue-setup-extend-plus";
import eslintPlugin from "vite-plugin-eslint";
import vueJsx from "@vitejs/plugin-vue-jsx";
import importToCDN from "vite-plugin-cdn-import";
// import AutoImport from "unplugin-auto-import/vite";
// import Components from "unplugin-vue-components/vite";
// import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import { vitePluginMars3d } from "vite-plugin-mars3d";
// @see: https://vitejs.dev/config/
// export const BASE_IMAGE_URL = import.meta.env.NODE_ENV === "development" ? "./src" : "";
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
const env = loadEnv(mode, process.cwd());
const viteEnv = wrapperEnv(env);
return {
base: "./",
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
"vue-i18n": "vue-i18n/dist/vue-i18n.cjs.js"
}
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/styles/var.scss";`
}
}
},
server: {
// 服务器主机名,如果允许外部访问,可设置为 "0.0.0.0"
host: "0.0.0.0",
port: viteEnv.VITE_PORT,
open: viteEnv.VITE_OPEN,
cors: true,
// 跨域代理配置
proxy: {
"/api": {
target: viteEnv.VITE_API_URL, // easymock
// target: "https://www.fastmock.site/mock/f81e8333c1a9276214bcdbc170d9e0a0", // fastmock
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, "")
}
}
// open: true,
// host: "localhost",
// port: 8520,
// //这里的ip和端口是前端项目的;下面为需要跨域访问后端项目
// proxy: {
// "^/token": {
// target: "http://192.168.34.155:8520/", //这里填入你要请求的接口的前缀
// ws: true, //代理websocket
// changeOrigin: true, //虚拟的站点需要更管origin
// secure: true, //是否https接口
// rewrite: path => path.replace(/^\/api/, "")
// }
// }
},
plugins: [
vue(),
vitePluginMars3d(),
createHtmlPlugin({
inject: {
data: {
title: viteEnv.VITE_GLOB_APP_TITLE
}
}
}),
// * 使用 svg 图标
createSvgIconsPlugin({
iconDirs: [resolve(process.cwd(), "src/assets/icons")],
symbolId: "icon-[dir]-[name]"
}),
// * EsLint 报错信息显示在浏览器界面上
// eslintPlugin(),
// * vite 可以使用 jsx/tsx 语法
vueJsx(),
// * name 可以写在 script 标签上
vueSetupExtend(),
// * 是否生成包预览(分析依赖包大小,方便做优化处理)
viteEnv.VITE_REPORT && visualizer(),
// * gzip compress
viteEnv.VITE_BUILD_GZIP &&
viteCompression({
verbose: true,
disable: false,
threshold: 10240,
algorithm: "gzip",
ext: ".gz"
}),
// * cdn 引入vue按需引入会导致依赖vue的插件出现问题(列如:pinia/vuex)
importToCDN({
modules: [
// {
// name: "vue",
// var: "Vue",
// path: "https://unpkg.com/vue@next"
// },
// 使用cdn引入element-plus时,开发环境还是需要在main.js中引入element-plus,可以不用引入css
// {
// name: "element-plus",
// var: "ElementPlus",
// path: "https://unpkg.com/element-plus",
// css: "https://unpkg.com/element-plus/dist/index.css"
// }
]
})
// * demand import element
// AutoImport({
// resolvers: [ElementPlusResolver()]
// }),
// Components({
// resolvers: [ElementPlusResolver()]
// }),
],
// * 打包去除 console.log && debugger
esbuild: {
pure: viteEnv.VITE_DROP_CONSOLE ? ["console.log", "debugger"] : []
},
build: {
outDir: "dist",
minify: "esbuild",
// esbuild 打包更快,但是不能去除 console.logterser打包慢但能去除 console.log
// minify: "terser",
// terserOptions: {
// compress: {
// drop_console: viteEnv.VITE_DROP_CONSOLE,
// drop_debugger: true
// }
// },
chunkSizeWarningLimit: 2500,
rollupOptions: {
output: {
// Static resource classification and packaging
chunkFileNames: "assets/js/[name]-[hash].js",
entryFileNames: "assets/js/[name]-[hash].js",
assetFileNames: "assets/[ext]/[name]-[hash].[ext]"
}
}
}
};
});