zjs_project 2 years ago
commit
11a325275f
71 changed files with 22445 additions and 0 deletions
  1. 23 0
      .gitignore
  2. 24 0
      README.md
  3. 5 0
      babel.config.js
  4. 19 0
      jsconfig.json
  5. 15624 0
      package-lock.json
  6. 67 0
      package.json
  7. BIN
      public/favicon.ico
  8. 18 0
      public/index.html
  9. 284 0
      src/App.vue
  10. 903 0
      src/assets/common.css
  11. 234 0
      src/assets/common.scss
  12. 311 0
      src/assets/css/common.css
  13. 135 0
      src/assets/css/style.css
  14. 1035 0
      src/assets/font/iconfont.css
  15. BIN
      src/assets/font/iconfont.ttf
  16. BIN
      src/assets/font/iconfont.woff
  17. BIN
      src/assets/font/iconfont.woff2
  18. BIN
      src/assets/img/C2B@2x.png
  19. BIN
      src/assets/img/bg_balance.png
  20. BIN
      src/assets/img/bg_cost.png
  21. BIN
      src/assets/img/bg_money.png
  22. BIN
      src/assets/img/brand_1.png
  23. BIN
      src/assets/img/brand_2.png
  24. BIN
      src/assets/img/brand_3.png
  25. BIN
      src/assets/img/brand_4.png
  26. BIN
      src/assets/img/brand_5.png
  27. BIN
      src/assets/img/icon_clear_text.png
  28. BIN
      src/assets/img/icon_eye_project.png
  29. BIN
      src/assets/img/icon_money.png
  30. BIN
      src/assets/img/keyan-graph.png
  31. BIN
      src/assets/img/keyan-line.png
  32. BIN
      src/assets/img/keyan1.png
  33. BIN
      src/assets/img/other.png
  34. BIN
      src/assets/img/phone.png
  35. BIN
      src/assets/img/point.png
  36. BIN
      src/assets/img/pre-order1.png
  37. BIN
      src/assets/img/pre-order2.png
  38. BIN
      src/assets/img/组 23947.png
  39. BIN
      src/assets/logo.png
  40. 26 0
      src/components/leftOperateComp/leftOperateComp.css
  41. 11 0
      src/components/leftOperateComp/leftOperateComp.html
  42. 86 0
      src/components/leftOperateComp/leftOperateComp.vue
  43. 41 0
      src/components/mapComponent/mapComponent.css
  44. 9 0
      src/components/mapComponent/mapComponent.html
  45. 690 0
      src/components/mapComponent/mapComponent.vue
  46. 56 0
      src/main.js
  47. 604 0
      src/mixins/cropper.js
  48. 40 0
      src/pages/loginView/loginView.html
  49. 171 0
      src/pages/loginView/loginView.scss
  50. 162 0
      src/pages/loginView/loginView.vue
  51. 8 0
      src/pages/mainView/mainView.html
  52. 1 0
      src/pages/mainView/mainView.scss
  53. 126 0
      src/pages/mainView/mainView.vue
  54. 35 0
      src/router/index.js
  55. 93 0
      src/services/request.js
  56. 84 0
      src/services/requestConfig.js
  57. 186 0
      src/services/urlConfig.js
  58. 23 0
      src/store/actions.js
  59. 12 0
      src/store/index.js
  60. 12 0
      src/store/mutations.js
  61. 7 0
      src/store/state.js
  62. 165 0
      src/utils/command.js
  63. 294 0
      src/utils/common.js
  64. 317 0
      src/utils/interface.js
  65. 52 0
      src/utils/localStorage.js
  66. 15 0
      src/utils/rem.js
  67. 20 0
      src/utils/resetMessage.js
  68. 23 0
      src/utils/time.js
  69. 146 0
      src/utils/util.js
  70. 220 0
      src/vendor/Export2Excel.js
  71. 28 0
      vue.config.js

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 24 - 0
README.md

@@ -0,0 +1,24 @@
+# hello-world
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 5 - 0
babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

+ 19 - 0
jsconfig.json

@@ -0,0 +1,19 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "module": "esnext",
+    "baseUrl": "./",
+    "moduleResolution": "node",
+    "paths": {
+      "@/*": [
+        "src/*"
+      ]
+    },
+    "lib": [
+      "esnext",
+      "dom",
+      "dom.iterable",
+      "scripthost"
+    ]
+  }
+}

File diff suppressed because it is too large
+ 15624 - 0
package-lock.json


+ 67 - 0
package.json

@@ -0,0 +1,67 @@
+{
+  "name": "hello-world",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "serve": "vue-cli-service serve",
+    "lint": "vue-cli-service lint",
+    "build": "cross-env NODE_ENV=production vue-cli-service build",
+    "test": "cross-env NODE_ENV=test vue-cli-service build",
+    "test2": "cross-env NODE_ENV=test2 vue-cli-service build",
+    "test3": "cross-env NODE_ENV=test3 vue-cli-service build",
+    "test4": "cross-env NODE_ENV=test4 vue-cli-service build",
+    "prod": "cross-env NODE_ENV=production vue-cli-service build",
+    "uat": "cross-env NODE_ENV=uat vue-cli-service build",
+    "uat3": "cross-env NODE_ENV=uat3 vue-cli-service build"
+  },
+  "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
+    "@better-scroll/core": "^2.4.2",
+    "axios": "^0.21.1",
+    "better-scroll": "^2.4.2",
+    "core-js": "^3.8.3",
+    "echarts": "^4.0.0",
+    "element-ui": "2.15.8",
+    "jquery": "^3.6.0",
+    "qiniu-js": "^2.4.0",
+    "three": "^0.154.0",
+    "vue": "^2.6.14",
+    "vue-count-to": "^1.0.13",
+    "vue-loader": "^15.9.3",
+    "vue-router": "^3.5.3",
+    "vuex": "^3.0.1"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.12.16",
+    "@babel/eslint-parser": "^7.12.16",
+    "@vue/cli-plugin-babel": "~5.0.0",
+    "@vue/cli-plugin-eslint": "~5.0.0",
+    "@vue/cli-service": "~5.0.0",
+    "cross-env": "^7.0.3",
+    "eslint": "^7.32.0",
+    "eslint-plugin-vue": "^8.0.3",
+    "node-sass": "^4.14.1",
+    "sass-loader": "^7.3.1",
+    "vue-template-compiler": "^2.6.14"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "eslint:recommended"
+    ],
+    "parserOptions": {
+      "parser": "@babel/eslint-parser"
+    },
+    "rules": {}
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not dead"
+  ]
+}

BIN
public/favicon.ico


+ 18 - 0
public/index.html

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+	<meta http-equiv="Access-Control-Allow-Origin" content="*">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title><%= htmlWebpackPlugin.options.title %></title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 284 - 0
src/App.vue

@@ -0,0 +1,284 @@
+<template>
+	<div id="app">
+		<router-view v-if="isRouterAlive" />
+		<div class="loadingShadow" v-show="loading">
+			<div class="loadData">
+				<img src="https://skyforest.static.elaber.cn/detail/loading.gif" alt="" />
+				<div class="loadingMsg">{{loadingMsg}}</div>
+			</div>
+		</div>
+		<div class="loadingShadow rows justify-center" v-show="showAccountView">
+			<div class="account-view">
+				<!--顶部-->
+				<div class="title rows rows-between">
+					<div class="rows" style="margin-right:10rem">
+						<img class="title-icon" src="https://dm.static.elab-plus.com/thing/ty/zhsq.png">
+						账号选择
+					</div>
+					<div class="close" @click="closeFun">
+						<i class="el-icon-close close-img"></i>
+					</div>
+				</div>
+				<div class="content" style="margin-top:20rem;">
+					<div class="">选择关联账号</div>
+					<div class="content-main-view" style="margin-top:10rem;">
+						<div class="rows rows-between" @click="accountChange(item)"
+							style="margin-bottom:20rem;cursor: pointer;" v-for="(item,index) in acountList"
+							:key="index">
+							<div class="rows">
+								<div style="margin-right:18rem;">
+									<div v-if="selectAccount && selectAccount.advertiserId == item.advertiserId"
+										class="selcect-view"></div>
+									<div v-else class="unselcect-view"></div>
+								</div>
+								<div>{{item.name}}{{' ID'+item.advertiserId}})</div>
+							</div>
+							<div v-if="selectAccount && selectAccount.advertiserId == item.advertiserId"
+								class="icon-gougou iconfont gougou-icon"></div>
+						</div>
+					</div>
+				</div>
+				<div class="auth-btn-view rows justify-center" style="margin-top:35rem">
+					<div class="auth-btn style2 rows justify-center" @click="accountConfirm">确定</div>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+	import {
+		getStorage,
+		removeItem
+	} from '@/utils/localStorage';
+	export default {
+		name: "App",
+		provide() {
+			return {
+				reload: this.reload,
+			};
+		},
+		data() {
+			return {
+				themeColor: "rgba(0,97,232,1)",
+				themeColor2: "rgba(0,97,232,0.2)",
+				isRouterAlive: true,
+				showAccountView: false, //是否显示用户账号列表
+				acountList: [], //弹出层账号列表数据
+				selectAccount: null, //选中的账号
+			};
+		},
+		created() {
+			document.addEventListener('visibilitychange', (event) => {
+				console.warn("***pageshow-handle***", event, document.hidden, document.visibilityState)
+				//外链回退到vue应用要执行的代码
+				if (document.visibilityState == 'visible') { //页面显示
+					this.accountHandle()
+				}
+			})
+			this.accountHandle(true)
+		},
+		watch: {
+			loading: {
+				handler(newVal) {
+					if (!newVal) {
+						this.$store.state.loadingMsg = ''
+					}
+				}
+			}
+		},
+		computed: {
+			loading() {
+				return this.$store.state.loading;
+			},
+			loadingMsg() {
+				if (this.$store.state.loadingMsg) {
+					return this.$store.state.loadingMsg;
+				} else {
+					return "正在查询,请耐心等待";
+				}
+			}
+		},
+		mounted() {
+			// 禁止图片单机事件,防止出现图片点击浏览器自动预览功能
+			document.body.addEventListener("click", function(e) {
+				if (e.target.nodeName.toLowerCase() == "img") {
+					e.preventDefault();
+				}
+			});
+		},
+		methods: {
+			reload() {
+				this.isRouterAlive = false;
+				this.$nextTick(function() {
+					this.isRouterAlive = true;
+				});
+			},
+			//账号获取
+			accountHandle(type = false) {
+				var acountList = getStorage('acountList') ? JSON.parse(getStorage('acountList')) : null;
+				console.warn("***acountList***", acountList);
+				if (acountList) {
+					if (acountList.length > 1) {
+						this.selectAccount = null;
+						this.acountList = acountList;
+						this.showAccountView = true;
+					} else {
+						this.showAccountView = false;
+						this.selectAccount = acountList[0];
+						removeItem('acountList'); //移除待选择列表的账号数据
+						if (type) { //页面加载时触发
+							setTimeout(() => { //等待其他组件创建好对应的事件监听
+								window.$bus.$emit("projectUpdate", this.$route.query.projectId, this
+								.selectAccount);
+								window.$bus.$emit("setAccount", this.selectAccount);
+							}, 5000);
+						} else { //页面出现时触发-非初次加载
+							window.$bus.$emit("projectUpdate", this.$route.query.projectId, this.selectAccount);
+							window.$bus.$emit("setAccount", this.selectAccount);
+						}
+
+					}
+				} else {
+					this.showAccountView = false;
+				}
+			},
+			closeFun() {
+				this.showAccountView = false;
+			},
+			//账号选择
+			accountChange(item) {
+				if (!item) {
+					return false;
+				}
+				this.selectAccount = item;
+			},
+			//确认账号选择
+			async accountConfirm() {
+				if (!this.selectAccount) {
+					this.$message.warning("请选择关联账号!");
+					return false;
+				}
+				// let userInfo = window.userInfo;
+				// userInfo['userAccount'] = this.selectAccount;
+				removeItem('acountList'); //选择好后,移除待选择列表的账号数据
+				this.showAccountView = false;
+				let res = await requestConfig('bindAdvertiser', {
+					"advertiserId": this.selectAccount.advertiserId,
+					"companyId": window.userCompanyModel.companyId,
+					"name": this.selectAccount.name,
+					"platform": this.selectAccount.platform || '',
+					"oauthType": this.getAuthType(),
+				}, false, false)
+				if (res.success) {
+					// this.$store.dispatch('setAccount',this.selectAccount);
+					window.$bus.$emit("projectUpdate", this.$route.query.projectId, this.selectAccount);
+					window.$bus.$emit("setAccount", this.selectAccount);
+					removeItem("OAUTHTYPE");
+				}
+			},
+			getAuthType() {
+				const oauthType = JSON.parse(window.localStorage.getItem('OAUTHTYPE')) || '';
+				if (oauthType) {
+					return oauthType.accountType
+				} else {
+					return "2" //默认是2
+				}
+			},
+		},
+	};
+</script>
+
+<style>
+	#app {
+		font-family: Avenir, Helvetica, Arial, sans-serif;
+		-webkit-font-smoothing: antialiased;
+		-moz-osx-font-smoothing: grayscale;
+		/* text-align: center;
+		color: #2c3e50;
+		margin-top: 60px; */
+	}
+
+	body {
+		background: #181C28;
+	}
+
+	.el-tooltip__popper.is-light {
+		backdrop-filter: blur(10.36rem) !important;
+		background-color: rgba(255, 255, 255, 0.4) !important;
+		border: none !important;
+		color: #ffffff !important;
+	}
+
+
+	.el-tooltip__popper .popper__arrow,
+	.el-tooltip__popper .popper__arrow::after {
+		border-style: none !important;
+	}
+
+	.el-picker-panel__body .el-date-picker__header .el-picker-panel__icon-btn {
+		color: #FFFFFF;
+	}
+
+	.el-picker-panel__body .el-date-picker__header .el-date-picker__header-label {
+		color: #FFFFFF;
+	}
+
+	.el-picker-panel__body .el-picker-panel__content .el-date-table th {
+		color: #FFFFFF;
+	}
+
+	.dropdown-view-menu {
+		font-size: 14px;
+		color: var(--themeColor9);
+		/* width: 336rem; */
+		box-sizing: border-box;
+		padding: 15rem !important;
+		margin-top: 3rem;
+		backdrop-filter: blur(60px);
+		border: none !important;
+		background-color: rgba(255, 255, 255, 0.15) !important;
+		white-space: nowrap;
+		overflow: hidden;
+		text-overflow: ellipsis;
+	}
+
+	.dropdown-view-menu .active {
+		color: #CEF7D1;
+	}
+
+	.dropdown-view-text {
+		font-family: "Verdana Bold";
+		font-weight: 700;
+		text-decoration: underline;
+		font-size: 14px;
+		color: #fff;
+	}
+
+	.select-julangview {
+		display: none;
+	}
+
+	.popper-class-qr {
+		padding: 0px !important;
+	}
+
+	.BMap_cpyCtrl {
+		display: none;
+	}
+
+	.anchorBL {
+		display: none;
+	}
+
+	.amap-logo img {
+		display: none;
+	}
+
+	.amap-copyright {
+		opacity: 0;
+	}
+</style>
+<style lang="scss" scoped>
+	@import "./assets/common.scss";
+</style>

+ 903 - 0
src/assets/common.css

@@ -0,0 +1,903 @@
+* {
+    margin: 0;
+    padding: 0;
+}
+
+body {
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+}
+
+div {
+    box-sizing: border-box;
+}
+
+.rows {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+}
+
+.rows-between {
+    justify-content: space-between;
+}
+
+.columns {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: space-between;
+}
+
+.eslipe {
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+}
+
+.flex-start {
+    align-items: flex-start;
+}
+
+.flex-end {
+    justify-content: flex-end;
+}
+
+.justify-center {
+    justify-content: center;
+}
+
+.justify-content-start {
+    justify-content: flex-start;
+}
+
+.flex-1 {
+    flex: 1;
+}
+
+.grid-view {
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    /* grid-row-gap: 20rem; */
+    grid-gap: 20rem 80rem;
+}
+
+::-webkit-scrollbar {
+    width: 0;
+    height: 0;
+    color: transparent;
+}
+
+.el-checkbox__inner {
+    border-color: #EF863F;
+}
+
+.el-checkbox__inner:hover {
+    border-color: #EF863F;
+}
+
+.pointer {
+    cursor: pointer
+}
+
+
+/* 项目提示信息 */
+
+.infoWindowHtml {
+    z-index: 1000!important;
+    cursor: pointer;
+}
+
+.project-content {
+    position: relative;
+    /* float: left; */
+    /* width: auto; */
+    width: 300rem;
+    padding: 15rem 20rem;
+    box-sizing: border-box;
+    /* background: linear-gradient(90deg,#000000 1%, rgba(0,0,0,0.00));
+	backdrop-filter: blur(30.24rem); */
+    padding-bottom: 4rem;
+    cursor: pointer;
+}
+
+.filter-view {
+    position: absolute;
+    width: 100%;
+    height: 100%;
+    ;
+    left: 0rem;
+    top: 0rem;
+    filter: blur(30rem);
+    background: linear-gradient(90deg, #000000 1%, rgba(0, 0, 0, 0.00));
+    border-radius: 12px;
+    backdrop-filter: blur(10.02px);
+    z-index: -1;
+}
+
+.project-head {
+    width: 40rem;
+    height: 40rem;
+    line-height: 40rem;
+    background: rgba(0, 0, 0, 0.00);
+    border: 1rem solid rgba(255, 255, 255, 0.33);
+    border-radius: 50%;
+    margin-right: 8rem;
+    font-size: 18px;
+    font-family: Verdana, Verdana-Bold;
+    font-weight: 700;
+    text-align: center;
+    color: #ffffff;
+    object-fit: cover;
+}
+
+.project-name {
+    height: 28rem;
+    line-height: 28rem;
+    font-size: 20px;
+    font-family: Verdana, Verdana-Bold;
+    font-weight: 700;
+    text-align: left;
+    color: #ffffff;
+}
+
+.project-address {
+    height: 17rem;
+    line-height: 17rem;
+    opacity: 0.5;
+    font-size: 12px;
+    font-family: Verdana, Verdana-Bold;
+    font-weight: 400;
+    text-align: left;
+    color: #ffffff;
+}
+
+.project-tips {
+    width: 40rem;
+    height: 22rem;
+    background: rgba(255, 255, 255, 0.2);
+    border-radius: 4rem;
+    font-size: 14px;
+    font-family: FontName, FontName-Regular;
+    font-weight: 400;
+    text-align: center;
+    color: #ffffff;
+    line-height: 22rem;
+    font-style: italic;
+    margin-left: 10rem;
+}
+
+.project-area {
+    margin-top: 6rem;
+    height: 20rem;
+    line-height: 20rem;
+    font-size: 14px;
+    font-family: Verdana, Verdana-Bold;
+    font-weight: 700;
+    text-align: left;
+    color: #ffffff;
+    overflow: hidden;
+}
+
+.project-footer {
+    position: relative;
+    width: 100%;
+    height: 10rem;
+    margin-top: 10rem;
+    overflow: hidden;
+}
+
+.project-footer-top {
+    width: 100%;
+    height: 4rem;
+    background: linear-gradient(90deg, var(--themeColor4) 1%, transparent);
+}
+
+.project-footer-left {
+    position: absolute;
+    top: 0rem;
+    border-width: 10rem;
+    border-top-color: transparent;
+    border-right-color: transparent;
+    border-bottom-color: transparent;
+    border-left-color: var(--themeColor4);
+    border-style: solid;
+    border-left-width: 5rem;
+    border-top-width: 0rem;
+}
+
+.polyon-content {
+    float: left;
+    width: auto;
+    font-size: 14px;
+    white-space: nowrap;
+    font-family: Verdana, Verdana-Bold;
+    font-weight: 700;
+    text-align: center;
+    color: var(--themeColor1);
+    text-shadow: 0rem 0rem #000000;
+}
+
+.competitionProjectHide {
+    display: none !important;
+}
+
+.competitionProjectShow {
+    display: flex;
+}
+
+.infoWindowUnSelected .project-head {
+    display: none;
+}
+
+.infoWindowUnSelected .project-name {
+    height: 20rem;
+    line-height: 20rem;
+    font-size: 14px;
+}
+
+.infoWindowSelected .project-tips,
+.infoWindowUnSelected .project-tips {
+    display: none;
+}
+
+.infoWindowHtml.infoWindowSelected {
+    z-index: 1001!important;
+}
+
+.infoWindowUnSelected .project-address {
+    display: none;
+}
+
+.infoWindowUnSelected .project-area {
+    height: 17rem;
+    line-height: 17rem;
+    opacity: 0.6;
+    font-size: 12px;
+    margin-top: 0rem;
+}
+
+.infoWindowUnSelected .project-footer {
+    margin-top: 8rem;
+}
+
+.competitionUnSelected .project-name {
+    height: 20rem;
+    line-height: 20rem;
+    font-size: 14px;
+}
+
+.competitionUnSelected .project-area {
+    display: none;
+}
+
+
+/* 项目竞品状态 */
+
+.competitionProject .project-name {
+    height: 20rem;
+    line-height: 20rem;
+    font-size: 14px;
+}
+
+.competitionProject .project-head,
+.competitionProject .project-area,
+.competitionProject .project-address {
+    display: none;
+}
+
+
+/* 圆柱样式 */
+
+.cricleColumn-view {
+    position: relative;
+    width: 90rem;
+    height: 152rem;
+    cursor: pointer;
+}
+
+.cricleColumn-img {
+    width: 90rem;
+    height: 152rem;
+}
+
+.cricleColumn-text {
+    position: absolute;
+    bottom: 0rem;
+    left: 0rem;
+    width: 100%;
+    height: 37rem;
+    font-size: 14px;
+    font-family: DIN Alternate, DIN Alternate-Bold;
+    font-weight: 700;
+    text-align: center;
+    color: #ffdf80;
+    line-height: 14rem;
+}
+
+.cricleColumn1-view {
+    position: relative;
+    width: 82rem;
+    height: 152rem;
+    cursor: pointer;
+}
+
+.cricleColumn1-img {
+    width: 82rem;
+    height: 152rem;
+}
+
+.cricleColumn2-view {
+    width: 60px;
+    height: 60px;
+}
+
+.cricleColumn2-img {
+    width: 100%;
+    height: 100%;
+}
+
+.cricleColumn1-text {
+    position: absolute;
+    bottom: 14rem;
+    left: 0rem;
+    width: 100%;
+    font-size: 14px;
+    font-family: DIN Alternate, DIN Alternate-Bold;
+    font-weight: 700;
+    text-align: center;
+    color: #fff;
+    line-height: 20rem;
+}
+
+.project-plate2{
+    display: flex;
+    flex-direction: column;
+    width: 40px;
+    height: 58px;
+    align-items: center;
+}
+
+
+.plate-point-icon2{
+    width: 10rem;
+    height: 10rem;
+    min-height: 10rem;
+    background: #FFDB89;
+    border-radius: 50%;
+    margin-top: 15rem;
+}
+
+.plate-point-name-img2{
+    width: 35px;
+    height: 35px;
+    border-radius: 50%;
+    transform: rotate(45deg);
+}
+
+.plate-point-name2{
+    background: #FFDB89;
+    width: 40px;
+    min-width: 40px;
+    height: 40px;
+    min-height: 40px;
+    border-top-left-radius: 50%;
+    border-top-right-radius: 50%;
+    border-bottom-right-radius: 50%;
+    border-bottom-left-radius: 3px;
+    transform: rotate(-45deg);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+.plate-point-name-txt2 {
+    font-size: 18px;
+    font-family: Verdana, Verdana-Bold;
+    text-align: center;
+    color: #ffffff;
+    transform: rotate(45deg);
+    overflow: hidden;
+    white-space: nowrap;
+    width: 40px;
+}
+
+.el-picker-panel__content .el-date-table td.disabled div{
+    background: transparent;
+}
+
+.el-date-table td.current:not(.disabled) span{
+    background-color: var(--themeColor1);
+}
+.el-date-table td.today span{
+    color: var(--themeColor1);
+}
+.el-date-table td:hover{
+    color: var(--themeColor1);
+}
+
+.project-plate {
+    display: flex;
+    flex-direction: row;
+    width: 265px;
+    height: 58px;
+    align-items: center;
+}
+
+.plate-point-icon {
+    width: 10rem;
+    height: 10rem;
+    background: #fede7f;
+    border-radius: 50%;
+    margin-left: 20rem;
+}
+
+.plate-point-name {
+    font-size: 16px;
+    font-family: Verdana, Verdana-Bold;
+    font-weight: 700;
+    text-align: left;
+    color: #ffffff;
+    margin-left: 10rem;
+    background: #181C28;
+    border-radius: 6rem;
+    padding: 6rem 10rem;
+}
+
+.plate-point-name-img {
+    width: 35px;
+    height: 35px;
+    border-radius: 50%;
+    transform: rotate(45deg);
+}
+
+.plate-point-name-txt {
+    font-size: 18px;
+    font-family: Verdana, Verdana-Bold;
+    font-weight: 700;
+    text-align: center;
+    color: #ffffff;
+    transform: rotate(45deg);
+    overflow: hidden;
+    white-space: nowrap;
+    width: 40px;
+}
+
+.cricleColumn2-text {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    width: 100%;
+    font-size: 12px;
+    font-family: DIN Alternate, DIN Alternate-Bold;
+    text-align: center;
+    color: #fff;
+}
+
+.poi-view {
+    position: relative;
+    width: max-content;
+    height: 30rem;
+    background: rgba(255, 255, 255, 0.2);
+    border-radius: 15rem;
+    backdrop-filter: blur(30rem);
+    cursor: pointer;
+}
+
+.poi-view-radius {
+    width: 24rem;
+    height: 24rem;
+    line-height: 22rem;
+    background: rgba(118, 188, 255, 0.50);
+    border: 1px solid #76bcff;
+    border-radius: 50%;
+    font-size: 12px;
+    font-family: Verdana, Verdana-Regular;
+    font-weight: 400;
+    text-align: center;
+    color: #ffffff;
+    margin-left: 4rem;
+}
+
+.poi-view-text {
+    font-size: 14px;
+    font-family: Verdana, Verdana-Regular;
+    font-weight: 400;
+    text-align: left;
+    color: #ffffff;
+    margin-left: 5rem;
+    margin-right: 10rem;
+}
+
+.poi-point {
+    border-radius: 50%;
+    width: 10rem;
+    height: 10rem;
+    background: #ffad5c;
+    border: 1rem solid #fff;
+}
+
+.poi-view-poi {
+    position: relative;
+    width: max-content;
+    background: rgba(255, 255, 255, 0.2);
+    border-radius: 5rem;
+    backdrop-filter: blur(30rem);
+    cursor: pointer;
+    padding: 10rem;
+    display: flex;
+    align-items: center;
+}
+
+.poi-view-poi-num {
+    width: 24rem;
+    min-width: 24rem;
+    height: 24rem;
+    background: var(--themeColor2_2);
+    border: 1px solid var(--themeColor2);
+    font-size: 12px;
+    text-align: center;
+    color: #fff;
+    line-height: 24rem;
+    border-radius: 50%;
+    margin-right: 10rem;
+}
+
+.poi-view-info {
+    font-size: 14px;
+    font-family: Verdana, Verdana-Regular;
+    font-weight: 400;
+    text-align: left;
+    color: #ffffff;
+    margin-left: 5rem;
+    margin-right: 10rem;
+}
+
+.poi_sanjiao {
+    position: absolute;
+    bottom: -12rem;
+    width: 0rem;
+    height: 0;
+    border: 6rem solid;
+    border-color: rgba(255, 255, 255, 0.2) transparent transparent;
+    left: calc((100% - 12rem) / 2);
+
+}
+
+.poiUnSelected .poi-view {
+    background: unset;
+    backdrop-filter: unset;
+}
+
+.poiUnSelected .poi-view-text {
+    opacity: 0;
+}
+
+.trafficPoint-view {
+    width: 24rem;
+    height: 24rem;
+    background: rgba(255, 255, 255, 0.00);
+    border: 1px solid var(--themeColor2);
+    border-radius: 50%;
+    font-size: 12px;
+    font-family: Verdana, Verdana-Regular;
+    font-weight: 400;
+    color: var(--themeColor2);
+    text-align: center;
+    line-height: 24rem;
+}
+
+
+/* 预览视图里面的拖拽样式 */
+
+.custom-content-marker {
+    position: relative;
+    width: 206px;
+    height: 206px;
+    /*border-radius: 50%;*/
+    /*border: var(--themeColor3) solid 1px;*/
+    /*background: var(--themeColor3_2);*/
+    box-sizing: border-box;
+}
+
+.custom-content-img {
+    width: 32px;
+    height: 32px;
+}
+
+.project-view {
+    position: absolute;
+    right: 0rem;
+    top: 0rem;
+    width: 690rem;
+    height: calc(100% - 50rem);
+    padding: 20rem 20rem 20rem 0;
+    transition: 0.3s;
+    transform: translateX(0rem);
+    z-index: 11 !important;
+}
+
+.project-view-content {
+    min-height: 240rem;
+    position: relative;
+    width: 100%;
+    height: calc(100% - 100rem);
+    border-radius: 10rem;
+    padding: 20rem;
+    backdrop-filter: blur(10.36rem);
+    color: azure;
+    margin-top: 10rem;
+}
+
+.project-view-content-scroll {
+    overflow: auto;
+}
+
+.show-flex1 {
+    display: flex;
+}
+
+.align-center {
+    align-items: center;
+}
+
+.column {
+    flex-direction: column;
+}
+
+.content-center {
+    justify-content: center;
+}
+
+.content-between {
+    justify-content: space-between;
+}
+
+.content-around {
+    justify-content: space-around;
+}
+
+.content-start {
+    justify-content: flex-start;
+}
+.content-end {
+    justify-content: flex-end;
+}
+
+.cursor-pointer {
+    cursor: pointer;
+}
+
+.disabled {
+    cursor: not-allowed;
+    opacity: 0.5;
+}
+
+.el-select-dropdown {
+    border-radius: 10px;
+    backdrop-filter: blur(30px);
+    background-color: rgba(149, 149, 149, 0.9);
+    border: none;
+    /*color: #fff;*/
+}
+
+.el-select-dropdown__item {
+    color: #fff;
+}
+
+.el-select-dropdown__item.hover,
+.el-select-dropdown__item:hover {
+    background-color: rgba(255, 255, 255, 0.1);
+}
+
+.el-select-dropdown__item.selected {
+    color: var(--themeColor11);
+    font-weight: 700;
+}
+
+.el-picker-panel {
+    border-radius: 10px;
+    backdrop-filter: blur(30px);
+    background-color: rgba(149, 149, 149, 0.5);
+    border: none;
+    color: #fff;
+}
+
+.time-select-item {
+    color: #fff;
+    text-align: center;
+}
+
+.time-select-item:hover {
+    background-color: rgba(255, 255, 255, 0.1) !important;
+}
+
+.time-select-item.selected {
+    color: var(--themeColor1) !important;
+    font-weight: 700;
+}
+.amap-ui-pointsimplifier-container .overlay-title{
+    width: max-content;
+    background-color: rgba(255, 255, 255, 0.2) !important;
+    border-radius: 5rem !important;
+    backdrop-filter: blur(30rem);
+    border:none !important;
+    font-size: 14px !important;
+    font-family: Verdana, Verdana-Regular;
+    font-weight: 400;
+    text-align: left;
+    color: #ffffff !important;
+    padding: 10rem !important;
+ }
+.amap-ui-pointsimplifier-container .overlay-title.top:after{
+    border-top-color:rgba(255, 255, 255, 0) !important;
+
+
+}
+.amap-ui-pointsimplifier-container .overlay-title.top:before{
+    border-top-color:rgba(255, 255, 255, 0.2) !important;
+
+}
+.amap-ui-pointsimplifier-container .overlay-title.top {
+    transform: translate(-50%,-115%) !important;
+}
+
+.popper-class-11{
+    /*background-color: rgb(121, 121, 121);*/
+    background-color:rgba(255,255,255,0.2);
+    border: none;
+    color:rgba(255,255,255,0.9);
+    backdrop-filter: blur(12px);
+    min-width: auto;
+}
+
+.popper-class-12{
+    /*background-color: rgb(121, 121, 121);*/
+    background-color:rgba(255,255,255,0.4);
+    border: none;
+    color:rgba(255,255,255,0.8);
+    backdrop-filter: blur(30px);
+
+}
+
+.popper-class-12.el-popper .popper__arrow,.popper-class-11.el-popper .popper__arrow {
+    display: block !important;
+    border-top-color: rgba(255,255,255,0.41)
+}
+
+.popper-class-12 .popper__arrow::after {
+    bottom: 1px;
+    margin-left: -6px;
+    border-top-color: rgba(87, 87, 87, 0.41) !important;
+    border-bottom-width: 0;
+}
+
+.popper-class-11 .popper__arrow::after {
+    bottom: 1px;
+    margin-left: -6px;
+    border-top-color: rgba(87, 87, 87, 0.41) !important;
+    border-bottom-width: 0;
+}
+
+.popper-class-12 .el-input__inner,.popper-class-12 .el-input__inner,
+.popper-class-11 .el-input__inner,.popper-class-11 .el-input__inner{
+    background-color: transparent;
+    border: 1px solid rgba(255,255,255,0.3);
+    color: rgba(255,255,255,0.8);
+    height: 32px;
+    line-height: 32px;
+    padding-left: 20px;
+    padding-right: 35px;
+}
+
+.popper-class-11 .el-input__prefix,.popper-class-11 .el-input__suffix{
+    top: 9px;
+}
+
+.theme1 .el-radio__input.is-checked .el-radio__inner {
+    border-color: var(--themeColor11);
+    background: transparent;
+}
+.theme1 .el-radio__inner::after {
+    width: 8px;
+    height: 8px;
+    background-color: var(--themeColor11);
+}
+.theme1 .el-radio__inner:hover {
+    border-color: var(--themeColor11);
+}
+.theme1 .el-radio__inner {
+    border: 1px solid #cbc0c0;
+    border-radius: 100%;
+    width: 14px;
+    height: 14px;
+    background-color: transparent;
+    cursor: pointer;
+    box-sizing: border-box;
+}
+.theme1 .el-radio__input.is-checked+.el-radio__label {
+    color: rgba(255,255,255,0.7);
+}
+.theme1 .el-radio{
+    font-family: "Verdana";
+    font-weight: 400;
+    font-size: 14px;
+    text-align: left;
+    color: rgba(255,255,255,0.7);
+}
+.el-input__inner:focus.el-focus{
+    border-color: var(--themeColor11);
+}
+.popper-class-12 .danwei{
+    color: rgba(255,255,255,0.8);
+    height: 32px;
+    line-height: 32px;
+}
+
+.popper-class-12 .el-slider__runway{
+    height: 4px;
+    background-color: rgba(255,255,255,0.4);
+}
+
+.popper-class-12 .el-slider__bar{
+    height: 4px;
+    background-color: rgb(251, 231, 166);
+}
+
+.popper-class-12 .el-slider__button {
+    width: 12px;
+    height: 12px;
+    border: none;
+}
+
+.align-start{
+    align-items: flex-start;
+}
+
+.align-end{
+    align-items: flex-end;
+}
+
+
+.el-date-table td.end-date span, .el-date-table td.start-date span {
+    background-color: var(--themeColor11) !important;
+    color: #6E6F72;
+}
+
+.el-date-table td.in-range div, .el-date-table td.in-range div:hover, .el-date-table.is-week-mode .el-date-table__row.current div, .el-date-table.is-week-mode .el-date-table__row:hover div {
+    background-color: rgba(242, 246, 252, 0.2);
+}
+
+.el-date-table td.today span {
+    color: var(--themeColor11);
+}
+
+.el-date-table td:hover {
+    color: var(--themeColor11);
+}
+
+.el-date-table td.available:hover {
+    color:  var(--themeColor11);
+}
+
+.el-picker-panel__icon-btn{
+    color: var(--themeColor9);
+}
+
+.el-date-range-picker__content.is-left {
+    border-right: 1px solid var(--themeColor9_1);
+}
+
+.el-date-table th {
+    border-bottom: 1px solid var(--themeColor9_1);
+}
+.pp-planstatus{
+    margin-left: -15px;
+
+}
+.pp-planstatus .el-select-dropdown__item{
+   font-size: 13px;
+    padding: 0 15px;
+}

+ 234 - 0
src/assets/common.scss

@@ -0,0 +1,234 @@
+.loadingShadow{
+    position: fixed;
+    z-index: 999999999999;
+    left: 0;
+    top: 0;
+    width: 100vw;
+    height: 100vh;
+}
+
+.loadData{
+    min-width:110px;
+    height:110px;
+    position: absolute;
+    left: 50%;
+    top:50%;
+    transform: translate(-50%,-50%);
+    background: rgba(0,0,0,0.6);
+    border-radius: 10px;
+    z-index: 1000;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content:center;
+    img{
+        width:90px;
+		margin-top: 10px;
+    }
+
+    .loadingMsg{
+        color: rgba(255, 255, 255, 0.83);
+        margin: 10px;
+		margin-top: 0px;
+    }
+}
+.account-view{
+	width: 500rem;
+	// height: 362rem;
+	padding:30rem 40rem;
+	box-sizing:border-box;
+	background-color: rgba(255, 255, 255, 0.9);
+	border-radius: 20rem;
+	// backdrop-filter: blur(30px);
+	.title-icon{
+		width:18rem;
+		margin-right:10rem;
+	}
+	.close{
+		.close-img{
+			font-size: 16rem;
+			font-weight: bold;
+			color:#000;
+			cursor: pointer;
+		}
+	}
+	.content{
+		width: 100%;
+		color: #0b0b0b;
+		font-size: 14rem;
+		.content-main-view{
+			height: 250rem;
+			border-radius: 6rem;
+			background: #fff;
+			box-sizing:border-box;
+			padding: 18rem;
+			overflow: auto;
+			.selcect-view{
+				position: relative;
+				width: 16rem;
+				height: 16rem;
+				border-radius: 100%;
+				background: transparent;
+				border: 1rem solid #ef863f;
+				box-sizing:border-box;
+			}
+			.selcect-view::after{
+				content: '';
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%,-50%);
+				width: 10rem;
+				height: 10rem;
+				border-radius: 100%;
+				background: #ef863f;
+				box-sizing:border-box;
+			}
+			.unselcect-view{
+				width: 16rem;
+				height: 16rem;
+				border-radius: 8rem;
+				background: rgba(249, 249, 249, 0.2);
+				border: 1rem solid rgba(0, 0, 0, 0.2);
+			}
+			.gougou-icon{
+				color: #EF863F;
+			}
+		}
+	}
+	.auth-btn-view{
+		.auth-btn{
+			width: 120rem;
+			height: 40rem;
+			border-radius: 10rem;
+			cursor: pointer;
+		}
+		.style1{
+			font-family: "Verdana Bold";
+			font-weight: 700;
+			font-size: 14rem;
+			color: #151515;
+			background: #d5d5d5;
+		}
+		.style2{
+			font-family: "Verdana Bold";
+			font-weight: 700;
+			font-size: 14rem;
+			color: #fff;
+			background: #ef863f;
+			box-shadow: 0 12px 24px rgba(239, 134, 63, 0.2);
+		}
+	}
+}
+.overflow{
+    overflow: hidden;
+    text-overflow:ellipsis;
+    white-space: nowrap;
+}
+.ellipsis{
+    text-overflow: ellipsis;
+}
+// @media screen and (min-width:768px) {
+//     body,html,#app{
+//         min-width: 1336px;
+//         max-width: 1336px;
+//         background: #f4f4f4;
+//         color: #737373;
+//         height: 100%;
+//     };
+// }
+
+body,html{
+    height:100%;
+    width:100%;
+    margin: 0 auto;
+    padding: 0;
+    position: relative;
+    background-color: #f4f4f4;
+    // font-size: 13px;
+}
+#app{
+    width:100%;
+    margin: 0 auto;
+    padding: 0;
+    height:100%;
+    left:0;
+    top:0;
+    -webkit-overflow-scrolling: touch;
+    position:absolute;
+    font-family: Verdana, Verdana-Bold, "Hiragino Sans GB", "Microsoft Yahei UI",
+    "Microsoft Yahei", 微软雅黑, "Segoe UI", Tahoma, 宋体宋体, SimSun,
+    sans-serif;
+}
+
+ul, li, ol, dl, dd,a{
+	list-style: none;
+	padding: 0;
+	margin:0;
+}
+:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
+	color:#B1C1C8;
+}
+
+::-moz-placeholder { /* Mozilla Firefox 19+ */
+	color:#B1C1C8;
+}
+
+input:-ms-input-placeholder{
+	color:#B1C1C8;
+}
+
+input::-webkit-input-placeholder{
+	color:#B1C1C8;
+}
+
+.show-flex5{
+    display: flex;
+}
+.align-center{
+    align-items: center;
+}
+.column{
+    flex-direction: column;
+}
+.content-center{
+    justify-content: center;
+}
+.content-between{
+    justify-content: space-between;
+}
+.content-around{
+    justify-content: space-around;
+}
+.cursor-pointer{
+    cursor: pointer;
+}
+.flex-end{
+    justify-content: flex-end;
+}
+/********************  element 分页样式修改  *****************/
+#app{
+    ::v-deep .el-pagination .btn-next,::v-deep .el-pagination .btn-prev {
+        background: center center no-repeat #0000;
+        background-size: 16px;
+        cursor: pointer;
+        margin: 0;
+        color: #c7c8c9;
+        border: 1px solid #fff3;
+        border-radius: 4px;
+    }
+
+    ::v-deep .el-pagination.is-background .el-pager li {
+        background-color: #f4f4f500;
+        color: #8d8d8d;
+    }
+
+    ::v-deep .el-pagination.is-background .el-pager li:not(.disabled).active {
+        background-color: #fff2;
+        border-radius: 4px;
+        color: #FFF;
+    }
+
+}
+
+/*****************************************************************/

+ 311 - 0
src/assets/css/common.css

@@ -0,0 +1,311 @@
+body{
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+}
+.rows{
+    display: flex;
+    flex-direction:row;
+    align-items:center;
+}
+.rows-between{
+    justify-content:space-between;
+}
+.columns{
+    display: flex;
+    flex-direction:column;
+    align-items:center;
+    justify-content:space-between;
+}
+.eslipe {
+	overflow: hidden;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+}
+.flex-start{
+	align-items:flex-start;
+}
+.justify-center{
+	justify-content: center;
+}
+.grid-view{
+	display: grid;
+	grid-template-columns: repeat(2, 1fr);;
+	/* grid-row-gap: 20rem; */
+	grid-gap:20rem 80rem;
+}
+::-webkit-scrollbar{
+	width: 0;
+	height: 0;
+	color: transparent;
+}
+/* 项目提示信息 */
+.infoWindowHtml{
+    z-index: 1000!important;
+    cursor: pointer;
+}
+.project-content{
+    position: relative;
+	/* float: left; */
+	/* width: auto; */
+    width: max-content;
+	padding:15rem 20rem;
+	box-sizing: border-box;
+	/* background: linear-gradient(90deg,#000000 1%, rgba(0,0,0,0.00));
+	backdrop-filter: blur(30.24rem); */
+    padding-bottom: 4rem;
+    cursor: pointer;
+}
+.filter-view{
+	position: absolute;
+	width: 100%;
+	height: 100%;;
+	left: 0rem;
+	top: 0rem;
+	filter: blur(30rem);
+	background: linear-gradient(90deg,#000000 1%, rgba(0,0,0,0.00));
+	z-index: -1;
+}
+.project-head{
+	width: 40rem;
+	height: 40rem;
+    line-height: 40rem;
+	background: rgba(0,0,0,0.00);
+	border: 1rem solid rgba(255,255,255,0.33);
+	border-radius: 50%;
+	margin-right: 8rem;
+    font-size: 18px;
+	font-family: Verdana, Verdana-Bold;
+	font-weight: 700;
+	text-align: center;
+	color: #ffffff;
+    object-fit: cover;
+}
+.project-name{
+	height: 28rem;
+	line-height: 28rem;
+	font-size: 20px;
+	font-family: Verdana, Verdana-Bold;
+	font-weight: 700;
+	text-align: left;
+	color: #ffffff;
+}
+.project-address{
+	height: 17rem;
+	line-height: 17rem;
+	opacity: 0.5;
+	font-size: 12px;
+	font-family: Verdana, Verdana-Bold;
+	font-weight: 400;
+	text-align: left;
+	color: #ffffff;
+}
+.project-tips{
+	width: 40rem;
+	height: 22rem;
+	background: rgba(255,255,255,0.2);
+	border-radius: 4rem;
+	font-size: 14px;
+	font-family: FontName, FontName-Regular;
+	font-weight: 400;
+	text-align: center;
+	color: #ffffff;
+	line-height: 22rem;
+	font-style: italic;
+	margin-left: 10rem;
+}
+.project-area{
+	margin-top: 6rem;
+	height: 20rem;
+	line-height: 20rem;
+	font-size: 14px;
+	font-family: Verdana, Verdana-Bold;
+	font-weight: 700;
+	text-align: left;
+	color: #ffffff;
+    overflow: hidden;
+}
+.project-footer{
+	position: relative;
+	width: 100%;
+	height: 10rem;
+	margin-top: 10rem;
+    overflow: hidden;
+}
+.project-footer-top{
+	width: 100%;
+	height: 4rem;
+	background: linear-gradient(90deg,var(--themeColor4) 1%, transparent);
+}
+.project-footer-left{
+	position: absolute;
+	top: 0rem;
+	border-width:10rem;
+	border-top-color: transparent;
+	border-right-color: transparent;
+	border-bottom-color: transparent;
+	border-left-color: var(--themeColor4);
+	border-style:solid;
+	border-left-width: 5rem;
+	border-top-width: 0rem;
+}
+.polyon-content{
+	float: left;
+	width: auto;
+	font-size: 14px;
+    white-space: nowrap;
+	font-family: Verdana, Verdana-Bold;
+	font-weight: 700;
+	text-align: center;
+	color: var(--themeColor1);
+	text-shadow: 0rem 0rem #000000;
+}
+.infoWindowUnSelected .project-head{
+	display: none;
+}
+.infoWindowUnSelected .project-name{
+    height: 20rem;
+	line-height: 20rem;
+    font-size: 14px;
+}
+.infoWindowSelected .project-tips,.infoWindowUnSelected .project-tips{
+	display: none;
+}
+.infoWindowHtml.infoWindowSelected{
+    z-index: 1001!important;
+}
+.infoWindowUnSelected .project-address{
+	display: none;
+}
+.infoWindowUnSelected .project-area{
+    height: 17rem;
+	line-height: 17rem;
+    opacity: 0.6;
+    font-size: 12px;
+	margin-top: 0rem;
+}
+.infoWindowUnSelected .project-footer{
+	margin-top: 8rem;
+}
+.competitionUnSelected .project-name{
+    height: 20rem;
+	line-height: 20rem;
+    font-size: 14px;
+}
+.competitionUnSelected .project-area{
+    display: none;
+}
+/* 项目竞品状态 */
+.competitionProject .project-name{
+    height: 20rem;
+	line-height: 20rem;
+    font-size: 14px;
+}
+.competitionProject .project-head,.competitionProject .project-area,.competitionProject .project-address{
+	display: none;
+}
+/* 圆柱样式 */
+.cricleColumn-view{
+	position: relative;
+	width: 90rem;
+	height: 152rem;
+    cursor: pointer;
+}
+.cricleColumn-img{
+	width: 90rem;
+	height: 152rem;
+}
+.cricleColumn-text{
+	position: absolute;
+	bottom: 0rem;
+	left: 0rem;
+	width: 100%;
+	height: 37rem;
+	font-size: 14px;
+	font-family: DIN Alternate, DIN Alternate-Bold;
+	font-weight: 700;
+	text-align: center;
+	color: #ffdf80;
+	line-height: 14rem;
+}
+.cricleColumn1-view{
+	position: relative;
+	width: 82rem;
+	height: 152rem;
+    cursor: pointer;
+}
+.cricleColumn1-img{
+	width: 82rem;
+	height: 152rem;
+}
+.cricleColumn1-text{
+	position: absolute;
+	bottom: 14rem;
+	left: 0rem;
+	width: 100%;
+	font-size: 14px;
+	font-family: DIN Alternate, DIN Alternate-Bold;
+	font-weight: 700;
+	text-align: center;
+	color: #fff;
+	line-height: 20rem;
+}
+
+.poi-view{
+	position: relative;
+	width: max-content;
+	height: 30rem;
+	background: rgba(255,255,255,0.2);
+	border-radius: 15rem;
+	backdrop-filter: blur(30rem);
+    cursor: pointer;
+}
+.poi-view-radius{
+	width: 24rem;
+	height: 24rem;
+	line-height: 22rem;
+	background: rgba(118,188,255,0.50);
+	border: 1px solid #76bcff;
+	border-radius: 50%;
+	font-size: 12px;
+	font-family: Verdana, Verdana-Regular;
+	font-weight: 400;
+	text-align: center;
+	color: #ffffff;
+	margin-left: 4rem;
+}
+.poi-view-text{
+	font-size: 14px;
+	font-family: Verdana, Verdana-Regular;
+	font-weight: 400;
+	text-align: left;
+	color: #ffffff;
+	margin-left: 5rem;
+	margin-right: 10rem;
+}
+.poiUnSelected .poi-view{
+	background:unset;
+	backdrop-filter:unset;
+}
+.poiUnSelected .poi-view-text{
+	opacity: 0;
+}
+.trafficPoint-view{
+    width: 24rem;
+    height: 24rem;
+    background: rgba(255,255,255,0.00);
+    border: 1px solid var(--themeColor2);
+    border-radius: 50%;
+    font-size: 12px;
+    font-family: Verdana, Verdana-Regular;
+    font-weight: 400;
+    color: var(--themeColor2);
+    text-align: center;
+    line-height: 24rem;
+}
+
+.auto-height{
+	height: auto;
+}
+

+ 135 - 0
src/assets/css/style.css

@@ -0,0 +1,135 @@
+div{
+	box-sizing: border-box;
+}
+.project-view{
+	position: absolute;
+	right: 0rem;
+	top: 0rem;
+	width: 690rem;
+	height: calc(100% - 50rem);
+	padding: 20rem 20rem 20rem 0;
+    transition: 0.3s;
+    transform: translateX(0rem);
+    z-index: 11 !important;
+}
+.project-view-content{
+    min-height: 240rem;
+	position: relative;
+	width: 100%;
+    height: calc(100% - 100rem);
+	border-radius: 10rem;
+	padding: 20rem;
+	backdrop-filter: blur(10.36rem);
+	color: azure;
+    margin-top: 20rem;
+}
+.project-view-content-scroll{
+    overflow:auto;
+}
+.competition-top{
+	color: #cccccc;
+}
+.competition-top-btnlist{
+	border-radius: 8rem;
+	border: #7FFFD4 1rem solid;
+	height: 30rem;
+	line-height: 30rem;
+	overflow: hidden;
+}
+.btn-item{
+	font-size: 13px;
+	padding: 0rem 10rem;
+	background-color: transparent;
+}
+.btn-item.active{
+	background-color: rgb(188,223,139);
+	color: white;
+}
+.competition-info{
+	margin-top: 60rem;
+}
+.info-item-text{
+	font-size: 24px;
+	color: rgb(188,223,139);
+}
+.chart-view{
+	position: relative;
+	margin-top: 20rem;
+	width: 100%;
+	height: 300rem;
+}
+.chart{
+	/* width: 100%; */
+	/* height: 100%; */
+    width: 570rem;
+    height: 300rem;
+}
+.change-echarts{
+	position: absolute;
+	right: 0rem;
+	top: 0rem;
+	height: 20rem;
+	line-height: 20rem;
+}
+.echarts-item{
+	position: relative;
+	color: #F0FFFF;
+	font-size: 12px;
+	margin-right: 20rem;
+	cursor: pointer;
+}
+
+.foot-view{
+    position: absolute;
+	bottom: 0rem;
+	width: 1400rem;
+	height: 40rem;
+    margin: 10rem 20rem;
+}
+
+.view-bg{
+	border-radius: 20rem;
+	padding: 20rem;;
+	box-shadow: 0rem 4rem 16rem 0rem rgba(255,177,136,0.30);
+	backdrop-filter: blur(10.36rem);
+	color: azure;
+}
+
+.point-circle{
+    width: 240rem;
+    height: 240rem;
+    border-radius: 50%;
+    background-color: #ffaa5199;
+    border: 1rem solid #ff7151;
+    align-items: center;
+    justify-content: center;
+}
+
+.point-img{
+    width:60rem;
+    height: 60rem;
+}
+.menceng{
+    position: absolute;
+    top:0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+}
+
+.pointer{
+    cursor:pointer
+}
+.custom-content-marker{
+	position: relative;
+	width: 206px;
+	height: 206px;
+	/*border-radius: 50%;*/
+	/*border: var(--themeColor3) solid 1px;*/
+	/*background: var(--themeColor3_2);*/
+	box-sizing: border-box;
+}
+.custom-content-img{
+	width: 32px;
+	height: 32px;
+}

File diff suppressed because it is too large
+ 1035 - 0
src/assets/font/iconfont.css


BIN
src/assets/font/iconfont.ttf


BIN
src/assets/font/iconfont.woff


BIN
src/assets/font/iconfont.woff2


BIN
src/assets/img/C2B@2x.png


BIN
src/assets/img/bg_balance.png


BIN
src/assets/img/bg_cost.png


BIN
src/assets/img/bg_money.png


BIN
src/assets/img/brand_1.png


BIN
src/assets/img/brand_2.png


BIN
src/assets/img/brand_3.png


BIN
src/assets/img/brand_4.png


BIN
src/assets/img/brand_5.png


BIN
src/assets/img/icon_clear_text.png


BIN
src/assets/img/icon_eye_project.png


BIN
src/assets/img/icon_money.png


BIN
src/assets/img/keyan-graph.png


BIN
src/assets/img/keyan-line.png


BIN
src/assets/img/keyan1.png


BIN
src/assets/img/other.png


BIN
src/assets/img/phone.png


BIN
src/assets/img/point.png


BIN
src/assets/img/pre-order1.png


BIN
src/assets/img/pre-order2.png


BIN
src/assets/img/组 23947.png


BIN
src/assets/logo.png


+ 26 - 0
src/components/leftOperateComp/leftOperateComp.css

@@ -0,0 +1,26 @@
+.leftOperateArea{
+    position: absolute;
+    top: 60px;
+    left: 0vw;
+    height: calc(100vh - 60px);
+	/* width: 500rem; */
+	width: 150rem;
+    /* margin: 0px 1vw; */
+    padding: 10px;
+    background: rgba(255,255,255,0.2);
+    border-radius: 4px;
+    backdrop-filter: blur(30px);
+	z-index: 20;
+	overflow: auto;
+}
+.area-contain{
+	margin-top:10px;
+}
+.item-operate{
+	cursor: pointer;
+	margin-right: 1rem;
+}
+.item-operate:last-child{
+	margin-right: 0rem;
+}
+

+ 11 - 0
src/components/leftOperateComp/leftOperateComp.html

@@ -0,0 +1,11 @@
+<div class="leftOperateArea" v-show="showLeftArea">
+	<!-- 空间操作台 -->
+	<div class="areaOperate">
+		<el-tag>空间操作</el-tag>
+		<div class="area-contain rows">
+			<div class="item-operate" v-for="(item,index) in dataList" :key="item.id" @click="operateHandle(item)">
+				<el-button type="primary" size="mini" plain>{{item.text}}</el-button>
+			</div>
+		</div>
+	</div>
+</div>

+ 86 - 0
src/components/leftOperateComp/leftOperateComp.vue

@@ -0,0 +1,86 @@
+<template src="./leftOperateComp.html">
+
+</template>
+<script>
+	// import AMapLoader from '@amap/amap-jsapi-loader';
+	export default {
+		name: 'leftOperateComp',
+		data() {
+			return {
+				status: 'add',
+				showLeftArea: true,
+				
+				activeId:'',	//当前活动中的操作id
+				dataList: [
+					{
+						id:1,
+						text:'添加空间'
+					},
+					{
+						id:2,
+						text:'移动空间'
+					}
+				],
+			}
+		},
+		computed: {},
+		mounted() {
+			
+		},
+		methods: {
+			init() {
+				
+			},
+
+			/**
+			 * 关闭页面
+			 */
+			closePage() {
+				this.addCompeteVisible = false;
+				window.$bus.$emit('addProjectVisible', true, false); //显示新建地块的视图,但不初始化数据
+			},
+			//操作
+			operateHandle(item){
+				if(!item || !item.id){
+					return false;
+				}
+				this.activeId = item.id;
+				// this.$emit("toImportCuemanage", item, this.landIdList, screenDateIn)
+				this.$emit('operateHandle',item)
+			},
+			/**
+			 * 预览项目
+			 */
+			async previewDK() {
+				// this.isActive = 2;
+				console.log("---previewDK1---")
+
+				let that = this;
+				let result = this.addCompete();
+				if (result) { //校验通过
+					console.log("---previewDK2---", that.form)
+					let data = Object.assign({}, that.form, {
+						sv: this.sv,
+						isJinPin: true
+					});
+					if (!this.fullscreenLoading) {
+						this.addProjectVisible = false; //隐藏新增图层
+						window.$bus.$emit('openPreviewComp', data); // 通知预览-且开始精调经纬度过程
+						window.$bus.$emit('closeOrOpenFootComponetView', false); //隐藏页面页脚
+					} else {
+						await this.getAddress();
+						this.addProjectVisible = false; //隐藏新增图层
+						window.$bus.$emit('openPreviewComp', data); // 通知预览-且开始精调经纬度过程
+						window.$bus.$emit('closeOrOpenFootComponetView', false); //隐藏页面页脚
+					}
+				} else {
+					return false;
+				}
+			},
+		}
+	}
+</script>
+<style lang="css" scoped>
+	@import "./leftOperateComp.css";
+	@import "@/assets/common.css";
+</style>

+ 41 - 0
src/components/mapComponent/mapComponent.css

@@ -0,0 +1,41 @@
+#mapDiv{
+    width: 100%;
+    height: 100vh;
+    background: #181C28;
+}
+.map {
+  position: relative;  /* 作为子元素的相对定位元素 */
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+#labels {
+  position: absolute;  /* 把Label定位在容器内 */
+  left: 0;             /* 默认定位在左上角 */
+  top: 0;
+  color: white;
+}
+#labels>div {
+  position: absolute;  /* 让我们的容器决定尺寸 */
+  left: 0;             /* 默认定位在左上角 */
+  top: 0;
+  cursor: pointer;     /* 当悬浮时,变为一个小手 */
+  font-size:12px;
+  user-select: none;   /* 不允许文字被选中 */
+  white-space: nowrap;
+  text-shadow:         
+    -1px -1px 0 #000,
+    0   -1px 0 #000,
+    1px -1px 0 #000,
+    1px  0   0 #000,
+    1px  1px 0 #000,
+    0    1px 0 #000,
+    -1px  1px 0 #000,
+    -1px  0   0 #000;
+}
+#labels>div:hover {
+  color: red;
+}
+canvas:focus {
+  outline:none;
+}

+ 9 - 0
src/components/mapComponent/mapComponent.html

@@ -0,0 +1,9 @@
+<div class="map" style="position: absolute;width: 100%;height: 100vh;z-index: 1;">
+    <div id="mapDiv" ref="webgl"></div>
+	<canvas id="glcanvas" width="100vw" height="100vh" ref="glcanvas">
+		你的浏览器似乎不支持或者禁用了 HTML5 <code>&lt;canvas&gt;</code> 元素。
+	</canvas>
+	<div id="labels"></div>
+	<!-- 左侧操作区域 -->
+	<left-operate-comp @operateHandle="operateHandle"></left-operate-comp>
+</div>

+ 690 - 0
src/components/mapComponent/mapComponent.vue

@@ -0,0 +1,690 @@
+<template src="./mapComponent.html"></template>
+<script>
+	// import AMapLoader from "@amap/amap-jsapi-loader";
+	import * as THREE from 'three';
+	import Stats from 'three/addons/libs/stats.module.js';
+	import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
+	import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
+	import { DragControls } from 'three/addons/controls/DragControls.js';
+	import leftOperateComp from "@/components/leftOperateComp/leftOperateComp";
+	export default {
+		name: "mapComponent",
+		props: {},
+		components:{
+			leftOperateComp
+		},
+		data() {
+			return {
+				area: null,
+				selectModuleItem: null,
+				showMap: false,
+				is3D: true,
+				isOpen: false, //是否打开项目展示
+				scene: null,
+				camera: null,
+				canvas: null,
+				renderer: null,
+				stats:null,
+				starWorldPosition:null,
+				drawAreaObject:null,
+				XLine:null,
+				YLine:null,
+				areaList:[],//用户绘制的空间存放的数据对象
+				pageStatus:1,	//当前页面状态 1 显示态 2 编辑态
+				cursorObj:null,	//鼠标当前划过的对象
+				cursorMeshColor:null,	//记录下划过对象的元素颜色
+				moveObj:null,	//移动对象
+				moveStarPosition:null,	//移动对象的初始位置-用于计算移动距离
+				adsorbDis:0.3,			//移动对象时的吸附距离
+			};
+		},
+		created() {},
+		watch: {
+			// areaData: {
+			// 	handler(newVal) {
+			// 		if(newVal){
+			// 			this.loadMap();
+			// 		}
+			// 	},
+			// 	immediate: true
+			// }
+		},
+		mounted() {
+			var isDrawing = false;
+			// this.loadMap();
+			// window.$bus.$off('loginSuccess',this.loadMap);
+			// window.$bus.$on('loginSuccess', this.loadMap);
+			// window.$bus.$off('resetMap');
+			// window.$bus.$on('resetMap', (data) => {
+			// 	this.isOpen = data;
+			// 	this.resetMapCenter();
+			// })
+			var that = this;
+			const container = this.$refs.webgl;
+			this.stats = new Stats();
+			container.appendChild(this.stats.dom);
+			
+			this.scene = new THREE.Scene();//场景对象
+			this.scene.background = new THREE.Color("#fff");//设置场景的背景色
+			// this.scene.environment = new THREE.Color("#ccc");
+			//创建透视相机
+			this.camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 10000);
+			this.camera.position.set(0, 0, 15);
+			this.scene.add(this.camera);//把相机添加到场景里面
+			// const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
+			// this.scene.add( ambientLight );
+			const canvas3d = this.$refs.glcanvas;
+			//创建渲染器
+			this.renderer = new THREE.WebGLRenderer({
+				canvas:canvas3d,
+				antialias: false,
+				preserveDrawingBuffer: true,
+			});
+			this.renderer.setPixelRatio(window.devicePixelRatio);
+			this.renderer.setSize(window.innerWidth, window.innerHeight);
+			container.appendChild(this.renderer.domElement);
+
+			//极坐标辅助
+			// const axesHelper = new THREE.AxesHelper( 50 );
+			// this.scene.add( axesHelper );
+			//网格辅助
+			const gridHelper = new THREE.GridHelper(50, 50, 0x808080, 0x808080);
+			gridHelper.position.y = 0;
+			gridHelper.position.x = 0;
+			gridHelper.rotation.x = Math.PI / 2;//翻转
+			gridHelper.name = "辅助网格"
+			this.scene.add(gridHelper);
+			
+			// 4.创建一个长、宽、高均为5个单位的立方体
+			// const geometry = new THREE.BoxGeometry(5, 5, 5);
+			// 创建一个长、宽、的矩形;three.js 默认单位是米
+			const geometry = new THREE.PlaneGeometry(50, 50);
+
+			// 5.创建Lambert网格材质
+			const materialBasic = new THREE.MeshBasicMaterial({
+				color: 'transparent', // 绿色
+				transparent: true, // 设置材质为透明
+				opacity: 0.5 // 设置透明度
+			});
+			// 6.创建一个网格模型对象
+			const mesh = new THREE.Mesh(geometry, materialBasic); //网络模型对象Mesh
+			mesh.position.set(0, 0, 0);
+			mesh.name="bgPan";//背景板-用于计算鼠标点击以及滑动时的位置-精确位置
+			// 把网格模型添加到三维场景
+			this.scene.add(mesh);
+			
+			// 设置相机看向物体的方向(默认指向三维坐标系的原点)
+			// this.camera.lookAt(0, 0, 0);
+			// 修改几何体位置
+			// const controls = new OrbitControls( this.camera, this.renderer.domElement );
+			// controls.target.set( 0, 0.5, 0 );
+			// controls.update();
+			// controls.enablePan = false;
+			// controls.enableDamping = true;
+			
+			// function render(){
+			// 	this.renderer.render(this.scene, this.camera);//单次渲染
+			// 	requestAnimationFrame(render)
+			// }
+			const raycaster = new THREE.Raycaster();
+			this.render(); //开启渲染
+			this.renderer.domElement.addEventListener('mousemove', onMouseMove, false);
+			this.renderer.domElement.addEventListener('mouseup', mouseup, false);//释放鼠标
+			this.renderer.domElement.addEventListener('mousedown', mousedown, false);//按下鼠标
+			this.renderer.domElement.addEventListener('contentmenu', contentmenu, false);//右键事件
+			const labelContainerElem = document.querySelector('#labels');
+			window.onresize = ()=> {
+				this.camera.aspect = window.innerWidth / window.innerHeight;
+				this.camera.updateProjectionMatrix();
+				this.renderer.setSize( window.innerWidth, window.innerHeight );
+			};
+			//把鼠标的点击坐标-屏幕坐标转换为three.js体系里面的世界坐标
+			function getWorldPoint (event) {
+				var mouse = new THREE.Vector2();
+				mouse.x = (event.clientX / window.innerWidth) * (2/window.devicePixelRatio) - 1;
+				mouse.y = -(event.clientY / window.innerHeight) * (2/window.devicePixelRatio) + 1;
+				raycaster.setFromCamera(mouse, that.camera);
+				var intersects = raycaster.intersectObjects(that.scene.children);
+				// var intersects = raycaster.intersectObjects(that.camera);
+				if (intersects.length > 0) {
+					let meshMap = intersects.find(it => {
+						return it.object.name=="bgPan" && it.point
+					});
+					var worldPosition = {};
+					if(meshMap && meshMap.point){
+						worldPosition = meshMap.point;
+					}
+					return worldPosition;
+				}
+			}
+			//获取当前鼠标悬浮到的哪个空间上-也即选取对应的空间
+			function getSelectArea (event) {
+				var mouse = new THREE.Vector2();
+				mouse.x = (event.clientX / window.innerWidth) * (2/window.devicePixelRatio) - 1;
+				mouse.y = -(event.clientY / window.innerHeight) * (2/window.devicePixelRatio) + 1;
+				raycaster.setFromCamera(mouse, that.camera);
+				var intersects = raycaster.intersectObjects(that.areaList);
+				// var intersects = raycaster.intersectObjects(that.camera);
+				if (intersects.length > 0) {
+					let selectArea = intersects[0].object;
+					return selectArea;
+				}
+			}
+			//鼠标右键事件
+			function contentmenu (event) {
+				console.warn("***contentmenu***")
+				that.starWorldPosition = null;//清空初始点击位置
+			}
+			//释放鼠标
+			function mouseup(event) {
+				if(that.pageStatus==1){//页面处在显示态
+					if(that.moveObj){//存在移动对象-也就是用户点击过屏幕,系统拾取了移动对象
+						that.moveObj.material.opacity = 1;
+						that.moveObj = null;//清空移动对象
+					}else{
+						// cursorMove(event);//鼠标划过处理
+					}
+				}else if(that.pageStatus==2){//页面处在编辑态-即绘制状态
+					isDrawing = false;
+					that.starWorldPosition = null;//清空初始点击位置
+					that.areaList.push(that.drawAreaObject);//把用户绘制的空间添加到空间列表中
+					that.drawAreaObject = null;//清空
+					console.warn("***mouseup-that.areaList***",that.areaList)
+				}
+			}
+			//按下鼠标
+			function mousedown(event) {
+				console.warn("***mousedown***")
+				if(!event){
+					return false;
+				}
+				if(that.pageStatus==1){//页面处在显示态
+					if(that.cursorObj){//如果存在滑动对象-则需要拾取它-因为下一步要移动
+						that.moveObj = that.cursorObj;//声明并且赋值移动对象
+						that.moveStarPosition = getWorldPoint(event);//记录下移动对象初始点击的位置
+					}else{//点击时没有滑动对象,则需要把上一次的移动对象清空
+						that.moveObj = null;
+					}
+				}else if(that.pageStatus==2){//页面处在编辑态-即绘制状态
+					isDrawing = true;
+					let posi = getWorldPoint(event);
+					that.starWorldPosition = posi;//记录下点击的位置
+				}
+			}
+			//鼠标移动中
+			function onMouseMove(event) {
+			    // event.preventDefault();
+				if(that.pageStatus==1){//页面处在显示态
+					if(that.moveObj){//存在移动对象-也就是用户点击过屏幕,系统拾取了移动对象
+						moveObj(that.moveObj,event)
+					}else{
+						cursorMove(event);//鼠标划过处理
+					}
+				}else if(that.pageStatus==2){//页面处在编辑态
+					if (!isDrawing) return;
+					let _position = getWorldPoint(event);
+					if(!_position || !_position.x){//没有获取到坐标,可能发生了越界
+						return false;
+					}
+					if(!that.drawAreaObject){//此时需要创建drawAreaObject
+						// // 创建一个长、宽、的矩形;three.js 默认单位是米
+						let width = 1;
+						let height = 1;
+						const geometry = new THREE.PlaneGeometry(width, height);
+						
+						// 5.创建Lambert网格材质
+						const materialBasic = new THREE.MeshBasicMaterial({
+							color: 0x00ff00, // 绿色
+						});
+						// // 6.创建一个网格模型对象
+						const mesh = new THREE.Mesh(geometry, materialBasic); //网络模型对象Mesh
+						mesh.position.set(that.starWorldPosition.x + width/2, that.starWorldPosition.y - height/2, 0);
+						
+						that.drawAreaObject = mesh;
+						that.scene.add(that.drawAreaObject);
+						that.drawAreaObject.starWorldPosition = that.starWorldPosition;
+					}
+					
+					var width = _position.x - that.starWorldPosition.x;
+					var height = -(_position.y - that.starWorldPosition.y);//注意Y方向上的正方向是向上的
+								
+					that.drawAreaObject.scale.set(width, height, 1);
+					that.drawAreaObject.position.set(that.starWorldPosition.x + width / 2, that.starWorldPosition.y - height / 2, 0);
+					drawXLine(_position);	//绘制X轴提示线
+					drawYLine(_position);	//绘制Y轴提示线
+					drawArea(_position)		//绘制面积提示语
+				}
+			}
+			//绘制X轴提示线-2D position 鼠标对应的点
+			function drawXLine (position) {
+				let startPosition = that.starWorldPosition;
+				let endPosition = position;
+				//数据过滤-确保数据是正确的
+				if(!startPosition || !endPosition || !startPosition.x || !endPosition.x){
+					return false;
+				}
+				if(startPosition.x == endPosition.x){//线段的开始点和结束点不能相同
+					return false
+				}
+				let cha = 0.1;//偏移量
+				if(endPosition.y > startPosition.y){
+					cha = -0.1
+				}
+				let XLine = that.drawAreaObject.XLine;
+				if(!XLine){//如果当前绘制的空间没有X轴提示线
+					// 创建线的几何体
+					var geometry = new THREE.BufferGeometry();
+					// 初始线的顶点位置
+					var positions = new Float32Array(6);
+					positions[0] = startPosition.x; // x1
+					positions[1] = startPosition.y + cha; // y1
+					positions[2] = 0; // z1
+					positions[3] = endPosition.x; // x2
+					positions[4] = startPosition.y + cha; // y2
+					positions[5] = 0; // z2
+					// 设置线的属性
+					geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
+					const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
+					const line = new THREE.Line( geometry, material );
+					that.drawAreaObject.XLine = line;//保存X轴提示线
+					that.scene.add(line);
+				}else{
+					XLine.geometry.attributes.position.array[1] = startPosition.y + cha; // y1
+					XLine.geometry.attributes.position.array[3] = endPosition.x;
+					XLine.geometry.attributes.position.array[4] = startPosition.y + cha;
+					XLine.geometry.attributes.position.needsUpdate = true;
+				}
+				//超过1个单位的距离,才显示
+				if( Math.abs(endPosition.x - startPosition.x)/2 > 1 ){
+					if(XLine && XLine.elem){
+						XLine.elem.style.display = 'block';
+					}
+					let content = "";
+					let tempV = new THREE.Vector3();
+					tempV.x = (endPosition.x + startPosition.x)/2;
+					tempV.y = startPosition.y + cha*4;
+					tempV.z = 0;
+					content =  Math.abs(endPosition.x - startPosition.x).toFixed(2) + 'm';
+					makeTips(XLine,tempV,content)
+				}else{
+					if(XLine && XLine.elem){
+						XLine.elem.style.display = 'none';
+					}
+				}
+			}
+			//绘制Y轴提示线-2D position 鼠标对应的点
+			function drawYLine (position) {
+				let startPosition = that.starWorldPosition;
+				let endPosition = position;
+				//数据过滤-确保数据是正确的
+				if(!startPosition || !endPosition || !startPosition.y || !endPosition.y){
+					return false;
+				}
+				if(startPosition.y == endPosition.y){//线段的开始点和结束点不能相同
+					return false
+				}
+				let cha = 0.1;
+				if(endPosition.x > startPosition.x){
+					cha = -0.1
+				}
+				let YLine = that.drawAreaObject.YLine;
+				if(!YLine){//如果当前绘制的空间没有X轴提示线
+					// 创建线的几何体
+					var geometry = new THREE.BufferGeometry();
+					// 初始线的顶点位置
+					var positions = new Float32Array(6);
+					positions[0] = startPosition.x + cha; // x1
+					positions[1] = startPosition.y; // y1
+					positions[2] = 0; // z1
+					positions[3] = endPosition.x + cha; // x2
+					positions[4] = startPosition.y; // y2
+					positions[5] = 0; // z2
+					// 设置线的属性
+					geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
+					const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
+					const line = new THREE.Line( geometry, material );
+			
+					that.drawAreaObject.YLine = line;//保存X轴提示线
+					that.scene.add(line);
+				}else{
+					YLine.geometry.attributes.position.array[0] = startPosition.x + cha; // y1
+					YLine.geometry.attributes.position.array[3] = startPosition.x + cha;
+					YLine.geometry.attributes.position.array[4] = endPosition.y;
+					YLine.geometry.attributes.position.needsUpdate = true;
+				}
+				//超过1个单位的距离,才显示
+				if(Math.abs(endPosition.y - startPosition.y)/2 > 1 ){
+					if(YLine.elem){
+						YLine.elem.style.display = 'block';
+					}
+					let content = "";
+					let tempV = new THREE.Vector3();
+					tempV.x = startPosition.x + cha;
+					tempV.y = (endPosition.y + startPosition.y)/2;
+					tempV.z = 0;
+					content =  Math.abs(endPosition.y - startPosition.y).toFixed(2) + 'm';
+					makeTips(YLine,tempV,content)
+				}else{
+					if(YLine && YLine.elem){
+						YLine.elem.style.display = 'none';
+					}
+				}
+			}
+			//绘制区域面积-2D position 鼠标对应的点
+			function drawArea (position) {
+				let startPosition = that.starWorldPosition;
+				let endPosition = position;
+				let obj = that.drawAreaObject;//当前绘制的空间对象
+				//数据过滤-确保数据是正确的
+				if(!startPosition || !endPosition || !startPosition.y || !endPosition.y
+				|| !startPosition.x || !endPosition.x){
+					return false;
+				}
+				if(startPosition.y == endPosition.y || startPosition.x == endPosition.x){//线段的开始点和结束点不能相同
+					return false
+				}
+				if(Math.abs(endPosition.x - startPosition.x)/2 > 1 ){
+					let content = "";
+					let tempV = new THREE.Vector3();
+					tempV.x = (startPosition.x + endPosition.x)/2;
+					tempV.y = (startPosition.y + endPosition.y)/2;
+					tempV.z = 0;
+					content = (Math.abs(endPosition.y - startPosition.y)*Math.abs(endPosition.x - startPosition.x)).toFixed(2) + '㎡';
+					// console.log('makeTips-area', JSON.parse(JSON.stringify(tempV)),JSON.parse(JSON.stringify(endPosition)),JSON.parse(JSON.stringify(startPosition)),);
+					makeTips(obj,tempV,content)
+				}
+			}
+			//绘制和更新提示线上的距离值-单位米 point 是世界坐标系上的点位
+			function makeTips(line, point, content=null) {
+				if(!line){//如果没有提示线,则不处理
+					return false;
+				}
+				if(!line.elem){//提示线上不存在距离值div,则创建一个
+					let elem = document.createElement('div');
+					line.elem = elem;//向父级对象上添加div对象-方便父级对象找到这个div,从而操作
+					labelContainerElem.appendChild(line.elem);
+				}
+				const tempV = new THREE.Vector3();
+				tempV.x = point.x;
+				tempV.y = point.y;
+				tempV.z = point.z;
+				line.lableX = point.x;//记录下线上提示的位置
+				line.lableY = point.y;
+				// 获取标准化屏幕坐标,x和y都会在-1和1区间
+				// x = -1 表示在最左侧
+				// y = -1 表示在最底部
+				tempV.project(that.camera);
+				// window.innerWidth, window.innerHeight
+				// 将标准屏幕坐标转化为CSS坐标
+				const x = (tempV.x *  .5 + .5) * window.innerWidth;
+				const y = (tempV.y * -.5 + .5) * window.innerHeight;
+				line.elem.textContent = content?content:line.elem.textContent;//提示的文字内容
+				// 将元素移动到此位置
+				line.elem.style.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
+			}
+			//鼠标划过处理
+			function cursorMove (event) {
+				let area = getSelectArea(event);//获取鼠标划过的空间
+				if(that.cursorObj){//当前存在鼠标划过的对象
+					if(!area){//从当前滑过对象上移开
+						that.cursorObj.material.color = that.cursorMeshColor;//恢复原来颜色
+						that.cursorObj = null;
+						that.cursorMeshColor = null;
+						document.body.style.cursor = 'default';//还原鼠标样式
+					}else{//当次还存在划过的对象
+						if(that.cursorObj.uuid == area.uuid){//一致,则不处理
+							return false;
+						}else{//不同
+							that.cursorObj.material.color = that.cursorMeshColor;//恢复原来颜色
+							that.cursorObj = area;//记录下当前鼠标划过的对象;
+							that.cursorMeshColor = area.material.color.clone();//复制当前模型材质的颜色,用与取消选中时还原
+							let color = new THREE.Color(0xff9f36); // 使用sRGB颜色值
+							color.convertSRGBToLinear(); // 将颜色值转换为线性颜色值
+							area.material.color = color;//变更颜色
+							document.body.style.cursor = 'move';//修改鼠标样式
+						}
+					}
+				}else{//不存在鼠标划过的对象
+					if(!area){
+						document.body.style.cursor = 'default';//修改鼠标样式
+						return false;
+					}
+					that.cursorMeshColor = area.material.color.clone();//复制当前模型材质的颜色,用与取消选中时还原
+					that.cursorObj = area;//记录下当前鼠标划过的对象;
+					let color = new THREE.Color(0xff9f36); // 使用sRGB颜色值
+					color.convertSRGBToLinear(); // 将颜色值转换为线性颜色值
+					area.material.color = color;//修改颜色
+					document.body.style.cursor = 'move';//修改鼠标样式
+					console.warn("****cursorObj***",that.cursorObj)
+				}
+			}
+			//空间对象移动
+			function moveObj (obj,event) {
+				if(!obj || !event){
+					return false;
+				}
+				let _position = getWorldPoint(event);
+				if(!_position || !_position.x){//没有获取到坐标,可能发生了越界
+					return false;
+				}
+				let _x = _position.x - that.moveStarPosition.x;//相对上一次移动触发时的移动距离
+				let _y = _position.y - that.moveStarPosition.y;
+				if(_x==0 && _y==0){//没有变化
+					return false;
+				}
+				if(obj.adsorbLockX){//X轴吸附
+					if(_position.x <= obj.adsorDisMaxX && _position.x >= obj.adsorDisMinX ){//移动的距离没超过阈值-不实际移动
+						_x = 0;//锁定X轴,不移动
+					}else{
+						moveObjHandle(obj,-obj.adsorDisX,0);//补充移动,填补鼠标的偏移量
+						obj.adsorbLockX = false;//解锁,可以继续移动
+					}
+				}
+				if(obj.adsorbLockY){//Y轴吸附
+					if(_position.y <= obj.adsorDisMaxY && _position.y >= obj.adsorDisMinY ){//移动的距离没超过阈值-不实际移动
+						_y = 0;//锁定Y轴移动距离,不移动
+					}else{
+						moveObjHandle(obj,0,-obj.adsorDisY);//补充移动,填补鼠标的偏移量
+						obj.adsorbLockY = false;//解锁,可以继续移动
+						// console.warn("***moveObjHandle2***",_position.y,obj.adsorDisMaxY,obj.adsorDisMinY,obj.position.y)
+					}
+				}
+				// console.warn("***moveObjHandle0***",_x,_y,
+				// obj.adsorDisMaxX,obj.adsorDisMinX,
+				// obj.adsorDisMaxY,obj.adsorDisMinY,
+				// obj.adsorbLockX,obj.adsorbLockY,
+				// that.moveStarPosition.x,that.moveStarPosition.y)
+				//先移动
+				moveObjHandle(obj,_x,_y);
+				//没有锁定X轴时
+				if(!obj.adsorbLockX){//X轴吸附
+					that.moveStarPosition.x = _position.x;
+				}
+				//没有锁定Y轴时
+				if(!obj.adsorbLockY){//Y轴吸附
+					that.moveStarPosition.y = _position.y;
+				}
+				if(!obj.adsorbLockX || !obj.adsorbLockY){//当前移动对象没有锁定也即吸附
+					// that.moveStarPosition.x = _position.x;
+					// that.moveStarPosition.y = _position.y;
+					adsorbHandle(obj,_x,_y);//开始吸附处理
+				}
+			}
+			//移动对象移动处理函数
+			function moveObjHandle(obj,_x=0,_y=0){
+				//先移动
+				if(obj.XLine){//如果移动对象存在X轴提示线
+					obj.XLine.translateX(_x);
+					obj.XLine.translateY(_y);
+					let tempV = new THREE.Vector3();//文字移动后的坐标位置-世界坐标系下
+					tempV.x = obj.XLine.lableX + _x;
+					tempV.y = obj.XLine.lableY + _y;
+					tempV.z = 0;
+					makeTips(obj.XLine,tempV)
+				}
+				if(obj.YLine){//如果移动对象存在Y轴提示线
+					obj.YLine.translateX(_x);
+					obj.YLine.translateY(_y);
+					let tempV = new THREE.Vector3();//文字移动后的坐标位置-世界坐标系下
+					tempV.x = obj.YLine.lableX + _x;
+					tempV.y = obj.YLine.lableY + _y;
+					tempV.z = 0;
+					makeTips(obj.YLine,tempV)
+				}
+				if(obj.elem){//如果移动对象存在面积提示lable
+					let tempV = new THREE.Vector3();//文字移动后的坐标位置-世界坐标系下
+					tempV.x = obj.lableX + _x;
+					tempV.y = obj.lableY + _y;
+					tempV.z = 0;
+					makeTips(obj,tempV)
+				}
+				obj.translateX(_x);
+				obj.translateY(_y);
+			}
+			//吸附处理函数
+			//移动结束后进行吸附经查
+			//吸附定义如下:如果移动对象进入其他空间边界线0.5m(adsorbDis)范围内,则触发吸附
+			//吸附过程中,只要移动对象没有离开吸附区域(由adsorbDis确定),则锁定移动目标;
+			//移动对象一旦离开吸附区域,则恢复至可移动状态,同时消除偏移量,确保鼠标位置正确
+			function adsorbHandle (obj,_x,_y) {
+				let direction = {
+					horizontal:'',	//水平移动的方向
+					vertical:'',	//垂直移动的方向
+				};
+				//计算移动方向-相对上一次的
+				if(_x>0){//向右移动
+					direction.horizontal = 'right';
+				}
+				else if(_x<0){//向左移动
+					direction.horizontal = 'left';
+				}
+				if(_y>0){//向上移动-检查上边界,下边界不做检查-当前逻辑
+					direction.vertical = 'up';
+				}
+				else if(_y<0){//向下移动-检查下边界,上边界不做检查-当前逻辑
+					direction.vertical = 'down';
+				}
+				let dis = adsorbCheck(obj,direction);//吸附检查
+				if(dis.x){
+					obj.adsorbLockX = true;//X轴吸附锁定
+					if(direction.horizontal == 'left'){
+						obj.adsorDisMaxX = that.moveStarPosition.x + (that.adsorbDis - dis.x);//吸附距离
+						obj.adsorDisMinX = that.moveStarPosition.x - (that.adsorbDis + dis.x);//吸附距离
+					}else if(direction.horizontal == 'right'){
+						obj.adsorDisMaxX = that.moveStarPosition.x + (that.adsorbDis + dis.x);//吸附距离
+						obj.adsorDisMinX = that.moveStarPosition.x - (that.adsorbDis - dis.x);//吸附距离
+					}
+					obj.adsorDisX = dis.x;//对象的偏移量-相对鼠标的
+					// obj.adsorDirec = direction.horizontal;//吸附方向
+					console.warn("***moveObj-checkX1***",dis,that.moveStarPosition.x,dis,direction,obj.adsorbLockX,obj.adsorbLockY)
+				}
+				if(dis.y){
+					obj.adsorbLockY = true;//Y轴吸附锁定
+					if(direction.vertical == 'down'){
+						obj.adsorDisMaxY = that.moveStarPosition.y + (that.adsorbDis - dis.y);//吸附距离
+						obj.adsorDisMinY = that.moveStarPosition.y - (that.adsorbDis + dis.y);//吸附距离
+					}else if(direction.vertical == 'up'){
+						obj.adsorDisMaxY = that.moveStarPosition.y + (that.adsorbDis + dis.y);//吸附距离
+						obj.adsorDisMinY = that.moveStarPosition.y - (that.adsorbDis - dis.y);//吸附距离
+					}
+					obj.adsorDisY = dis.y;//对象的偏移量-相对鼠标的
+					// obj.adsorDirec = direction.vertical;//吸附方向
+					console.warn("***moveObj-checkY2***",dis,that.moveStarPosition.y,dis,direction,obj.adsorbLockX,obj.adsorbLockY)
+				}
+				if(dis.x || dis.y){
+					moveObjHandle(obj,dis.x,dis.y);//补充移动
+				}
+			}
+			//吸附检查-遍历所有绘制的空间;obj 当前操作的空间对象
+			//direction 移动的方向
+			//如果某一方向上没有变化,则不检测该方向,该方向返回为undefined
+			function adsorbCheck (obj,direction) {
+				let _areaList = that.areaList;
+				if(!_areaList || _areaList.length<2){//绘制的空间必须大于1个,检查才有意义
+					return false;
+				}
+				let _sourceX;
+				let _sourceY;
+				let _x,_y;//修正后的移动距离
+				if(direction.horizontal=='left'){//向左移动
+					_sourceX = obj.position.x - Math.abs(obj.scale.x/2);//获取右侧垂直线的X轴的值-世界坐标系
+				}else if(direction.horizontal=='right'){//向右移动
+					_sourceX = obj.position.x + Math.abs(obj.scale.x/2);//获取右侧垂直线的X轴的值-世界坐标系
+				}
+				if(direction.vertical=='up'){//向上移动
+					_sourceY = obj.position.y + Math.abs(obj.scale.y/2);//获取右侧垂直线的X轴的值-世界坐标系
+				}else if(direction.vertical=='down'){//向下移动
+					_sourceY = obj.position.y - Math.abs(obj.scale.y/2);//获取右侧垂直线的X轴的值-世界坐标系
+				}
+				
+				//获取其他空间的水平、垂直线
+				// _areaList.forEach((item,index)=>{
+				for (let item of _areaList) {
+					if(item!=obj){//其他空间对象
+						let leftX,rightX,topY,downY;
+						rightX = item.position.x + Math.abs(item.scale.x/2);//获取右侧垂直线的X轴的值-世界坐标系
+						leftX = item.position.x - Math.abs(item.scale.x/2);//获取左侧垂直线的X轴的值-世界坐标系
+						topY = item.position.y + Math.abs(item.scale.y/2);//获取up侧垂直线的X轴的值-世界坐标系
+						downY = item.position.y - Math.abs(item.scale.y/2);//获取左侧垂直线的X轴的值-世界坐标系
+						if(_sourceX != null && _x==null){//说明水平方向上有移动
+							if(Math.abs(_sourceX - rightX) < that.adsorbDis){//检查到距离差到达阈值
+								// console.warn("***adsorbDis-checkX1***",_sourceX,rightX,direction)
+								_x = rightX - _sourceX;
+							}else if(Math.abs(_sourceX - leftX) < that.adsorbDis){//检查到距离差到达阈值
+								// console.warn("***adsorbDis-checkX2***",_sourceX,leftX,direction)
+								_x = leftX - _sourceX;
+							}
+						}
+						if(_sourceY != null && _y==null){//说明垂直方向上有移动
+							if(Math.abs(_sourceY - topY) < that.adsorbDis){//检查到距离差到达阈值
+								// console.warn("***adsorbDis-checkY1***",_sourceY,topY,direction)
+								_y =  topY - _sourceY;
+							}else if(Math.abs(_sourceY - downY) < that.adsorbDis){//检查到距离差到达阈值
+								// console.warn("***adsorbDis-checkY2***",_sourceY,downY,direction)
+								_y = downY - _sourceY;
+							}
+						}
+						if(_x != null && _y != null){//表示两个方向都要检查
+							break;
+						}
+					}
+				}
+				return {x:_x,y:_y}
+			}
+			//绘制墙壁-2D
+			function drawWall () {
+				
+			}
+		},
+		destroyed() {
+			window.map && typeof window.map.destroyed === "function" && window.map.destroyed();
+			window.map = null;
+		},
+		methods: {
+			initData(area) {
+				this.area = area;
+			},
+			render() {
+				this.renderer.render(this.scene, this.camera); //单次渲染
+				this.stats.update();
+				requestAnimationFrame(this.render)
+			},
+			//操作监听
+			operateHandle(item){
+				if(!item || !item.id){
+					return false;
+				}
+				if(item.id==1){//空间新增
+					this.pageStatus = 2;
+				}
+				if(item.id==2){//空间新增
+					this.pageStatus = 1;
+				}
+				console.warn("***operateHandle***",item,this.pageStatus)
+			},
+		},
+	};
+</script>
+<style lang="css" scoped>
+	@import "./mapComponent.css";
+</style>

+ 56 - 0
src/main.js

@@ -0,0 +1,56 @@
+import Vue from 'vue'
+import App from './App.vue'
+import store from '@/store/index.js';
+import api from '@/services/urlConfig.js'; //导入请求的环境地址配置
+import router from '@/router';
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css'; //导入ele-ui 的样式
+import $ from 'jquery'; //引入JQuery
+import axios from '@/services/request.js'; //重新定义axios,向里面添加一些参数
+import '@/services/requestConfig.js'; //导入请求的拦截器
+import common from '@/utils/common.js'; //引入公共函数
+import '@/utils/rem.js'; //rem单位的使用
+
+import '@/assets/common.css'; //公共样式
+import "@/assets/font/iconfont.css"; //引用公共icon库
+// import popUpComponent from "@/components/popUpComponent/popUpComponent.js"; // 公共弹框样式
+// import previewComponent from "@/components/previewComponent/previewComponent.js"; // 公共图片视频预览
+import "@/utils/command.js"; // 自定义指令
+import {message} from "@/utils/resetMessage";
+// import checkPermission from "@/utils/permission";
+
+Vue.use(ElementUI); //导入ele-ui
+// Vue.prototype.$popUp = popUpComponent;
+// Vue.prototype.$preview = previewComponent;
+window.$bus = new Vue(); //定义一个事件总线对象-方便组件通讯
+window.axios = axios;
+window.common = common;
+window.$ = $;
+Vue.prototype.axios = axios;
+// Vue.prototype.checkPermission = checkPermission; // 权限校验
+Vue.config.productionTip = false; //阻止启动生产消息
+Vue.prototype.$message = message//重写提示
+
+// 引入echarts
+import * as echarts from 'echarts'
+window.echarts = echarts
+
+console.log('***process.env***', process.env);
+window.env = process.env.NODE_ENV;
+env = env == 'development' ? 'test2' : env;
+window.$config = api(env);
+console.log("window.$config", window.$config);
+
+// runtime模式-运行时
+// new Vue({
+//   render: h => h(App),
+// }).$mount('#app')
+
+// compiler(模板)
+window.mapVue = new Vue({
+    el: '#app',
+    router,
+    store,
+    components: { App },
+    template: '<App/>',
+});

+ 604 - 0
src/mixins/cropper.js

@@ -0,0 +1,604 @@
+// import { Toast } from "mint-ui";
+    import {adverMaterielServer} from '@/services'
+    var qiniu = require('qiniu-js');
+export default {
+    data() {
+        return {
+            callback: null,
+            // cropperFlag:true,
+            isDisable: false,
+        }
+    },
+    methods: {
+        // preview 预览图片
+        preview(type) {
+            var test = window.open('about:blank')
+            test.document.body.innerHTML = '图片生成中..'
+            if (type === 'blob') {
+                this.$refs.cropper.getCropBlob((data) => {
+                    test.location.href = window.URL.createObjectURL(data)
+                })
+            } else {
+                this.$refs.cropper.getCropData((data) => {
+                    test.location.href = data
+                })
+            }
+        },
+        uploadImgFunc(e, option, form, callback) {
+            // this.currentOption
+            // 对象合并
+            Object.assign(this.currentOption, option);
+            this.currentOption.form = form;
+            this.callback = callback;
+            // this.currentOption.Item = obj;
+            //上传图片
+            var file = e.target.files[0];
+            const isLt2M = file.size / 1024 / 1024 < this.limit;
+
+            if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
+                this.$message.warning('图片类型必须是.gif,jpeg,jpg,png,bmp中的一种');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            if (!isLt2M) {
+                // this.$message.error('上传图片大小不能超过 ' + this.limit + 'MB!');
+                this.$message.warning('上传图片大小不能超过 ' + this.limit + 'MB!');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            this.currentOption.fileName = file.name;
+            var reader = new FileReader()
+            reader.onload = (e) => {
+                let data
+                if (typeof e.target.result === 'object') {
+                    // 把Array Buffer转化为blob 如果是base64不需要
+                    data = window.URL.createObjectURL(new Blob([e.target.result]))
+                } else {
+                    data = e.target.result
+                }
+                this.currentOption.img = data;
+                this.showCropper = true;
+                setTimeout(()=>{
+                    cropperFlag = true; //重置状态,使得可以重新上传
+                },1000)
+            }
+            // 转化为base64
+            // reader.readAsDataURL(file)
+            // 转化为blob
+            reader.readAsArrayBuffer(file)
+        },
+        uploadImgObj(e, option, form, obj, flag) {
+            // this.currentOption
+            // 对象合并
+            if (e.target.dataset.common == 1) {
+                this.commonFlag = true;
+            }
+            console.log("1%%%$$^*&*", this.currentOption, option)
+            Object.assign(this.currentOption, option);
+            this.currentOption.form = form;
+            this.currentOption.Item = obj;
+            console.log("2%%%$$^*&*", this.currentOption, option)
+            //上传图片
+            var file = e.target.files[0];
+            const fileSize = file.size / 1024 / 1024;
+            if (this.gifLimit && fileSize > this.gifLimit && !file.type.includes('mp4')) {
+                this.$message.warning('上传gif图片大小不能超过 ' + this.gifLimit + 'MB!');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            const isLt2M = file.size / 1024 / 1024 < this.limit;
+            if(obj == 'uploadSwipVideo'){
+                if (!/\.(MP4|mp4)$/.test(e.target.value)) {
+                    this.$message.warning('文件片类型必须是MP4');
+                    var videoForm = document.getElementById(form); //获取表单对象
+                    videoForm && videoForm.reset(); // 重置表单
+                    return false
+                }
+            }
+            else if (obj == 'includeVideo') { //可以上传视频
+                if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG|MP4|mp4)$/.test(e.target.value)) {
+                    this.$message.warning('文件片类型必须是.gif,jpeg,jpg,png,bmp,MP4中的一种');
+                    var videoForm = document.getElementById(form); //获取表单对象
+                    videoForm && videoForm.reset(); // 重置表单
+                    return false
+                }
+
+            } else {
+                if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
+                    this.$message.warning('图片类型必须是.gif,jpeg,jpg,png,bmp中的一种');
+                    var videoForm = document.getElementById(form); //获取表单对象
+                    videoForm && videoForm.reset(); // 重置表单
+                    return false
+                }
+            }
+            if (!isLt2M && !file.type.includes('gif') && !file.type.includes('mp4')) {
+                // this.$message.error('上传图片大小不能超过 ' + this.limit + 'MB!');
+                this.$message.warning('上传图片大小不能超过 ' + this.limit + 'MB!');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            if (fileSize > 1000 && file.type.includes('mp4')) {
+                // this.$message.error('上传图片大小不能超过 ' + this.limit + 'MB!');
+                this.$message.warning('上传视频大小不能超过 ' + 10 + 'MB!');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            if ((file.type === 'image/gif' || obj == 'includeVideo' || obj == 'isOriginal' || this.operateKey ==
+                    'videoCoverUrl' || flag == 'isOriginUpload') && this.uploadMaterielFile && typeof this.uploadMaterielFile ==
+                "function") {
+                console.log('gif图,进入非剪裁')
+                var item = {};
+                item.file = file;
+                this.uploadMaterielFile(item, form, file.type.includes('mp4') ? 'video' : 'gif'); //正常上传图片
+                setTimeout(()=>{
+                    cropperFlag = true; //重置状态,使得可以重新上传
+                },1000)
+                return false;
+            } else {
+                console.log('进入非剪裁')
+                var item = {};
+                item.file = file;
+                this.uploadMaterielFile(item, form, file.type.includes('mp4') ? 'video' : 'gif'); //正常上传图片
+                setTimeout(()=>{
+                    cropperFlag = true; //重置状态,使得可以重新上传
+                },1000)
+                return false;
+            }
+            // console.log('进入剪裁')
+            // this.currentOption.fileName = file.name;
+            // var reader = new FileReader()
+            // reader.onload = (e) => {
+            //     let data
+            //     if (typeof e.target.result === 'object') {
+            //         // 把Array Buffer转化为blob 如果是base64不需要
+            //         data = window.URL.createObjectURL(new Blob([e.target.result]))
+            //     } else {
+            //         data = e.target.result
+            //     }
+            //     this.currentOption.img = data;
+            //     this.showCropper = true;
+            // }
+            // reader.readAsArrayBuffer(file)
+        },
+        uploadImg(e, option, form, staticLimit, gifLimit, obj) {
+
+            var file = e.target.files[0];
+            if (form === 'tdForm' && e.target.value.includes('gif')) {
+                this.$message.warning('图片类型不能为gif格式');
+                return false
+            }
+            if (form === 'tdForm' && file.size / 1024 / 1024 > 2) {
+                this.$message.warning('图片大小不能超过2M!');
+                return false
+            }
+            console.log("***uploadImg***");
+            var _limit = staticLimit ? staticLimit : this.limit;
+            var _giflimit = gifLimit ? gifLimit : 5; //Gif 图片的限制是5MB,产品确认的
+            const isLt2M = file.size / 1024 / 1024 < _limit;
+            const isLtGIF = file.size / 1024 / 1024 < _giflimit;
+            if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG|pdf)$/.test(e.target.value)) {
+                this.$message.warning('图片类型必须是.gif,jpeg,jpg,png,bmp中的一种');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            if (file.type === 'image/gif') {
+                if (!isLtGIF) {
+                    this.$message.warning('上传图片大小不能超过' + _giflimit + 'MB!');
+                    var videoForm = document.getElementById(form); //获取表单对象
+                    videoForm && videoForm.reset(); // 重置表单
+                    return false
+                }
+            } else if (!isLt2M) {
+                this.$message.warning('上传图片大小不能超过 ' + _limit + 'MB!');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            Object.assign(this.currentOption, option);
+
+            // 如果是gif图片则调用正常上传不启用裁剪过程
+            if ((file.type === 'image/gif' || obj == 'isOriginal') && this.uploadMaterielFile && typeof this.uploadMaterielFile == "function") {
+                var item = {};
+                item.file = file;
+                this.uploadMaterielFile(item, form); //正常上传图片
+                setTimeout(()=>{
+                    cropperFlag = true; //重置状态,使得可以重新上传
+                },1000)
+                return false;
+            }
+            // Object.assign(this.currentOption, option);
+            this.currentOption.form = form;
+            this.currentOption.fileName = file.name;
+            var reader = new FileReader()
+            reader.onload = (e) => {
+                let data
+                if (typeof e.target.result === 'object') {
+                    // 把Array Buffer转化为blob 如果是base64不需要
+                    data = window.URL.createObjectURL(new Blob([e.target.result]))
+                } else {
+                    data = e.target.result
+                }
+                this.currentOption.img = data;
+                this.showCropper = true;
+                setTimeout(()=>{
+                    cropperFlag = true; //重置状态,使得可以重新上传
+                },1000)
+            }
+            // 转化为base64
+            // reader.readAsDataURL(file)
+            // 转化为blob
+            reader.readAsArrayBuffer(file)
+        },
+        uploadImgXMB(e, option, form, limit, obj) {
+            console.log("***uploadImg***");
+            var file = e.target.files[0];
+            var _limit = limit || 2;
+            const isLt2M = file.size / 1024 / 1024 < _limit;
+            const isLtGIF = file.size / 1024 / 1024 < _limit; //Gif 图片的限制是5MB,产品确认的
+            if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
+                this.$message.warning('图片类型必须是.gif,jpeg,jpg,png,bmp中的一种');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            if (file.type === 'image/gif') {
+                if (!isLtGIF) {
+                    this.$message.warning('上传图片大小不能超过' + _limit + 'MB!');
+                    var videoForm = document.getElementById(form); //获取表单对象
+                    videoForm && videoForm.reset(); // 重置表单
+                    return false
+                }
+            } else if (!isLt2M) {
+                this.$message.warning('上传图片大小不能超过 ' + _limit + 'MB!');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            Object.assign(this.currentOption, option);
+            // 如果是gif图片则调用正常上传不启用裁剪过程
+            if ((file.type === 'image/gif' || obj == 'isOriginal') && this.uploadMaterielFile && typeof this.uploadMaterielFile == "function") {
+                var item = {};
+                item.file = file;
+                this.uploadMaterielFile(item, form); //正常上传图片
+                setTimeout(()=>{
+                    cropperFlag = true; //重置状态,使得可以重新上传
+                },1000)
+                return false;
+            }
+            // Object.assign(this.currentOption, option);
+            this.currentOption.form = form;
+            this.currentOption.fileName = file.name;
+            var reader = new FileReader()
+            reader.onload = (e) => {
+                let data
+                if (typeof e.target.result === 'object') {
+                    // 把Array Buffer转化为blob 如果是base64不需要
+                    data = window.URL.createObjectURL(new Blob([e.target.result]))
+                } else {
+                    data = e.target.result
+                }
+                this.currentOption.img = data;
+                this.showCropper = true;
+                setTimeout(()=>{
+                    cropperFlag = true; //重置状态,使得可以重新上传
+                },1000)
+            }
+            // 转化为base64
+            // reader.readAsDataURL(file)
+            // 转化为blob
+            reader.readAsArrayBuffer(file)
+        },
+        // 上传原图:obj 是 包含图片的对象,property 是obj 对象里面图片地址对应的属性key
+        async uploadObjImageFile(e, form, obj,  property) {
+            var self = this;
+            var file = e.target.files[0];
+            const isLt2M = file.size / 1024 / 1024 < this.limit;
+            const isLtVideo = file.size / 1024 / 1024 < this.videolimit; //视频 的限制是5MB
+            const isLtGIF = file.size / 1024 / 1024 < this.gifLimit; //Gif 图片的限制是5MB,产品确认的
+            if (!/\.(gif|jpg|jpeg|png|GIF|JPG|PNG|mp4)$/.test(e.target.value)) {
+                this.$message.warning('类型必须是.gif,jpeg,jpg,png,mp4中的一种');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false
+            }
+            if (file.type === 'video/mp4') {
+                if (!isLtVideo) {
+                    this.$message.warning('上传文件大小不能超过' + this.videolimit + 'MB!');
+                    var videoForm = document.getElementById(form); //获取表单对象
+                    videoForm && videoForm.reset(); // 重置表单
+                    return false
+                }
+            }
+            else{
+                if (file.type === 'image/gif') {
+                    if (!isLtGIF) {
+                        this.$message.warning('上传图片大小不能超过' + this.gifLimit + 'MB!');
+                        var videoForm = document.getElementById(form); //获取表单对象
+                        videoForm && videoForm.reset(); // 重置表单
+                        return false
+                    }
+                } else if (!isLt2M) {
+                    this.$message.warning('上传图片大小不能超过 ' + this.limit + 'MB!');
+                    var videoForm = document.getElementById(form); //获取表单对象
+                    videoForm && videoForm.reset(); // 重置表单
+                    return false
+                }
+            }
+            if (file.name.length > 100) {
+                this.$message.warning('文件名过长,请不要超过100个字符');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false;
+            }
+            self.$store.state.loading = true;
+
+            var formData = new FormData();
+            formData.append("file", file);
+            let res = await requestConfig('aliyunOpenapiUploadOss', formData, false);
+            if (res.success) {
+                var imgUrl = res.single || ''
+                obj[property] = imgUrl;
+            }
+            self.$store.state.loading = false;
+            var videoForm = document.getElementById(form); //获取表单对象
+            videoForm && videoForm.reset(); // 重置表单
+        },
+        cropperUpload(type, callback) {
+            var file = "";
+            var self = this;
+            this.isDisable = true;
+            console.log("cropperFlag1:", cropperFlag);
+            if (cropperFlag == false) {
+                return false;
+            }
+            cropperFlag = false;
+            console.log("cropperFlag2:", cropperFlag);
+            // if(this.cropperFlag == true){
+            //     return this.$message.warning("请等待上传完毕,不要重复点击");
+            // }
+            // this.cropperFlag = true;
+            try {
+                if (type === 'blob') {
+                    self.$refs.cropper.getCropBlob((data) => {
+                        file = window.URL.createObjectURL(data)
+                        // console.log("***uploadProjectFile***", type, file)
+                        if (!self.callback) {
+                            self.callback = callback;
+                        }
+
+                        typeof self.callback == "function" && self.callback(file); // 执行回调函数
+                        // cropperFlag = true;
+                        self.isDisable = false;
+                    })
+                } else {
+                    self.$refs.cropper.getCropData((data) => {
+                        file = data
+                        // console.log("***uploadProjectFile***", type, file)
+                        // this.uploadProjectFile(file)
+                        if (!self.callback) {
+                            self.callback = callback;
+                        }
+
+                        typeof self.callback == "function" && self.callback(file); // 执行回调函数
+                        // cropperFlag = true;
+                        self.isDisable = false;
+                    })
+                }
+            } catch (e) {
+                this.$message.error(e.message);
+                cropperFlag = true;
+            }
+        },
+        // 关闭弹层
+        cropoerCancel(option, callback) {
+            var videoForm = document.getElementById(option.form); //获取表单对象
+            videoForm.reset(); // 重置表单
+            this.showCropper = false;
+            option.img = "";
+            callback && typeof callback == "function" && callback();
+        },
+        rotateLeft() {
+            this.$refs.cropper.rotateLeft()
+        },
+        rotateRight() {
+            this.$refs.cropper.rotateRight()
+        },
+        next(res) {},
+        // 上传七牛云发生错误
+        error(res) {
+            this.$message.error('上传失败' + res.message);
+        },
+        async uploadMaterielFile(item, form, type) {
+            if (item.file.name.length > 100) {
+                this.$message.warning('文件名过长,请不要超过100个字符');
+                var videoForm = document.getElementById(form); //获取表单对象
+                videoForm && videoForm.reset(); // 重置表单
+                return false;
+            }
+            var self = this;
+            console.log(item);
+
+            var formData = new FormData();
+            formData.append("file", item.file);
+            let imgUrl = ''
+            let res = await requestConfig('aliyunOpenapiUploadOss', formData, false);
+            if (res.success) {
+                 imgUrl = res.single || ''
+                if (self.currentOption.Item === 'iconItem') {
+                    self.area.areaTitleObj.iconStyle['background-image'] = 'url(' + imgUrl + ')'
+                } else if (self.currentOption.Item === 'uploadSwipImg') {//轮播组件的图片
+                    self.area.imagesList[self.moduleCurrentEditIndex].imageUrl = imgUrl
+                } else if (self.currentOption.Item === 'uploadSwipVideo') {//轮播组件的视频
+                    self.area.imagesList[self.moduleCurrentEditIndex].videoUrl = imgUrl
+                } else if (self.currentOption.Item === 'uploadSwipImg4') {
+                    self.area.moduleLeftList[self.moduleCurrentEditIndex].moduleStyle.imageUrl = imgUrl
+                } else if (self.currentOption.Item === 'uploadDoubleRightImg') {
+                    self.area.moduleRightList[self.moduleCurrentEditIndex].moduleStyle.imageUrl = imgUrl
+                } else if (self.currentOption.Item === 'uploadMsgIconImg') {//统一标题icon图片
+                    self.area.unifyTitleObj.iconStyle['background-image'] = 'url(' + imgUrl + ')'
+                } else if (self.currentOption.Item === 'uploadProjectIconImg') { //项目位置
+                    self.area.projectSet.iconStyle['background-image'] = 'url(' + imgUrl + ')'
+                } else if(self.currentOption.Item==='uploadTitleIconImg'){
+                    self.area.areaTitleObj.iconStyle['background-image'] = 'url('+imgUrl+')'
+                } else if (self.currentOption.Item === 'moduleTitleObjIconItem') {
+                    self.moduleView.titleObj.iconStyle['background-image'] = 'url(' + imgUrl + ')'
+                } else if (self.currentOption.Item === 'moduleTitleObjunIconItem') {
+                    self.moduleView.titleObj.iconStyle['unbackground-image'] = 'url(' + imgUrl + ')'
+                } else if (self.currentOption.Item === 'moduleIconItem') {
+                    self.moduleView.iconStyle['background-image'] = 'url(' + imgUrl + ')'
+                } else if (self.currentOption.Item === 'moduleunIconItem') {
+                    self.moduleView.iconStyle['unbackground-image'] = 'url(' + imgUrl + ')'
+                } else if (self.currentOption.Item === 'afterImageUrl') {
+                    self.moduleView.moduleStyle.afterImageUrl = imgUrl;
+                } else if (self.currentOption.Item === 'overImageUrl') {
+                    self.moduleView.moduleStyle.overImageUrl = imgUrl;
+                } else if (self.currentOption.Item === 'areaIconImageUrl') {//关闭icon配置
+                    self.area.iconStyle['background-image'] = 'url('+imgUrl+')'
+                } else if(self.currentOption.Item==='areaImageUrl'){//区域背景图
+                    self.area.areaStyle['background-image'] = 'url('+imgUrl+')'
+                } else if (self.currentOption.Item === 'includeVideo') {
+                    if (type == 'video') {
+                        self.moduleView.moduleStyle.videoUrl = imgUrl
+                    } else {
+                        self.moduleView.moduleStyle.imageUrl = imgUrl
+                    }
+                } else {
+                    console.log(self.moduleView.moduleStyle)
+                    self.moduleView.moduleStyle.imageUrl = imgUrl
+                }
+                self.$message.success('上传成功');
+            }
+            if (this.area.diyArea) {
+                this.$nextTick(() => {
+                    this.$store.state.loading = true;
+                    setTimeout(() => {
+                        let img = document.createElement("img");
+                        img.src = imgUrl;
+                        img.onload = () => {
+                            console.log("图片加载完成----", self.uploadImgs, "当前索引---", self.moduleCurrentEditIndex);
+                            if (self.uploadImgs.includes(self.moduleCurrentEditIndex)) {//当前图片已经上传
+                                self.usedIMGWidth -= self.getNum(self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle.width);
+                                self.uploadImgs.splice(self.uploadImgs.indexOf(self.moduleCurrentEditIndex), 1);
+                            }
+                            let imageCount = self.uploadImgs.length;
+                            console.log("图片加载完成", imageCount);
+                            if (imageCount < self.area.moduleList.length) {
+                                if (self.area.moduleList.length === 1) {
+                                    if (img.width <= 50) {
+                                        this.area.moduleList[0].moduleStyle.width = 50 + 'px';
+                                        this.area.moduleList[0].moduleStyle.height = (parseInt(img.height * 50 / img.width)) + 'px'
+                                        this.area.areaStyle.height = (parseInt(img.height * 50 / img.width)) + 'px';
+                                    } else if (img.width > 50 && img.width <= 750) {
+                                        this.area.moduleList[0].moduleStyle.width = parseInt(img.width) + 'px';
+                                        this.area.moduleList[0].moduleStyle.height = parseInt(img.height) + 'px';
+                                        this.area.areaStyle.height = parseInt(img.height) + 'px';
+                                    } else {
+                                        this.area.moduleList[0].moduleStyle.width = 750 + 'px';
+                                        this.area.moduleList[0].moduleStyle.height = parseInt(img.height * 750 / img.width) + 'px';
+                                        this.area.areaStyle.height = parseInt(img.height * 750 / img.width) + 'px';
+                                    }
+                                } else {
+                                    let currentMaxWidth = 750 - self.usedIMGWidth - (self.area.moduleList.length - imageCount - 1) * 50;
+                                    console.log("上传图片的参数-22", "当前剩余宽度:  " + currentMaxWidth + "  宽度: " + img.width, "  高度: " + img.height, "  索引:  " + this.moduleCurrentEditIndex);
+                                    if (img.width >= currentMaxWidth) {
+                                        self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle.width = currentMaxWidth + 'px';
+                                        self.usedIMGWidth += currentMaxWidth;
+                                        self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle.height = (parseInt(img.height * currentMaxWidth / img.width)) + 'px';
+                                    } else {
+                                        if (img.width <= 50) {
+                                            self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle.width = 50 + 'px';
+                                            self.usedIMGWidth += 50;
+                                            console.log("宽度不够最大的,小于50,-一个", self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle);
+                                            self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle.height = (parseInt(img.height * 50 / img.width)) + 'px';
+                                        } else {
+                                            self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle.width = parseInt(img.width) + 'px';
+                                            self.usedIMGWidth += parseInt(img.width);
+                                            console.log("宽度不够最大的,大于50,-", self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle);
+                                            self.area.moduleList[self.moduleCurrentEditIndex].moduleStyle.height = parseInt(img.height) + 'px';
+                                        }
+
+                                    }
+                                    self.area.areaStyle.height = "auto";
+                                }
+                            }
+                            this.$store.state.loading = false;
+                            if (!self.uploadImgs.includes(self.moduleCurrentEditIndex)) { //已上传中没有
+                                self.uploadImgs.push(self.moduleCurrentEditIndex); //存储已经上传的图片位置
+                            }
+                            self.area.uploadImgPositions = self.uploadImgs;
+                            self.area.usedIMGWidth = self.usedIMGWidth;
+
+                        }
+                    }, 1000)
+                })
+            }
+            var videoForm = document.getElementById(this.currentOption.form); //获取表单对象
+            videoForm && videoForm.reset();// 重置表单
+        },
+        async uploadFile(file) {
+            let data = {
+                "base64Str": file,
+            };
+            let result = await adverMaterielServer.uploadBase64(data);
+            console.log(result, 'gggggg')
+            if (result && result.data.success) {
+                if (this.currentOption.Item === 'iconItem') {
+                    this.area.areaTitleObj.iconStyle['background-image'] = 'url(' + result.data.single.filePath + ')'
+                } else if (this.currentOption.Item === 'uploadSwipImg') {
+                    this.area.imagesList[this.moduleCurrentEditIndex].imageUrl = result.data.single.filePath
+                } else if (this.currentOption.Item === 'uploadSwipImg4') {
+                    this.area.moduleLeftList[this.moduleCurrentEditIndex].moduleStyle.imageUrl = result.data.single.filePath
+                } else if (this.currentOption.Item === 'uploadDoubleRightImg') {
+                    this.area.moduleRightList[this.moduleCurrentEditIndex].moduleStyle.imageUrl = result.data.single.filePath
+                } else if (this.currentOption.Item === 'uploadMsgIconImg') {//统一标题icon图片
+                    this.area.unifyTitleObj.iconStyle['background-image'] = 'url(' + result.data.single.filePath + ')'
+                } else if (this.currentOption.Item === 'uploadProjectIconImg') {
+                    this.area.projectSet.iconStyle['background-image'] = 'url(' + result.data.single.filePath + ')'
+                } else if (this.currentOption.Item === 'uploadTitleIconImg') {
+                    this.area.areaTitleObj.iconStyle['background-image'] = 'url(' + result.data.single.filePath + ')'
+                } else if (this.currentOption.Item === 'moduleTitleObjIconItem') {
+                    this.moduleView.titleObj.iconStyle['background-image'] = 'url(' + result.data.single.filePath + ')'
+                } else if (this.currentOption.Item === 'moduleTitleObjunIconItem') {
+                    this.moduleView.titleObj.iconStyle['unbackground-image'] = 'url(' + result.data.single.filePath + ')'
+                } else if (this.currentOption.Item === 'moduleIconItem') {
+                    this.moduleView.iconStyle['background-image'] = 'url(' + result.data.single.filePath + ')'
+                } else if (this.currentOption.Item === 'moduleunIconItem') {
+                    this.moduleView.iconStyle['unbackground-image'] = 'url(' + result.data.single.filePath + ')'
+                } else if (this.currentOption.Item === 'uploadModuleImage1Form') {
+                    this.moduleView.imageStyle.imageUrl = result.data.single.filePath
+                } else if (this.currentOption.Item === 'afterImageUrl') {
+                    this.moduleView.moduleStyle.afterImageUrl = result.data.single.filePath
+                } else if (this.currentOption.Item === 'overImageUrl') {
+                    this.moduleView.moduleStyle.overImageUrl = result.data.single.filePath
+                } else {
+                    console.log(this.moduleView)
+                    this.moduleView.moduleStyle.imageUrl = result.data.single.filePath
+                }
+                if (this.area.diyArea) {
+                    let img = document.createElement("img");
+                    img.src = result.data.single.filePath;
+                    img.onload = () => {
+                        this.area.areaStyle.height = (parseInt(img.height * 750 / img.width)) + 'px'
+                        this.area.moduleList[0].moduleStyle.height = (parseInt(img.height * 750 / img.width)) + 'px'
+                    }
+                }
+                this.showCropper = false;
+                var videoForm = document.getElementById(this.currentOption.form); //获取表单对象
+                videoForm && videoForm.reset();// 重置表单
+            } else {
+                this.$message.error('图片上传失败');
+                this.showCropper = false;
+                this.currentOption.img = "";
+                var videoForm = document.getElementById(this.currentOption.form); //获取表单对象
+                videoForm && videoForm.reset();// 重置表单
+            }
+            cropperFlag = true; //重置状态,使得可以重新上传
+        },
+    }
+}

+ 40 - 0
src/pages/loginView/loginView.html

@@ -0,0 +1,40 @@
+<div class="login_body" v-if='showLoginView'>
+	<img class="login_bg image--not-loaded" v-if='isShow' src="https://dm.static.elab-plus.com/things/%E8%83%8C%E6%99%AF.png?imageMogr2/auto-orient/thumbnail/200x200/blur/1x0/quality/75"/>
+    <video id="bgVideo" class="login_bg" :class="{'image--is-loaded':isShow==false}" muted src="https://dm.static.elab-plus.com/thing/video/index.mp4"
+     autoplay loop @play="updateTime" style="z-index:-2;"></video>
+	<div class="rows login_logo">
+		<img class="img_logo" src="https://dm.static.elab-plus.com/tings/icon_logo_ting.png" alt="" srcset="" />
+        <img class="img_logo_rihgt"  src="https://dm.static.elab-plus.com/things/eLab%E5%9F%8E%E5%B8%82%E9%A9%BE%E9%A9%B6%E8%88%B1.png" alt="" srcset=""/>
+	</div>
+	<span class="logo_desc">- 对城市进行智慧开发和营销的决策型平台 -</span>
+	<div class="columns logo_info">
+		<input class="login_name" placeholder="输入手机号" type="text" maxlength="11" v-model.trim="name" autocomplete="off" />
+		<div class="line"></div>
+		<div class="verification_info">
+			<input class="verification" type="text" v-model="pwd" maxlength="6"  @keyup.13="enter"
+				placeholder="验证码" autocomplete="off" />
+			<span class="Verify" @click="goSendCode">{{ codeText === '获取验证码' ? codeText : ( codeText+'s' ) }}</span>
+		</div>
+	</div>
+	<div class="btn_login" @click="enter">立即进入</div>
+	<div class="login_fill"></div>
+	<div class="rows rows-between login_notice">
+		<div class="login_item_notice">
+			<img class="img_notice" src="https://dm.static.elab-plus.com/tings/icon_yun.png" alt="" />
+			<span class="txt_notice">实时核心数据<br />云端一手掌握</span>
+		</div>
+		<div class="login_item_notice">
+			<img class="img_notice" src="https://dm.static.elab-plus.com/tings/icon_nao.png" alt="" />
+			<span class="txt_notice">拥有上帝视角<br />智能开发·营销</span>
+		</div>
+		<div class="login_item_notice">
+			<img class="img_notice" src="https://dm.static.elab-plus.com/tings/icon_wifi.png" alt="" />
+			<span class="txt_notice">远程指挥操控<br />快速反应管控</span>
+		</div>
+	</div>
+	<div class="rows login_private">
+		由&nbsp;
+		<img class="img_elab" src="https://dm.static.elab-plus.com/tings/icon_elab.png" alt="" />
+		提供云计算&数据服务
+	</div>
+</div>

+ 171 - 0
src/pages/loginView/loginView.scss

@@ -0,0 +1,171 @@
+.login_body {
+  width: 100%;
+  height: 100%;
+  background: transparent;
+  box-sizing: border-box;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+    position: absolute;
+}
+.login_bg{
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+  position: absolute;
+  left: 0;
+  top: 0;
+  z-index: -1;
+}
+.login_logo {
+  margin-top: 7%;
+}
+.img_logo_rihgt{
+    width: 190rem;
+height: 87rem;
+margin-left: 25rem;
+}
+.img_logo {
+  width: 66rem;
+  height: 74rem;
+}
+.txt_logo {
+  font-size: 46rem;
+  font-family: FontName, FontName-Regular;
+  font-weight: 400;
+  text-align: left;
+  color: #ffffff;
+  line-height: 50rem;
+  margin-left: 30rem;
+  font-style: italic;
+}
+.logo_desc {
+  opacity: 0.8;
+  font-size: 16px;
+  font-family: Verdana, Verdana-Bold;
+  font-weight: 700;
+  text-align: center;
+  color: #ffffff;
+  margin-top: 31rem;
+}
+.logo_info {
+  width: 300rem;
+  height: 96rem;
+  background: #ffffff;
+  border-radius: 10rem;
+  margin-top: 37rem;
+}
+.login_name {
+  width: 100%;
+  height: 45rem;
+  font-size: 15px;
+  padding-left: 20rem;
+  box-sizing: border-box;
+  border-radius: 10rem;
+  border: transparent;
+   outline: transparent;
+}
+.line {
+  width: 265rem;
+  height: 1rem;
+  opacity: 0.1;
+  background: #707070;
+}
+.verification_info {
+  width: 100%;
+  height: 45rem;
+  font-size: 15px;
+  padding-left: 20rem;
+  box-sizing: border-box;
+  display: flex;
+  align-items: center;
+}
+.verification {
+  box-sizing: border-box;
+  border-radius: 10rem;
+  border: transparent;
+  height: 45rem;
+  outline: transparent;
+  width: 40%;
+  padding: unset;
+}
+.Verify {
+    width: 60%;
+  font-size: 14px;
+  font-family: Verdana, Verdana-Regular;
+  font-weight: 400;
+  text-align: center;
+  color: #ef863f;
+    cursor: pointer;
+    display: block;
+}
+.btn_login {
+  width: 300rem;
+  height: 46rem;
+  line-height: 46rem;
+  background: #ef863f;
+  border-radius: 10rem;
+  font-size: 15px;
+  font-family: Verdana, Verdana-Bold;
+  font-weight: 700;
+  text-align: center;
+  color: #ffffff;
+  margin-top: 10rem;
+  cursor: pointer;
+}
+.login_fill {
+  flex: 1;
+}
+.login_notice {
+  width: 40%;
+  margin-bottom: 40rem;
+}
+.login_private {
+  font-size: 12px;
+  font-family: Verdana, Verdana-Regular;
+  font-weight: 400;
+  text-align: center;
+  color: #ffffff;
+  margin-bottom: 40rem;
+}
+.login_item_notice {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+.img_notice {
+  width: 33rem;
+}
+
+.txt_notice {
+  font-size: 13px;
+  font-family: Verdana, Verdana-Regular;
+  font-weight: 400;
+  text-align: left;
+  color: #ffffff;
+  margin-left: 10rem;
+}
+.img_elab {
+  width: 52rem;
+  height: 20rem;
+}
+.image--not-loaded{
+    /* fix ios 缺少重绘的问题,添加无意义的transform强制触发重绘 */
+    transform: scale(1);
+    filter:blur(30px);
+}
+.image--is-loaded{
+    /* fix ios 缺少重绘的问题,添加无意义的transform强制触发重绘 */
+    transform: scale(1);
+    filter:blur(20px);
+    animation: sharpen 0.8s both;
+}
+@keyframes sharpen {
+    0% {
+        filter: blur(20px);
+    }
+    100% {
+        filter: blur(0px);
+    }
+}

+ 162 - 0
src/pages/loginView/loginView.vue

@@ -0,0 +1,162 @@
+<template src="./loginView.html"></template>
+
+<script>
+import util from "@/utils/util";
+import { loginService } from "@/services";
+import { setStorage, getStorage } from "@/utils/localStorage";
+import router from "@/router";
+import store from "@/store";
+export default {
+  data() {
+    return {
+      name: "",
+      pwd: "",
+      radio: true,
+      softTest: false,
+      showLoginView: true,
+      panel: "",
+      codeText: "获取验证码",
+      checked: true,
+      timerCode: null,
+      isShow: true,
+    };
+  },
+  mounted() {
+    console.log("***login-view-mounted***");
+    // if (location.href.indexOf("?softTest") != -1) {
+    // 	//表明是软件测试链接
+    // 	this.softTest = true;
+    // } else {
+    // 	this.softTest = false;
+    // }
+    // this.getIpAddr();
+    let userInfo = getStorage("userInfoThing");
+    if (userInfo) {
+      common.userInfoHandle(JSON.parse(userInfo));
+      console.log("login-data-success:");
+      this.showLoginView = false;
+      router.push({
+        name: "index",
+      });
+    }
+  },
+  methods: {
+    // 发送验证码
+    async goSendCode() {
+      if (this.name == "") {
+        this.$message.warning("请输入手机号");
+        return false;
+      }
+      // 验证手机号
+      if (!/^[1][3,4,5,7,8,9][0-9]{9}$/.test(this.name)) {
+        this.$message.warning("请输入合法的手机号");
+        return false;
+      }
+      if (this.codeText !== "获取验证码") {
+        this.$message.warning("不可重复发送验证码,请稍后再试");
+        return false;
+      }
+      // 发送请求
+      let data = {
+        phoneNumber: this.name,
+        sign: "ELAB",
+        verifyType: 2,
+      };
+      store.state.loadingMsg="获取中";
+      const res = await requestConfig("verifyCode", data);
+      if (res.success) {
+        this.$message.success("发送成功");
+        // 处理倒计时
+        this.handleCountDown();
+      } else {
+        this.$message.error(res.message);
+      }
+    },
+    clearTimer(id) {
+      if (id) {
+        clearInterval(id);
+        id = null;
+      }
+    },
+    updateTime(e) {
+      if (e.target.currentTime > 0) {
+        this.isShow = false; // 添加模糊出现的效果
+      }
+    },
+    // 处理倒计时
+    handleCountDown() {
+      this.codeText = 120;
+      // 先清除定时器
+      this.clearTimer(this.timerCode);
+      // 设置倒计时
+      this.timerCode = setInterval(() => {
+        if (this.codeText >= 2) {
+          this.codeText--;
+        } else {
+          this.codeText = "获取验证码";
+          this.clearTimer(this.timerCode);
+        }
+      }, 1000);
+    },
+    //登录接口
+    async enter() {
+      // console.log('标签');
+      if (!this.radio) {
+        return false;
+      }
+      if (this.name == "") {
+        this.$message.warning("请输入手机号");
+        return false;
+      }
+      // 验证手机号
+      if (!/^1\d{10}$/.test(this.name)) {
+        this.$message.warning("请输入合法的手机号");
+        return false;
+      }
+      if (this.pwd == "") {
+        this.$message.warning("请输入验证码");
+        return false;
+      }
+      let data = {
+        mobile: this.name,
+        verifyCode: this.pwd,
+        platform: 3,
+      };
+      store.state.loadingMsg="登录中";
+      const res = await requestConfig("login", data);
+      if (res.success) {
+        setStorage("userInfoThing", res.single);
+        common.userInfoHandle(res.single);
+        console.log("login-data-success:");
+        this.showLoginView = false;
+        // 登录成功后.默认赋值上一次退出时选中的项目
+        let disClearKey = '';
+        for (let i = 0; i < window.localStorage.length; i++) {
+          let key = window.localStorage.key(i);
+          if (key.includes("currentProject")) {
+            disClearKey = key
+          }
+        }
+        let projectId = '';
+        if(!disClearKey) {
+          projectId = disClearKey.replace('currentProject_','')
+        }
+        let routerData = {
+          name: "index"
+        }
+        if(projectId){
+          routerData['projectId'] = projectId
+        }
+        router.push(routerData);
+        // window.$bus.$emit('loginSuccess', true);//通知登录完成了-触发底图加载和显示等其他动作
+      } else {
+        this.$message.error(res.message || "登录错误");
+      }
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+@import "./loginView.scss";
+</style>

+ 8 - 0
src/pages/mainView/mainView.html

@@ -0,0 +1,8 @@
+<div class="mainView" v-if="showMainView">
+	<!-- log组件 -->
+	<!-- <elabComponet></elabComponet> -->
+	<!-- 底图组件 -->
+	<mapComponent></mapComponent>
+
+	<router-view></router-view>
+</div>

+ 1 - 0
src/pages/mainView/mainView.scss

@@ -0,0 +1 @@
+

+ 126 - 0
src/pages/mainView/mainView.vue

@@ -0,0 +1,126 @@
+<template src="./mainView.html"></template>
+
+<script>
+	import util from "@/utils/util";
+  import {
+    setStorage,
+    getStorage, removeItem
+  } from "@/utils/localStorage";
+	import router from '@/router'
+	// import elabComponet from '@/components/elabComponet/elabComponet.vue'
+	import mapComponent from '@/components/mapComponent/mapComponent.vue'
+	// import footComponent from '@/components/footComponent/footComponent.vue'
+	// import myProjectComp from '@/components/myProjectComp/myProjectComp.vue'
+	// import addProjectComp from '@/components/addProjectComp/addProjectComp.vue'
+	// import previewComp from '@/components/previewComp/previewComp.vue'
+	// import addCompeteComp from '@/components/addCompeteComp/addCompeteComp.vue'
+
+	// import tencentAuthComponent from "@/components/tencentAuthComponent/tencentAuthComponent.vue";
+	// import createMarkLoading from '@/components/createMarkLoading/createMarkLoading.vue'
+	// import authSuccess from '@/components/authSuccess/authSuccess.vue'
+	// import openCityComp from '@/components/openCityComp/openCityComp.vue'
+	// import userNextComp from '@/components/userNextComp/userNextComp.vue'
+	export default {
+		data() {
+			return {
+				showMainView:false,
+				isShowAuthPage:false,//授权窗口展示
+				tencentAuthState:{},
+				isNext:false,
+				landId:null,	//新建地块时获知的新建地块id
+			};
+		},
+		components: {
+			mapComponent,
+		},
+		mounted() {
+            let that = this;
+			console.warn("***mounted1**5*",this.$route.query);
+            this.showMainView = true;
+            
+            window.$bus.$off('openTencentAuth')
+			// 监听授权页面
+            window.$bus.$on('openTencentAuth',(data) =>{
+                console.log('打开授权页面',data)
+                if(data && data.isShowAuthPage){
+                    if(data.state){
+                        this.tencentAuthState = data.state
+                    }
+					if(data.landId){
+					    this.landId = data.landId
+					}
+                    that.isShowAuthPage = true
+                    configTemp["page"] = data.state.page;
+                    this.isNext = data.isNext||false;
+                    setStorage('CONFIG',configTemp)
+                }else{
+                    that.isShowAuthPage = false
+                }
+            })
+			window.$bus.$on('selectedProjectItem', (project) => {
+				console.log("路由",this.$route.path,project);
+				if (project && project.id) { //存在项目地块
+					// var newurl = this.updateQueryStringParameter(window.location.href, 'projectId', project.id);
+					//向当前url添加参数
+					//路由切换项目id
+					this.$router.push({ path: this.$route.path, query: { projectId: project.id} })
+					setStorage("currentProject_"+project.id, project);
+				} else {
+					this.$router.push({ path: this.$route.path, query: { noProject: 1}})
+				}
+			});
+		},
+		methods: {
+            anthClose(){
+              this.isShowAuthPage = false;
+            },
+            /**
+             * 已授权回调
+             */
+            async alreadyAuth(param,page){
+                this.isShowAuthPage = false;
+                // 请求提交
+                window.$bus.$emit("authed", this.isNext);
+                // console.log('授权',this.tencentAuthState)
+                // if(!param || !param['authorization_code']){
+                //     return ;
+                // }
+                // let config = getStorage('CONFIG') ? JSON.parse(getStorage('CONFIG')) : '';
+                // let redirectUri = config.redirectUri
+                // let data = {
+                //     "authorizationCode": param['authorization_code'] || "",
+                //     "companyId": window.userCompanyModel.companyId,
+                //     "grantType": "authorization_code",
+                //     "redirectUri": redirectUri || "",
+                //     "refreshToken": ""
+                // }
+                // let res = await requestConfig('authCallback',data)
+            },
+
+            updateQueryStringParameter(uri, key, value) {
+              if(!value) {
+                return uri;
+              }
+              var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
+              var separator = uri.indexOf('?') !== -1 ? "&" : "?";
+              if (uri.match(re)) {
+                return uri.replace(re, '$1' + key + "=" + value + '$2');
+              }
+              else {
+                return uri + separator + key + "=" + value;
+              }
+            },
+            getNewUrl(){
+              let url = window.location.href;
+              if(url.indexOf("?")!=-1){ //判断是否存在参数
+                url = url.split('?')[0]
+              }
+              return url;
+            }
+		},
+	};
+</script>
+
+<style lang="scss" scoped>
+	@import "./mainView.scss";
+</style>

+ 35 - 0
src/router/index.js

@@ -0,0 +1,35 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+
+// import Login from '@/pages/loginView/loginView.vue'
+import mainView from '@/pages/mainView/mainView.vue'
+
+Vue.use(Router)
+const router = new Router({
+    // mode: 'history',
+    routes: [
+        // 页面初始化
+        {
+            path: '/',
+            redirect: '/pages/mainView'
+        },
+        {
+            path: '/pages/mainView',
+            name: 'mainView',
+            component: mainView
+        }
+    ],
+})
+
+router.beforeEach((to, from, next) => {
+	console.warn("router:start-1", from,to);
+	//如果存在用户账号信息|| to.query.uid
+	next();
+})
+//同一个路由跳转报错解决,NavigationDuplicated: Avoided redundant navigation to current location:
+const originalPush = Router.prototype.push
+Router.prototype.push = function push(location) {
+    return  originalPush.call(this,location).catch(err=>err)
+}
+
+export default router;

+ 93 - 0
src/services/request.js

@@ -0,0 +1,93 @@
+import store from "@/store";
+import axios from 'axios';
+import {getStorage, removeItem} from '@/utils/localStorage'
+import router from '@/router'
+var requestCount = 0; //记录下同时的请求数
+import ElementUI from 'element-ui';
+var showToast = true;
+
+axios.defaults.headers.post['elabEnvironment'] = '4'; //axios默认的请求方式,可以自己设置
+axios.defaults.headers.post['userType'] = '1000'; //axios默认的请求方式,可以自己设置
+axios.interceptors.request.use(function(config) {
+	if(config.noLoading){
+		store.dispatch('setLoading',false);//不显示loading态
+	}
+	requestCount++;//请求数+1
+	if (config.url.includes('http')) {
+		return config;
+	} else {
+		config.url = window.$config.api_url + config.url;
+		if (config.url.includes('elab-marketing-operate/mofangTest/user/login')||config.url.includes('elab-marketing-user/vcode/send/verifyCode')) {
+			config.headers['userId'] = "";
+			config.headers['ip'] = "";
+			showToast = true;
+		} else {//uploadOss 上传format文件过大时提示不成功,接口500,通过测试与header有关,注释掉上传的header就好了
+			if (!config.url.includes('elab-marketing-sms/aliyun/openapi/uploadOss')){
+				let userinfo = getStorage('userInfoThing');
+				config.headers['userId'] = userinfo ? JSON.parse(userinfo).dataUserId : '';
+				config.headers['ip'] = getStorage('ip');
+				config.headers['maiya_token'] =  getStorage('userInfoThing') ? JSON.parse(getStorage('userInfoThing')).maiya_token || "" : ""; //token
+			}
+		}
+	}
+	return config;
+}, function(error) {
+	console.log(error)
+});
+
+axios.interceptors.response.use(function(response) {
+	requestCount = requestCount - 1;
+	if (requestCount < 1) {
+		store.state.loading = false;//不显示loading状态
+	}
+	let result = response.data;
+	return result;
+}, function(error) {
+	console.log("***error***", error, requestCount)
+	requestCount = requestCount - 1;
+	if (requestCount < 1) {
+		store.state.loading = false;//不显示loading状态
+	}
+	//如果返回的状态码是401则需要返回到登录
+	if(error.response && error.response.status && error.response.status==401){
+		window.$bus.$off();//取消所有的订阅事件
+		removeItem('userInfoThing');
+		removeItem('currentConponent');
+		removeItem('setProgramComponetData');
+		for (let i = 0; i < window.localStorage.length; i++) {
+			let key = window.localStorage.key(i);
+			if (key.includes("currentProject")) {
+				removeItem(key);
+			}
+			if (key.includes("planItem")) {
+				removeItem(key);
+			}
+		}
+		window.$clearPermissionRole();//登出时重置权限里面记录的权限单元
+		store.dispatch('setCurrentProject',null);
+		router.push({
+			name: "Login"
+		});
+		if (showToast){
+			showToast = false;
+			ElementUI.Message({
+				message:"账号已失效",
+				type:"error"
+			});
+		}
+		error.response.message = "账号已失效";
+		error.response.data.message = "账号已失效";
+		// MessageBox.alert('账号已失效,无法登录', '提示', {
+		//           confirmButtonText: '确定',
+		//           callback: action => {
+		//               router.replace({
+		//                   name: 'Login',
+		//                   query: {redirect: router.currentRoute.fullPath} //登录后再跳回此页面时要做的配置
+		//               })
+		//           }
+		//       });
+	}
+	let result = error.response;
+	return result;
+});
+export default axios;

+ 84 - 0
src/services/requestConfig.js

@@ -0,0 +1,84 @@
+import store from "@/store";
+
+var doubleClickList = []; //防连击的数组对象
+// 请求地址对象
+const endpoints = {
+    upload: 'elab-marketing-system/behavior/brandMiniWeb/upload', //埋点接口
+    login: 'elab-marketing-analyse/cockpit/login', //用户登录
+
+};
+window.requestConfig = async(endpoint, options, isHideLoading = false, preventDoubleClick = false, method = 'post') => {
+    if (!endpoints.hasOwnProperty(endpoint)) {
+        console.error(`no such endpoint: ${endpoint}`);
+        return {
+            message: "不存在该接口"
+        };
+    }
+    const requestOptions = {
+        path: endpoints[endpoint],
+        data: options,
+    };
+    if (preventDoubleClick) {
+        //说明该接口需要防止连击
+        if (doubleClickList[requestOptions.path] && doubleClickList[requestOptions.path].isRunning) {
+            console.log(`${requestOptions.path}触发连击,屏蔽该请求`)
+            return
+        } else {
+            console.log(`${requestOptions.path}触发连击,通过`)
+            doubleClickList[requestOptions.path] = {
+                isRunning: true
+            }
+        }
+    }
+    console.log(`获取${requestOptions.path}请求的参数:`, requestOptions.data)
+    requestOptions.url = requestOptions.path;
+    // var t = Math.round(new Date());
+    // requestOptions.time = t;
+
+    if (!requestOptions.url.includes('/elab-marketing-user/aysn/task/byone') &&
+        !requestOptions.url.includes('elab-marketing-analyse/heavenlyEye/saleTarget/add') &&
+        !requestOptions.url.includes('elab-marketing-analyse/heavenlyEye/customer/coverPopulation') &&
+        !requestOptions.url.includes('elab-marketing-analyse/heavenlyEye/customer/intention') &&
+        !requestOptions.url.includes('elab-marketing-analyse/urbanCockpit/sky_eye_marketing/getAdCreativeDraftCheckResult') &&
+        !requestOptions.url.includes('elab-marketing-analyse/heavenlyEye/getCompareMapTotalPopulation')
+    ) {
+        store.state.loading = true; //显示loading态
+    }
+    if (isHideLoading) {
+        store.state.loading = false; //显示loading态
+    }
+    if (requestOptions.url.includes('elab-marketing-analyse/heavenlyEye/importLocations') ||
+        requestOptions.url.includes('elab-marketing-sms/aliyun/openapi/uploadOss')) {
+        requestOptions.ContentType = 'multipart/form-data'
+    }
+    if (requestOptions) {
+        let platform = (window.userInfo && window.userInfo['userAccount'] && window.userInfo['userAccount'].platform) ? window.userInfo['userAccount'].platform : ''; //TODO 要还原成‘’的
+        let currentProject = store.state.currentProject ? store.state.currentProject : null;
+        let landId = currentProject ? currentProject.id : '';
+        requestOptions.data = requestOptions.data ? requestOptions.data : {};
+        let userTypeId = window.userInfo && window.userInfo.userType ? window.userInfo.userType.id : ''; //1客户端 ,2投手端
+        if (userTypeId == 2) {
+            if (!requestOptions.data.hasOwnProperty('platform') || !requestOptions.data.platform) {
+                requestOptions.data.platform = platform
+            }
+        }
+        if (!requestOptions.data.hasOwnProperty('landId') || !requestOptions.data.landId) {
+            requestOptions.data.landId = landId
+        }
+    }
+    var response;
+    if (requestOptions.url.includes('http') || method == 'get') {
+        let params = requestOptions.data;
+        response = await axios.get(requestOptions.url, { params });
+    } else {
+        response = await axios.post(requestOptions.url, requestOptions.data);
+    }
+    //说明该接口需要防止连击
+    if (preventDoubleClick && doubleClickList[requestOptions.path] && doubleClickList[requestOptions.path]
+        .isRunning) {
+        console.log(`${requestOptions.path}连击接口已返回,清空连击数组`)
+        doubleClickList[requestOptions.path].isRunning = false
+    }
+    // console.log('返回' + requestOptions.path + '请求的结果:', response)
+    return response;
+}

+ 186 - 0
src/services/urlConfig.js

@@ -0,0 +1,186 @@
+module.exports = function(env) {
+    let WEB_CONF = {}
+    if (env === 'test') {
+        WEB_CONF = {
+            miniAppUrl: 'https://h5test.elab-plus.com/',
+            zipUrl: 'http://139.196.5.59:5307',
+            uploadUrl: 'http://101.132.138.87:5555', //文件上传
+            api_url: 'https://gatewaytest.elab-plus.vip/', //測試
+            redirect_uri: 'https://h5test1.elab-plus.com/krpano/template', // 授权回调地址
+            themeColor1: '#FFD09F',
+            themeColor2: '#FFAD5C',
+            themeColor3: '#EF863F',
+            themeColor4: '#FFDF80',
+            themeColor5: '#848EFF',
+            themeColor6: '#76BCFF',
+            themeColor7: '#85FDF0',
+            themeColor8: '#FFEDB9',
+            themeColor9: '#FFFFFF',
+            themeColor10: '#000000',
+            themeColor11: '#B4FACB',
+            themeColor12: '#4D7B5C',
+			clientId:'1112011009',
+			appId:'1758586978178079',
+            baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+        }
+    } else if (env === 'test2') {
+        WEB_CONF = {
+            miniAppUrl: 'https://h5test.elab-plus.com/',
+            zipUrl: 'http://139.196.5.59:5307',
+            uploadUrl: 'http://106.14.187.241:5555', //文件上传
+            api_url: 'https://gatewaytest1.elab-plus.com/', //測試
+            redirect_uri: 'https://h5test1.elab-plus.com/krpano/template', // 授权回调地址
+            themeColor1: '#FFD09F',
+            themeColor2: '#FFAD5C',
+            themeColor3: '#EF863F',
+            themeColor4: '#FFDF80',
+            themeColor5: '#848EFF',
+            themeColor6: '#76BCFF',
+            themeColor7: '#85FDF0',
+            themeColor8: '#FFEDB9',
+            themeColor9: '#FFFFFF',
+            themeColor10: '#000000',
+            themeColor11: '#B4FACB',
+            themeColor12: '#4D7B5C',
+			clientId:'1112011009',
+			appId:'1758586978178079',
+            baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+        }
+    } else if (env === 'test3') {
+        WEB_CONF = {
+            miniAppUrl: 'https://h5test.elab-plus.com/',
+            zipUrl: 'http://139.196.5.59:5307',
+            uploadUrl: 'http://106.14.187.241:5555', //文件上传
+            api_url: 'https://gatewaytest3.skyforestcity.com/', //測試
+            redirect_uri: 'https://h5test3.elab-plus.net/krpano/template', // 授权回调地址
+            themeColor1: '#FFD09F',
+            themeColor2: '#FFAD5C',
+            themeColor3: '#EF863F',
+            themeColor4: '#FFDF80',
+            themeColor5: '#848EFF',
+            themeColor6: '#76BCFF',
+            themeColor7: '#85FDF0',
+            themeColor8: '#FFEDB9',
+            themeColor9: '#FFFFFF',
+            themeColor10: '#000000',
+            themeColor11: '#B4FACB',
+            themeColor12: '#4D7B5C',
+			clientId:'1112011009',
+			appId:'1758586978178079',
+            baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+        }
+    } else if (env === 'test4') {
+        WEB_CONF = {
+            miniAppUrl: 'https://h5test.elab-plus.com/',
+            zipUrl: 'http://139.196.5.59:5307',
+            uploadUrl: 'http://106.14.187.241:5555', //文件上传
+            api_url: 'https://gatewaytest4.skyforestcity.com/', //測試
+            redirect_uri: 'https://h5test1.elab-plus.com/krpano/template', // 授权回调地址
+            themeColor1: '#FFD09F',
+            themeColor2: '#FFAD5C',
+            themeColor3: '#EF863F',
+            themeColor4: '#FFDF80',
+            themeColor5: '#848EFF',
+            themeColor6: '#76BCFF',
+            themeColor7: '#85FDF0',
+            themeColor8: '#FFEDB9',
+            themeColor9: '#FFFFFF',
+            themeColor10: '#000000',
+            themeColor11: '#B4FACB',
+            themeColor12: '#4D7B5C',
+            clientId:'1112011009',
+            appId:'1758586978178079',
+            baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+        }
+    } else if (env === 'dev') {
+        WEB_CONF = {
+            miniAppUrl: 'http://h5test.elab-plus.com/',
+            zipUrl: 'http://139.196.5.59:5307',
+            uploadUrl: 'http://192.168.50.104:5555', //文件上传
+            api_url: 'http://192.168.50.104:5555/', //开发
+            redirect_uri: 'https://h5test1.elab-plus.com/krpano/template', // 授权回调地址
+            themeColor1: '#FFD09F',
+            themeColor2: '#FFAD5C',
+            themeColor3: '#EF863F',
+            themeColor4: '#FFDF80',
+            themeColor5: '#848EFF',
+            themeColor6: '#76BCFF',
+            themeColor7: '#85FDF0',
+            themeColor8: '#FFEDB9',
+            themeColor9: '#FFFFFF',
+            themeColor10: '#000000',
+            themeColor11: '#B4FACB',
+            themeColor12: '#4D7B5C',
+			clientId:'1112011009',
+			appId:'1758586978178079',
+            baiduAppid:'d06f13eae4d2bc56f5fa7359784c0af9',
+        }
+    } else if (env === 'uat') {
+        WEB_CONF = {
+            miniAppUrl: 'https://mng-uat.elaber.cn/',
+            uploadUrl: 'https://api-uat.elaber.cn', //文件上传地址
+            api_url: 'https://api-uat.elaber.cn/', //堡垒 接口地址https://dm.static.elab-plus.com/Kq3t1c3IDV.txt
+            redirect_uri: 'https://mng-uat.elaber.cn/krpano/template', // 授权回调地址
+            themeColor1: '#FFD09F',
+            themeColor2: '#FFAD5C',
+            themeColor3: '#EF863F',
+            themeColor4: '#FFDF80',
+            themeColor5: '#848EFF',
+            themeColor6: '#76BCFF',
+            themeColor7: '#85FDF0',
+            themeColor8: '#FFEDB9',
+            themeColor9: '#FFFFFF',
+            themeColor10: '#000000',
+            themeColor11: '#B4FACB',
+            themeColor12: '#4D7B5C',
+            clientId:'1112013355',
+			appId:'1758979466364941',
+            baiduAppid:'9a7c9c156493ffbb48bd562112e1161a',
+        }
+    } else if (env === 'uat3') {
+        WEB_CONF = {
+            miniAppUrl: 'https://mng-uat3.elaber.cn/',
+            uploadUrl: 'https://api-uat3.elaber.cn', //文件上传地址
+            api_url: 'https://api-uat3.elaber.cn/', //堡垒 接口地址https://dm.static.elab-plus.com/Kq3t1c3IDV.txt
+            redirect_uri: 'https://mng-uat3.elaber.cn/krpano/template', // 授权回调地址
+            themeColor1: '#FFD09F',
+            themeColor2: '#FFAD5C',
+            themeColor3: '#EF863F',
+            themeColor4: '#FFDF80',
+            themeColor5: '#848EFF',
+            themeColor6: '#76BCFF',
+            themeColor7: '#85FDF0',
+            themeColor8: '#FFEDB9',
+            themeColor9: '#FFFFFF',
+            themeColor10: '#000000',
+            themeColor11: '#B4FACB',
+            themeColor12: '#4D7B5C',
+            clientId:'1112013355',
+            appId:'1758979466364941',
+            baiduAppid:'9a7c9c156493ffbb48bd562112e1161a',
+        }
+    } else if (env === 'production') {
+        WEB_CONF = {
+            miniAppUrl: 'https://dm-mng.elab-plus.com.cn/',
+            uploadUrl: 'https://dm-api.elab-plus.cn', //文件上传
+            api_url: 'https://dm-api.elab-plus.cn/', //接口地址
+            redirect_uri: 'http://city.1949plus.com', // 授权回调地址
+            themeColor1: '#FFD09F',
+            themeColor2: '#FFAD5C',
+            themeColor3: '#EF863F',
+            themeColor4: '#FFDF80',
+            themeColor5: '#848EFF',
+            themeColor6: '#76BCFF',
+            themeColor7: '#85FDF0',
+            themeColor8: '#FFEDB9',
+            themeColor9: '#FFFFFF',
+            themeColor10: '#000000',
+            themeColor11: '#B4FACB',
+            themeColor12: '#4D7B5C',
+            clientId:'1112009742',
+			appId:'1758704971288606',
+            baiduAppid:'30c97c277abecefe282aaa2ea7fa4115',
+        }
+    }
+    return WEB_CONF
+}

+ 23 - 0
src/store/actions.js

@@ -0,0 +1,23 @@
+const actions = {
+	setLoading({
+		commit
+	}, loading) {
+		commit('SET_LOADING', loading)
+	},
+	setCurrentProject({
+		commit
+	}, project) {
+		commit('SET_CURRENTPRPOJECT', project)
+	},
+	setAccount({
+		commit
+	}, account) {
+		commit('SET_ACCOUNT', account)
+	},
+	// setCityListData({
+	// 	commit
+	// }, cityListData) {
+	// 	commit('SET_CITYLISTDATA', cityListData)
+	// },
+}
+export default actions

+ 12 - 0
src/store/index.js

@@ -0,0 +1,12 @@
+import Vuex from "vuex";
+import Vue from 'vue'
+import mutations from "./mutations";
+import actions from "./actions";
+import state from './state'
+Vue.use(Vuex)
+export default new Vuex.Store({
+	state,
+	mutations,
+	actions,
+	modules: {},
+})

+ 12 - 0
src/store/mutations.js

@@ -0,0 +1,12 @@
+const mutations = {
+	SET_LOADING(state, loading) {
+		state.loading = loading
+	},
+	SET_CURRENTPRPOJECT(state, project) {
+		state.currentProject = project
+	},
+	SET_ACCOUNT(state, account) {
+		state.account = account
+	},
+}
+export default mutations;

+ 7 - 0
src/store/state.js

@@ -0,0 +1,7 @@
+const state = {
+	loading: false,
+	currentProject: null,
+	loadingMsg:"",
+	account:null,	//账号
+}
+export default state

+ 165 - 0
src/utils/command.js

@@ -0,0 +1,165 @@
+import Vue from 'vue';
+//
+// /**
+//  *  自定义指令
+//  */
+Vue.directive('title2',function (el, binding, vcode) {
+    el.title = el.innerText;
+})
+
+Vue.directive('title', {
+    // 钩子函数,被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于 document 中)。
+    inserted(el,binding,vcode){
+        el.focus()
+        el.title = el.innerText;
+        // console.log( 'inserted',el,binding,vcode );
+    },
+    // 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
+    bind(el,binding,vcode){
+        // el.title = el.innerText;
+        // console.log(el,binding,vcode);
+        // console.log( 'bind',el,binding,vcode );
+    },
+    // 所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。
+    // 指令的值可能发生了改变也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
+    update(el,binding,vcode){
+        // el.title = window.$(el).get(0).innerText;
+        // console.log( 'update',window.$(el), el,binding,vcode );
+    },
+    // 所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
+    componentUpdated( el,binding,vcode ){
+        el.title = el.innerText;
+        // console.log( 'componentUpdated',el,binding,vcode  );
+    },
+    // 只调用一次,指令与元素解绑时调用。
+    unbind(){
+        console.log( 'unbind' );
+    }
+})
+
+/**
+ * 当输入框获取到焦点时,
+ * 为 show-focus 类 所在dom ,添加边框颜色类 el-focus
+ * v-focus 指令必须和show-focus配合使用  否则无效
+ */
+Vue.directive('focus',function (el, binding, vcode) {
+    let mtinputList = el.querySelectorAll('input')
+    if(!mtinputList){
+        mtinputList = el.querySelectorAll('textarea')
+    }
+    let mtinput = null;
+    if(!binding.value){
+        mtinput = mtinputList[0]
+
+        mtinput.onfocus = function () {
+            let dom = window.$(el).parents('.show-focus');
+            if(dom.length < 1){
+                window.$(mtinput).addClass('el-focus')
+            }else{
+                dom.addClass('el-focus');
+            }
+        }
+        mtinput.onblur = function () {
+            let dom = window.$(el).parents('.show-focus');
+            if(dom.length < 1){
+                window.$(mtinput).removeClass('el-focus')
+            }else{
+                dom.removeClass('el-focus');
+            }
+        }
+
+    }else{
+        for (let i=0; i < Number(binding.value) ; i++){
+            mtinput = mtinputList[i]
+            mtinput.onfocus = function () {
+                let dom = window.$(el).parents('.show-focus');
+                dom.addClass('el-focus');
+            }
+            mtinput.onblur = function () {
+                let dom = window.$(el).parents('.show-focus');
+                dom.removeClass('el-focus');
+            }
+        }
+    }
+
+})
+
+/**
+ * 输入汉字为两个字符,英文为1个字符
+ */
+Vue.directive('limitChineseMaxlength',{
+    // 钩子函数,被绑定元素插入父节点时调用 (父节点存在即可调用,不必存在于 document 中)。
+    inserted(el,binding,vcode){
+        limitCharsFun(el,binding,vcode);
+    },
+    // 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
+    bind(el,binding,vcode){
+        limitCharsFun(el,binding,vcode);
+    },
+    // 所在组件的 VNode 更新时调用,但是可能发生在其孩子的 VNode 更新之前。
+    // 指令的值可能发生了改变也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
+    update(el,binding,vcode){
+    },
+    // 所在组件的 VNode 及其孩子的 VNode 全部更新时调用。
+    componentUpdated( el,binding,vcode ){
+        limitCharsFun(el,binding,vcode);
+    },
+    // 只调用一次,指令与元素解绑时调用。
+    unbind(){
+    }
+})
+const limitCharsFun = function (el,binding,vcode){
+    window.$(el).removeClass('is-exceed')
+    let element = el.querySelector('.el-input__count-inner');
+    let mtinputList = el.querySelectorAll('input')
+    if(!mtinputList){
+        mtinputList = el.querySelectorAll('textarea')
+    }
+    let mtinput = null;
+    mtinput = mtinputList[0]
+    let maxLength = vcode.data.attrs.maxlength;
+    if (!maxLength){
+        maxLength = 60;
+    }
+    mtinput.setAttribute('maxlength',maxLength*2)
+    // mtinput.setAttribute("style","border-color:var(--themeColor9_5)")
+    if (element){
+        element.setAttribute('style',"color:#909399")
+    }
+    let inputValue = mtinput.value || vcode.data.model.value;
+    if (common.wordLengthFilter(inputValue)> maxLength){
+        if (common.byteLengthFilter(inputValue)>maxLength * 2){
+            mtinput.value =  common.subinput(inputValue,maxLength*2);
+        }else{
+            mtinput.value =  common.subinput(inputValue,common.byteLengthFilter(inputValue));
+        }
+        mtinput.dispatchEvent(new Event("input"));//调用input事件使vue v-model绑定更新,下面相同
+    }
+    let innerText = inputValue;
+    if (element){
+        element.innerHTML = common.wordLengthFilter(innerText)+'/'+maxLength
+    }
+
+};
+
+/**
+ *图片高度根据宽高比例自适应
+ */
+Vue.directive('proportion', {
+    inserted: function (el, binding) {
+        var w = el.offsetWidth;
+        var h = w * binding.value;
+        el.style.height = h + 'px';
+        el.__resize = function () { update(el, binding); }
+        window.addEventListener('resize', el.__resize);
+    },
+
+    componentUpdated: function (el, binding) {
+        update(el, binding);
+    },
+
+    unbind: function (el) {
+        window.removeEventListener('resize', el.__resize);
+    }
+});
+

+ 294 - 0
src/utils/common.js

@@ -0,0 +1,294 @@
+import store from "@/store";
+import axios from 'axios';
+import router from "@/router";
+import {getStorage,setStorage} from "@/utils/localStorage";
+import '@/services/requestConfig.js'; //导入请求的拦截器
+// import emojiConfig from '@/components/emojiComponent/lib/js/config'
+// import Config from "@/components/emojiComponent/lib/js/config";
+var CancelToken = axios.CancelToken;
+var source = CancelToken.source();
+const common = {
+    clearMap(type = 0){//清空地图相关
+        console.log("***clearMap***",type)
+		if(!window.map){//如果不存在地图对象,则不需要往下执行清空地图的动作
+			return false;
+		}
+        if(type==1){//入股清空类型是1,则表示要清空地图上的项目信息和聚合信息-全面清空
+            window.project && window.project.clearProjecttLayer();//先清空项目地图
+        }
+        window.modulePolygon && window.modulePolygon.clearPolygonLayer();//板块图层
+        window.competition && window.competition.clearCompetitionLayer();//竞品图层
+        window.poiOperate && window.poiOperate.clearPoiLayer();           //poi图层
+        window.trafficOperate && window.trafficOperate.clearTrafficLayer();//交通路网图层
+        window.massPointOperate && window.massPointOperate.clearMassLayer();//mass点位图层
+				this.cancelPois();
+    },
+	hexToRgba(hex, opacity) {
+	    if (!hex||!opacity){
+	        return hex
+	    }
+	    let RGBA;
+	    if (hex.includes('#')&&hex.length==7){
+	        RGBA = "rgba(" + parseInt("0x" + hex.slice(1, 3)) + "," + parseInt("0x" + hex.slice(3, 5)) + "," +
+	            parseInt("0x" + hex.slice(5, 7)) + "," + opacity + ")";
+	    }else if (hex.includes('rgb(')){
+	        var values = hex
+	            .replace(/rgb?\(/, '')
+	            .replace(/\)/, '')
+	            .replace(/[\s+]/g, '')
+	            .split(',')
+	            return 'rgba(${values[0]},${values[1]},${values[2]},${opacity})'
+	    }else if(hex.includes('rgba(')){
+	        var values = hex
+	            .replace(/rgba?\(/, '')
+	            .replace(/\)/, '')
+	            .replace(/[\s+]/g, '')
+	            .split(',')
+	            return 'rgba(${values[0]},${values[1]},${values[2]},${opacity})'
+	    }else{
+	        return hex
+	    }
+	    return RGBA
+	},
+	//项目切换时触发更新用户账号以及相关逻辑
+	userProjectChangeHandle(project){
+		if(!project){
+			return false;
+		}
+		let uid = window.mapVue.$route.query.uid || '';//获取当前路由上的uid
+		//当前缓存里面的账号信息
+		let _account = null;
+		let adversiterList = project.adversiterList || [];
+		// let userInfo = window.userInfo;
+		// let _a1 = userInfo ? userInfo['userAccount'] : null;
+
+		let _a3 = (adversiterList && adversiterList[0]) ? adversiterList[0] : null;
+		//当前项目下没有账号信息
+		if(!_a3){
+			this.userAccountChange(project,_account);//则设置当前账号为空
+			return false;//同时不在往下执行
+		}
+		//如果检测存在用户账号信息
+		if(uid){
+			//当前项目中寻找这个账号
+			_account = adversiterList.find(it=>it.advertiserId == uid);
+			if(!_account){//当前项目中不存在路由中的这个账号
+				_account = _a3;//使用当前项目下的 第一个账号作为当前账号;表示切换了项目地块
+			}
+		}else{//使用当前项目下的 第一个账号作为当前账号
+			_account = _a3;
+		}
+		console.warn("***account-userAccountChange0***",_account,project,uid);
+		this.userAccountChange(project,_account)
+	},
+	//切换账号,同时更新到全局变量中
+	userAccountChange(project,account){
+		if(!account){
+			console.warn("***account-userAccountChange2***",account,project);
+			window.userInfo['userAccount'] = null;//修改当前页面的
+			return false;
+		}
+		switch(account.platform){
+			case 1:
+				account['type'] = 'tencent';
+				account['typeName'] = '腾讯';
+				break;
+			case 2:
+				account['type'] = 'huge';
+				account['typeName'] = '巨量';
+				break;
+			case 3:
+				account['type'] = 'baidu';
+				account['typeName'] = '百度';
+				break;
+			default:
+				break;
+		}
+		// if((_account && account && _account.advertiserId == account.advertiserId) || (account==null && (!_account || !_account.advertiserId))){ //账号相同,则不需要更新
+		// 	console.warn("***账号相同,则不需更新***", _account,account);
+		// }
+		// else{//执行账号切换
+
+		// }
+		account.landId = project.id;//记录下当前选中账号 所属地块-因为不同地块可能有相同账号的情况
+		userInfo['userAccount'] = account;//修改当前页面的当前账号信息
+		// setStorage("userAccount", account);//更新到缓存里面-页面跳转时使用,window对象 不能跨页使用
+		console.warn("***account-userAccountChange1***",account,project);
+		//切换账号则切换路由中的uid
+		window.mapVue.$router.push({ path: window.mapVue.$route.path, query: { uid: account.advertiserId || '' }})
+	},
+	async getLocationPOI(param) {
+		const res = await requestConfig("locationPOI", param);
+		if (res.success) {
+			if (res.single) {
+				//绘制poi
+				this.getPois(res.single);
+			}
+		}else{
+			massPointOperate.removeMassList();
+		}
+	},
+
+	async recommendLocation(param) {
+		const res = await requestConfig("recommendLocation", param);
+		if (res.success) {
+			if (res.single.poiList){
+				let list = res.single.poiList;
+				massPointOperate.removeMassList();
+				window.massPointOperate.addMassPointList(list,true);
+			}
+			if (res.single.plateInfoModel&&res.single.plateInfoModel.length>0){
+				massPointOperate.addPolygons(res.single.plateInfoModel);
+			}
+		}else{
+			massPointOperate.removeMassList();
+		}
+	},
+
+	async recommendPlanLocation(param) {
+		const res = await requestConfig("recommendPlanLocation", param);
+		if (res.success) {
+			massPointOperate.removeMassList();
+			if (res.list){
+				let list = res.list;
+				window.massPointOperate.addMassPointList(list,true);
+			}
+		}else{
+			massPointOperate.removeMassList();
+		}
+	},
+
+	// 判断是否为Mac 操作系统
+	isMacAction() {
+		return /macintosh|mac os x/i.test(navigator.userAgent);
+	},
+
+	//判断两个对象是否相等
+	isEqual(objA,objB){
+		//相等
+		if(objA === objB) return objA !== 0 || 1/objA === 1/objB;
+		//空判断
+		if(objA == null || objB == null) return objA === objB;
+		//类型判断
+		if(Object.prototype.toString.call(objA) !== Object.prototype.toString.call(objB)) return false;
+
+		switch(Object.prototype.toString.call(objA)){
+			case '[object RegExp]':
+			case '[object String]':
+				//字符串转换比较
+				return '' + objA ==='' + objB;
+			case '[object Number]':
+				//数字转换比较,判断是否为NaN
+				if(+objA !== +objA){
+					return +objB !== +objB;
+				}
+
+				return +objA === 0?1/ +objA === 1/objB : +objA === +objB;
+			case '[object Date]':
+			case '[object Boolean]':
+				return +objA === +objB;
+			case '[object Array]':
+				//判断数组
+				for(let i = 0; i < objA.length; i++){
+					if (!this.isEqual(objA[i],objB[i])) return false;
+				}
+				return true;
+			case '[object Object]':
+				//判断对象
+				let keys = Object.keys(objA);
+				for(let i = 0; i < keys.length; i++){
+					if (!this.isEqual(objA[keys[i]],objB[keys[i]])) return false;
+				}
+
+				keys = Object.keys(objB);
+				for(let i = 0; i < keys.length; i++){
+					if (!this.isEqual(objA[keys[i]],objB[keys[i]])) return false;
+				}
+
+				return true;
+			default :
+				return false;
+		}
+	},
+
+	/**
+	 * 获取字符串的字符数
+	 * @param str
+	 * @returns {number}
+	 */
+	wordLengthFilter(str){
+		let size = this.byteLengthFilter(str)
+		return Math.round(size/2)
+	},
+
+	/**
+	 * 超出最大字节数截取
+	 * @param e 原始字符串
+	 * @param maxLength 最大字节数
+	 * @returns {string} 截取后的字符串
+	 */
+	copyWritingInput(e,maxLength = 60) {
+		let s = 0;
+		e = JSON.parse(JSON.stringify(e))
+		if (e==''){
+			return e
+		}
+		let cheseReg = /[(\u4e00-\u9fa5)(\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3010|\u3011|\u007e)]+$/
+		for (var i = 0; i < e.length; i++) {
+			const code = e.charAt(i);
+			if("\n" == code){ // 换行符不算入字节
+				s += 0
+			}else if(/\s/.test(code)){
+				s += 1;
+			}else if (/^[\u0000-\u00ffA-Za-z1-9]+$/.test(code)) {
+				s += 1;
+			}else if(cheseReg.test(code)){
+				s += 2
+			}else{
+				s += 0;
+			}
+			if (s > maxLength) {
+				return e.substring(0, i);
+				// return resultStr;
+			}
+			// resultStr += code
+		}
+		return e
+	},
+
+
+	/**
+	 * 新的截取功能
+	 * @param e
+	 * @param maxLength
+	 */
+	subinput(e,maxLength = 60){
+		let s = 0;
+		e = JSON.parse(JSON.stringify(e))
+		let cheseReg = /[(\u4e00-\u9fa5)(\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3010|\u3011|\u007e)]+$/
+		for (var i = 0; i < e.length; i++) {
+			const code = e.charAt(i);
+			if("\n" == code){ // 换行符不算入字节
+				s += 0
+			}else if(/\s/.test(code)){
+				s += 1;
+			}else if (/^[\u0000-\u00ffA-Za-z1-9]+$/.test(code)) {
+				s += 1;
+			}else if(cheseReg.test(code)){
+				s += 1;
+				if (s >= maxLength) {
+					return e.substring(0, i);
+				}else {
+					s += 1;
+				}
+			}else{
+				s += 0;
+			}
+			if (s >= maxLength) {
+				return e.substring(0, i + 1);
+			}
+		}
+	}
+};
+
+export default common;

+ 317 - 0
src/utils/interface.js

@@ -0,0 +1,317 @@
+
+/**
+ * 打印错误信息
+ * @param error: 错误内容
+ */
+iError = function (error) {
+    Error.print(error);
+};
+
+/**
+ * 注册点击事件
+ * @param dom: Dom对象
+ * @param handle: 处理函数
+ * @param useCapture:冒泡顺序
+ */
+iTapEvent = function (dom, handle, useCapture) {
+    dom && dom.addEventListener.call(dom, 'click', handle, useCapture);
+};
+
+/**
+ * 取消事件冒泡
+ * @param e: 事件对象
+ */
+iCancelEvent = function (e) {
+    if (e && e.stopPropagation) {
+        e.stopPropagation();
+    } else {
+        window.event.cancelBubble = true;
+    }
+};
+
+/**
+ * 动态创建CSS
+ * @param text: CSS内容
+ */
+iCreateCss = function (text) {
+    var domStyle = document.querySelector('style');
+    var domText = document.createTextNode(text);
+
+    if (domStyle) {
+        domStyle.appendChild(domText);
+    } else {
+        var domHead = document.head || document.getElementsByTagName('head')[0];
+
+        domStyle = document.createElement('style');
+        domStyle.type = 'text/css';
+
+        domStyle.appendChild(domText);
+        domHead.appendChild(domStyle);
+    }
+};
+
+/**
+ * 判断是否为空
+ * @param str: 字符串/对象
+ * @return 是/否
+ */
+iIsEmpty = function (obj) {
+    if (obj instanceof Object) {
+        for (var k in obj) {
+            return false;
+        }
+
+        return true;
+    } else {
+        return (obj == null || obj === '');
+    }
+};
+/**
+ * 将JSON对象转换为JSON字符串
+ * @param json: JSON对象
+ * @return: JSON字符串
+ */
+iJson2Str = function (json) {
+    return JSON.stringify(json);
+};
+
+/**
+ * 将JSON字符串转换为JSON对象
+ * @param str: JSON字符串
+ * @return: JSON对象
+ */
+iStr2Json = function (str) {
+    return JSON.parse(str);
+};
+
+/**
+ * 打印日志
+ * @param content: 日志内容
+ */
+iLog = console.log.bind(console);
+/**
+ * 判断是否微信浏览器
+ */
+function isWeixinBrowser() {
+    var agent = navigator.userAgent.toLowerCase();
+    if (agent.match(/MicroMessenger/i) == 'micromessenger') {
+        return true;
+    } else {
+        return false;
+    }
+}
+/**
+ * 验证邮箱
+ * @param val: 邮箱字符串
+ * @return: true(是)/false(否)
+ */
+iIsEmail = function (val) {
+    var reg = /^([.a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/;
+    return reg.test(val);
+};
+/**
+ * 验证是否手机号码
+ * @param val: 手机号码字符串
+ * @return: true(是)/false(否)
+ */
+iIsPhone = function (val) {
+    var reg = /^1[\d]{10}$/;
+    return reg.test(val);
+};
+
+/**
+ * 验证密码
+ * @param {String} val: 密码字符串
+ * @return: {Boolean} true(是)/false(否)
+ */
+iIsPwd = function (val) {
+    var reg = /(?!^\d+$)(?!^[a-zA-Z]+$)[0-9a-zA-Z]{6,20}$/;
+    return reg.test(val);
+};
+/**
+ * 将数字字符串转换为数字
+ * @param str: 原字符串
+ * @return: 数字
+ */
+iInt = function (str) {
+    return parseInt(str, 10);
+};
+
+/**
+ * 将浮点数字符串转换为浮点数
+ * @param str: 浮点数字符串
+ * @param precision: 精度(默认:2)
+ * @return: 浮点数
+ */
+iFloat = function (str, precision) {
+    var ret = parseFloat(str);
+
+    if (precision == null) {
+        precision = 2;
+    }
+
+    ret = ret.toFixed(precision);
+    return parseFloat(ret);
+};
+
+/**
+ * 将整数格式化为指定位数的字符串
+ * @param no: 整数
+ * @param len: 位数
+ * @return: 新字符串
+ */
+iNoStr = function (no, len) {
+    var ret = String(no);
+
+    len -= ret.length;
+
+    if (len > 0) {
+        for (var i = 0; i < len; i++) {
+            ret = '0' + ret;
+        }
+    }
+
+    return ret;
+};
+/**
+ * 遍历数组/对象
+ * @param obj: 原数组/对象
+ * @param callback: 回调函数(v:值,k:对象键字符串/数组索引)
+ * @return: 回调函数返回true时的元素值
+ */
+iEach = (function () {
+    var _isArrayLike = function (obj) {
+        var length = !!obj && 'length' in obj && obj.length,
+            type = iType(obj);
+
+        if (type === 'function' || obj != null && obj === obj.window) {
+            return false;
+        }
+
+        return type === 'array' || length === 0 ||
+            typeof length === 'number' && length > 0 && (length - 1) in obj;
+    };
+
+    return function (obj, callback) {
+        var k = 0;
+
+        if (!callback) {
+            return null;
+        }
+
+        if (_isArrayLike(obj)) {
+            var len = obj.length;
+
+            for (k = 0; k < len; k++) {
+                if (callback.call(obj[k], obj[k], k)) {
+                    return obj[k];
+                }
+            }
+        } else {
+            for (k in obj) {
+                if (callback.call(obj[k], obj[k], k)) {
+                    return obj[k];
+                }
+            }
+        }
+
+        return null;
+    };
+})();
+
+/**
+ * 格式化日期字符串中的-为/
+ * @param data: 日期(时间)字符串
+ * @return: 新字符串
+ */
+iFmtDate = function (data) {
+    return data.replace(/-/g, '/');
+};
+
+/**
+ * 将日期时间对象转换为日期字符串
+ * @param date: 日期时间对象
+ * @param spt: 间隔符(默认:"-")
+ * @return: 新字符串
+ */
+iDate = function (date, spt) {
+    if (spt == null) {
+        spt = '-';
+    }
+
+    var year = date.getFullYear();
+    var month = date.getMonth() + 1;
+    var day = date.getDate();
+
+    return iNoStr(year, 4) + spt +
+        iNoStr(month, 2) + spt +
+        iNoStr(day, 2);
+};
+
+/**
+ * 将日期时间对象转换为时间字符串
+ * @param date: 日期时间对象
+ * @param spt: 间隔符(默认:":")
+ * @return: 新字符串
+ */
+iTime = function (date, spt) {
+    if (spt == null) {
+        spt = ':';
+    }
+
+    var hour = date.getHours();
+    var minute = date.getMinutes();
+    var second = date.getSeconds();
+
+    return iNoStr(hour, 2) + spt +
+        iNoStr(minute, 2) + spt +
+        iNoStr(second, 2);
+};
+
+/**
+ * 将日期时间对象转换为日期时间字符串
+ * @param date: 日期时间对象
+ * @param dateSpt: 日期间隔符(默认:"-")
+ * @param timeSpt: 时间间隔符(默认:":")
+ * @param connSpt: 日期、时间间隔符(默认:" ")
+ * @return: 新字符串
+ */
+iDateTime = function (date, dateSpt, timeSpt, connSpt) {
+    if (connSpt == null) {
+        connSpt = ' ';
+    }
+    return iDate(date, dateSpt) + connSpt +
+        iTime(date, timeSpt);
+};
+
+/**
+ * 将当前日期时间转换为日期字符串
+ * @param spt: 日期间隔符(默认:"-")
+ * @return: 新字符串
+ */
+iCurDate = function (spt) {
+    var date = new Date();
+    return iDate(date, spt);
+};
+
+/**
+ * 将当前日期时间转换为时间字符串
+ * @param spt: 时间间隔符(默认:":")
+ * @return: 新字符串
+ */
+iCurTime = function (spt) {
+    var date = new Date();
+    return iTime(date, spt);
+};
+
+/**
+ * 将当前日期时间转换为日期时间字符串
+ * @param dateSpt: 日期间隔符(默认:"-")
+ * @param timeSpt: 时间间隔符(默认:":")
+ * @param connSpt: 日期、时间间隔符(默认:" ")
+ * @return: 新字符串
+ */
+iCurDateTime = function (dateSpt, timeSpt, connSpt) {
+    var date = new Date();
+    return iDateTime(date, dateSpt, timeSpt, connSpt);
+};

+ 52 - 0
src/utils/localStorage.js

@@ -0,0 +1,52 @@
+/**
+ * set storage
+ * @param key
+ * @param value
+ */
+export function setStorage(key, value) {
+	if (!window.localStorage) {
+		throw new Error('该浏览器不支持localStorage')
+	} else {
+		if (typeof value === 'object') {
+			if (key == "brandId" || key == "accountName" || key == "accountNo" || key == "houseName" || key == "houseId") {
+				window.sessionStorage.setItem(key, window.JSON.stringify(value))
+			} else {
+				window.localStorage.setItem(key, window.JSON.stringify(value))
+			}
+		} else {
+			if (key == "brandId" || key == "accountName" || key == "accountNo" || key == "houseName" || key == "houseId") {
+				window.sessionStorage.setItem(key, value)
+			} else {
+				window.localStorage.setItem(key, value)
+			}
+		}
+	}
+}
+/**
+ * get storage
+ * @param key
+ */
+export function getStorage(key) {
+	if (!window.localStorage) {
+		throw new Error('该浏览器不支持localStorage')
+	} else {
+		if (key == "brandId" || key == "accountName" || key == "accountNo" || key == "houseName" || key == "houseId") {
+			return window.sessionStorage.getItem(key)
+		} else {
+			return window.localStorage.getItem(key)
+		}
+
+	}
+}
+/**
+ * remove by key
+ * @param key
+ */
+export function removeItem(key) {
+	window.localStorage.removeItem(key)
+}
+
+// clear all storage
+export function clearAll() {
+	window.localStorage.clear()
+}

+ 15 - 0
src/utils/rem.js

@@ -0,0 +1,15 @@
+(function(){
+	function resize(){
+		var baseFontSize = 1;
+		var designWidth = 1440;
+		var width = window.innerWidth;
+		var currentFontSize = (width/designWidth)*baseFontSize;
+		document.querySelector('html').style.fontSize = currentFontSize+'px';
+	}
+	// 页面大小发生变化时
+	window.onresize = function(){
+		resize()
+	}
+	// 文档载入时监听修改文字大小
+	document.addEventListener('DOMContentLoaded',resize)
+}())

+ 20 - 0
src/utils/resetMessage.js

@@ -0,0 +1,20 @@
+import { Message } from 'element-ui';
+let messageInstance = null;
+const resetMessage = (options) => {
+    if(messageInstance) {
+        messageInstance.close()
+    }
+    messageInstance = Message(options)
+};
+['error','success','info','warning'].forEach(type => {
+    resetMessage[type] = options => {
+        if(typeof options === 'string') {
+            options = {
+                message:options
+            }
+        }
+        options.type = type
+        return resetMessage(options)
+    }
+})
+export const message = resetMessage

+ 23 - 0
src/utils/time.js

@@ -0,0 +1,23 @@
+export function formatDate (date, fmt) {
+  if (/(y+)/.test(fmt)) {
+    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
+  }
+  let o = {
+    'M+': date.getMonth() + 1,
+    'd+': date.getDate(),
+    'h+': date.getHours(),
+    'm+': date.getMinutes(),
+    's+': date.getSeconds()
+  }
+  for (let k in o) {
+    if (new RegExp(`(${k})`).test(fmt)) {
+      let str = o[k] + ''
+      fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? str : padLeftZero(str))
+    }
+  }
+  return fmt
+}
+
+function padLeftZero (str) {
+  return ('00' + str).substr(str.length)
+}

+ 146 - 0
src/utils/util.js

@@ -0,0 +1,146 @@
+
+const util = {
+    setTitle: (title) => {
+        document.title = title;
+
+        (function (t) {
+            document.title = t;
+            var i = document.createElement('iframe');
+            i.src = '/favicon.ico';
+            i.style.display = 'none';
+            i.onload = function () {
+                setTimeout(function () {
+                    i.remove();
+                }, 9)
+            }
+            document.body.appendChild(i);
+        })(title)
+    },
+    reformParam(methodName,para) {
+        var parameter = {}
+        parameter['merchantid'] = '1'
+        parameter['version'] = '1'
+        parameter['sign_type'] = 'RSA'
+        parameter['sign'] = '123'
+        parameter['charset'] = 'UTF-8'
+        parameter['method'] = methodName
+        var context = ''
+        for(var key in para){
+            context += '&'+key+'='+para[key]
+        }
+        parameter['context'] = context
+        return parameter
+    },
+    /**
+     *
+     * @param opt
+     * view:页面名称
+     * action:操作,如点击:click
+     * label:事件描述
+     * value:资源id
+     */
+    trackEvent: (opt) => {
+      //  console.log('trackEvent')
+        if (!opt) {
+            return;
+        }
+
+        opt.view = opt.view || '';
+        opt.action = opt.action || 'click';
+        opt.label = opt.label || '';
+        opt.value = opt.value || '';
+
+        if (_czc && _czc.push) {
+            _czc.push(['_trackEvent', opt.view, opt.action, opt.label, opt.value])
+        }
+    },
+
+    trackPageview: (pathTo, pathFrom) => {
+        if (_czc && _czc.push) {
+            _czc.push(["_trackPageview", pathTo, pathFrom]);
+        }
+    },
+    accountUrl:'skyforest.tencent.TencentController.signature',
+    tokenUrl:'skyforest.mine.MineController.login.v093',
+    adviserListUrl:'skyforest.dynatown.dynatownController.getDynatownList',
+    chatUrl:'skyforest.dynatown.dynatownController.connect',
+    dateFormat(date , fmt) {
+        let ret
+        const opt = {
+            'y+': date.getFullYear().toString(), // 年
+            'M+': (date.getMonth() + 1).toString(), // 月
+            'd+': date.getDate().toString(), // 日
+            'H+': date.getHours().toString(), // 时
+            'm+': date.getMinutes().toString(), // 分
+            's+': date.getSeconds().toString(), // 秒
+            // 有其他格式化字符需求可以继续添加,必须转化成字符串
+        }
+        for (let k in opt) {
+            ret = new RegExp('(' + k + ')').exec(fmt)
+            if (ret) {
+                fmt = fmt.replace(
+                  ret[1],
+                  ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')
+                )
+            }
+        }
+        return fmt
+    },
+    formatDatetime(val,format){
+        const year = val.getFullYear();
+        const month = val.getMonth()+1;
+        const day = val.getDate();
+        const hour = val.getHours();
+        const minute = val.getMinutes();
+        const second = val.getSeconds();
+        return year+'-'+(month>9?month:'0'+month)+'-'+day+' '+hour+':'+(minute>9?minute:'0'+minute)+':'+(second>9?second:'0'+second);
+
+    },
+    formatDayTime(val){
+        const year = val.getFullYear();
+        const month = val.getMonth()+1;
+        const day = val.getDate();
+        const hour = val.getHours();
+        const minute = val.getMinutes();
+        const second = val.getSeconds();
+        return year+'-'+(month>9?month:'0'+month)+'-'+day+' '+hour+':'+(minute>9?minute:'0'+minute);
+    },
+    formatTodayTime(val){
+        const year = val.getFullYear();
+        const month = val.getMonth()+1;
+        const day = val.getDate();
+        const hour = val.getHours();
+        const minute = val.getMinutes();
+
+        if(month==new Date().getMonth()+1&&day+1==new Date().getDate()){
+            return '昨天'+hour+':'+(minute>9?minute:'0'+minute);
+        }
+        else if(month==new Date().getMonth()+1&&day==new Date().getDate()){
+
+            return hour+':'+(minute>9?minute:'0'+minute);
+        }else{
+            return year+'-'+(month>9?month:'0'+month)+'-'+day+' '+hour+':'+(minute>9?minute:'0'+minute);
+        }
+    },
+
+    /**
+     * 计算天数
+     * @param date1
+     * @param date2
+     * @returns {number}
+     * @constructor
+     */
+    getNumberOfDays(date1,date2){//获得天数
+        if(!date1 || !date2){
+            return 0;
+        }
+        //date1:开始日期,date2结束日期
+        var a1 = Date.parse(new Date(date1));
+        var a2 = Date.parse(new Date(date2));
+        var day = parseInt((a2-a1)/ (1000 * 60 * 60 * 24)) + 1;//核心:时间戳相减,然后除以天数
+        return day
+    },
+
+};
+
+export default util;

+ 220 - 0
src/vendor/Export2Excel.js

@@ -0,0 +1,220 @@
+/* eslint-disable */
+import { saveAs } from 'file-saver'
+import * as XLSX from 'xlsx'
+
+function generateArray(table) {
+  var out = [];
+  var rows = table.querySelectorAll('tr');
+  var ranges = [];
+  for (var R = 0; R < rows.length; ++R) {
+    var outRow = [];
+    var row = rows[R];
+    var columns = row.querySelectorAll('td');
+    for (var C = 0; C < columns.length; ++C) {
+      var cell = columns[C];
+      var colspan = cell.getAttribute('colspan');
+      var rowspan = cell.getAttribute('rowspan');
+      var cellValue = cell.innerText;
+      if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
+
+      //Skip ranges
+      ranges.forEach(function (range) {
+        if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
+          for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
+        }
+      });
+
+      //Handle Row Span
+      if (rowspan || colspan) {
+        rowspan = rowspan || 1;
+        colspan = colspan || 1;
+        ranges.push({
+          s: {
+            r: R,
+            c: outRow.length
+          },
+          e: {
+            r: R + rowspan - 1,
+            c: outRow.length + colspan - 1
+          }
+        });
+      };
+
+      //Handle Value
+      outRow.push(cellValue !== "" ? cellValue : null);
+
+      //Handle Colspan
+      if (colspan)
+        for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
+    }
+    out.push(outRow);
+  }
+  return [out, ranges];
+};
+
+function datenum(v, date1904) {
+  if (date1904) v += 1462;
+  var epoch = Date.parse(v);
+  return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
+}
+
+function sheet_from_array_of_arrays(data, opts) {
+  var ws = {};
+  var range = {
+    s: {
+      c: 10000000,
+      r: 10000000
+    },
+    e: {
+      c: 0,
+      r: 0
+    }
+  };
+  for (var R = 0; R != data.length; ++R) {
+    for (var C = 0; C != data[R].length; ++C) {
+      if (range.s.r > R) range.s.r = R;
+      if (range.s.c > C) range.s.c = C;
+      if (range.e.r < R) range.e.r = R;
+      if (range.e.c < C) range.e.c = C;
+      var cell = {
+        v: data[R][C]
+      };
+      if (cell.v == null) continue;
+      var cell_ref = XLSX.utils.encode_cell({
+        c: C,
+        r: R
+      });
+
+      if (typeof cell.v === 'number') cell.t = 'n';
+      else if (typeof cell.v === 'boolean') cell.t = 'b';
+      else if (cell.v instanceof Date) {
+        cell.t = 'n';
+        cell.z = XLSX.SSF._table[14];
+        cell.v = datenum(cell.v);
+      } else cell.t = 's';
+
+      ws[cell_ref] = cell;
+    }
+  }
+  if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
+  return ws;
+}
+
+function Workbook() {
+  if (!(this instanceof Workbook)) return new Workbook();
+  this.SheetNames = [];
+  this.Sheets = {};
+}
+
+function s2ab(s) {
+  var buf = new ArrayBuffer(s.length);
+  var view = new Uint8Array(buf);
+  for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
+  return buf;
+}
+
+export function export_table_to_excel(id) {
+  var theTable = document.getElementById(id);
+  var oo = generateArray(theTable);
+  var ranges = oo[1];
+
+  /* original data */
+  var data = oo[0];
+  var ws_name = "SheetJS";
+
+  var wb = new Workbook(),
+    ws = sheet_from_array_of_arrays(data);
+
+  /* add ranges to worksheet */
+  // ws['!cols'] = ['apple', 'banan'];
+  ws['!merges'] = ranges;
+
+  /* add worksheet to workbook */
+  wb.SheetNames.push(ws_name);
+  wb.Sheets[ws_name] = ws;
+
+  var wbout = XLSX.write(wb, {
+    bookType: 'xlsx',
+    bookSST: false,
+    type: 'binary'
+  });
+
+  saveAs(new Blob([s2ab(wbout)], {
+    type: "application/octet-stream"
+  }), "test.xlsx")
+}
+
+export function export_json_to_excel({
+  multiHeader = [],
+  header,
+  data,
+  filename,
+  merges = [],
+  autoWidth = true,
+  bookType = 'xlsx'
+} = {}) {
+  /* original data */
+  filename = filename || 'excel-list'
+  data = [...data]
+  data.unshift(header);
+
+  for (let i = multiHeader.length - 1; i > -1; i--) {
+    data.unshift(multiHeader[i])
+  }
+
+  var ws_name = "SheetJS";
+  var wb = new Workbook(),
+    ws = sheet_from_array_of_arrays(data);
+
+  if (merges.length > 0) {
+    if (!ws['!merges']) ws['!merges'] = [];
+    merges.forEach(item => {
+      ws['!merges'].push(XLSX.utils.decode_range(item))
+    })
+  }
+
+  if (autoWidth) {
+    /*设置worksheet每列的最大宽度*/
+    const colWidth = data.map(row => row.map(val => {
+      /*先判断是否为null/undefined*/
+      if (val == null) {
+        return {
+          'wch': 10
+        };
+      }
+      /*再判断是否为中文*/
+      else if (val.toString().charCodeAt(0) > 255) {
+        return {
+          'wch': val.toString().length * 2
+        };
+      } else {
+        return {
+          'wch': val.toString().length
+        };
+      }
+    }))
+    /*以第一行为初始值*/
+    let result = colWidth[0];
+    for (let i = 1; i < colWidth.length; i++) {
+      for (let j = 0; j < colWidth[i].length; j++) {
+        if (result[j]['wch'] < colWidth[i][j]['wch']) {
+          result[j]['wch'] = colWidth[i][j]['wch'];
+        }
+      }
+    }
+    ws['!cols'] = result;
+  }
+
+  /* add worksheet to workbook */
+  wb.SheetNames.push(ws_name);
+  wb.Sheets[ws_name] = ws;
+
+  var wbout = XLSX.write(wb, {
+    bookType: bookType,
+    bookSST: false,
+    type: 'binary'
+  });
+  saveAs(new Blob([s2ab(wbout)], {
+    type: "application/octet-stream"
+  }), `${filename}.${bookType}`);
+}

+ 28 - 0
vue.config.js

@@ -0,0 +1,28 @@
+const {
+	defineConfig
+} = require('@vue/cli-service')
+module.exports = {
+	transpileDependencies: true,
+	runtimeCompiler: true, //是否使用包含运行时编译器的 Vue 构建版本。 
+	lintOnSave: true, //是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码
+	productionSourceMap: false, //如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
+	// 注意,一旦开启则意味着启动同源策略检查,浏览器会启动CORS
+	// crossorigin: 'anonymous', //设置生成的 HTML 中 <link rel="stylesheet"> 和 <script> 标签的 crossorigin 属性。
+	publicPath: process.env.NODE_ENV !== 'development' ? './' : '/', //打包发布时的目录
+	outputDir: 'webgl', //生产环境构建文件的目录-打包时才有意义
+	assetsDir: 'static', //放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。-打包时才有意义
+	indexPath: 'index.html', //指定生成的 index.html 的输出路径 (相对于 outputDir)。也可以是一个绝对路径。-打包时才有意义
+	devServer: {
+		open: false,
+		proxy:{},
+	},
+	chainWebpack: config => {
+		config
+			.plugin('html')
+			.tap(args => {
+				args[0].title = "webgl";//定义 HTML 文档的标题
+				args[0].template = 'public/index.html';// webpack模板的地址-相对或绝对路径
+				return args
+			})
+	}
+}