本文档面向二次开发与维护,描述当前仓库的技术栈、目录结构、运行时链路、数据与地图逻辑、认证与配置,以及可扩展点。
仓库package.json中项目名为shqpgov_school_district_inquiry,与业务展示名称不一致,以页面标题「张江高新区青浦园产业地图」为准。
单页大屏类应用:在 Leaflet 二维地图 上展示青浦区 园区边界、行政区划 与 重点企业点位,两侧面板提供产业统计(ECharts)、园区列表、图层与图例控制、企业搜索与底图切换。业务数据当前以 前端静态 GeoJSON/JS 模块 为主,非实时接口驱动(「立即同步」为前端模拟)。
| 类别 | 技术 |
|---|---|
| 框架 | Vue 2.6、Vue Router 3(hash)、Vuex 3 |
| UI | Element UI 2 |
| 地图 | Leaflet 1.3.1(public/index.html 全局引入)、Esri Leaflet 3、jQuery(部分 DOM 操作) |
| 图表 | ECharts 5 |
| 空间分析 | @turf/turf 7、proj4 |
| HTTP | axios(src/utils/request.js 封装) |
| 构建 | Vue CLI 5、vue.config.js 中 publicPath: './'、打包文件名带时间戳 |
public/index.html 在打包前加载:
./static/config/config.js:定义 systemConfig、map2DViewer 等全局对象(非 ES 模块)。createAuth.js(混淆脚本,提供登录密码加密相关 AesEncryptUtil)。ak=...,callback=initialize)—— 当前业务主路径以 Leaflet 为主,需确认是否仍依赖百度回调。Vue 入口 src/main.js 将 $Coordinate(coordinate)、$Decrypt(aes.js)、$CryptoJS(实为 publicFunction.js 默认导出)、$dayjs、$proj4、$bus 挂到实例上。
Industry_map/
├── public/
│ ├── index.html # 全局脚本、Leaflet CSS/JS
│ └── static/
│ ├── config/config.js # systemConfig、地图全局 map2DViewer 等
│ ├── images/ # 大屏装饰、图例、marker 图标
│ └── plugins/ # Leaflet 插件、createAuth.js 等
├── src/
│ ├── main.js # 应用入口
│ ├── App.vue # 根组件:启动时登录
│ ├── router/index.js # 路由(实质单页)
│ ├── store/index.js # Vuex:token、用户信息、底图类型等
│ ├── views/
│ │ ├── qpjyj.vue # 【主页面】产业地图大屏布局与业务编排
│ │ ├── industryDatas.js # 企业 FeatureCollection 式数组(体积大)
│ │ ├── parkDatas.js # 园区多边形
│ │ ├── qpDivisionDatas.js # 区县边界
│ │ ├── qpStreetDatas.js # 乡镇/街道边界
│ │ └── kewei_cydt_project.js # 按统一社会信用代码扩展企业工商等字段
│ ├── components/
│ │ ├── map/appMap.vue # Leaflet 地图:底图、marker、面、Popup
│ │ └── card/ # 卡片壳、饼图、柱状图
│ ├── api/common.js # 当前仅 OAuth 登录
│ ├── utils/
│ │ ├── request.js # axios 实例、拦截器里带 token 头
│ │ ├── encrypt.js # 登录封装(调用 common.login)
│ │ ├── publicFunction.js # Turf 几何包含、面积、坐标处理等
│ │ ├── aes.js # 另一套 AES 加解密(与 encrypt 流程区分)
│ │ └── coordinate.js # 坐标相关工具
│ ├── directives/drag.js
│ └── assets/ # 全局样式、字体
├── vue.config.js # 代理 /proxy_oauth、别名 @$、@static
└── package.json
index.html 中的 config.js、createAuth.js、Leaflet 等。main.js:注册 Element UI、v-drag、无缝滚动;router.beforeEach 根据 meta.title 设置 document.title。App.vue 在 mounted 中调用 encrypt()(无参则走默认账号,见下节)。/ 与 /* 均渲染 src/views/qpjyj.vue,mode: 'hash'。qpjyj.vue 中:
<AppMap v-if="$store.state.token" ... />
即 OAuth 返回 token 写入 Vuex/localStorage 后 才挂载地图组件,避免无 token 时政务底图 URL 缺少 proxyToken。
src/utils/encrypt.js)systemConfig.defaultAccount.username(config.js 中为 user_kwyzt)与 AesEncryptUtil.getPassword()(来自 createAuth.js)调用 api.login。AesEncryptUtil.getPassword(loginObj.password) 加密密码再登录;成功则 sessionStorage.sessionUserInfo 保存明文账号信息(用于刷新页时复登)。登录接口:POST ${systemConfig.oauthServiceUrl}/user/pwd/login,表单 application/x-www-form-urlencoded,字段含 userName、password、clientId。
成功:result.code == 200 时 result.message 作为 token 存入 Vuex 与 localStorage.TOKEN,result.content 为 userInfo。
vue.config.js:
devServer.port: 2024/proxy_oauth/ → http://121.43.55.7:10086/oauth(pathRewrite 去掉前缀)生产/配置里 oauthServiceUrl 与底图域名需与部署环境一致;当前 config.js 中 oauth 为直连 IP 端口。
src/utils/request.js)config.headers.token = localStorage.getItem("TOKEN")。get、postform、postBody 等;post 函数内部引用未定义的 ls,若调用会报错——当前业务主要使用 postform(登录)。src/store/index.js 核心字段:
| state | 含义 |
|---|---|
token |
与 localStorage TOKEN 同步 |
userInfo |
登录返回内容 |
baseMapType |
底图类型枚举(与页面实际切换逻辑部分重叠) |
windowsSize |
视口宽高 |
mapMethodsCollection、treeDataCollection 等 |
预留/历史地图能力 |
year |
首页年份字符串(当前大屏主要统计未绑定该字段) |
变更:setToken、setUserState、setUserInfo。
qpjyj.vueAppMap;左侧三张 Card(产业分布汇总、产业筛选说明、图层控制);右侧 Card(饼图热度、柱状集聚程度、园区列表)。initMap)地图组件 mapInit 完成后触发 @mapInit → initMap():
qpDivisionDatas → pieaddParkPolygon('区县行政边界', item, false)。qpStreetDatas → pieaddParkPolygon('乡镇行政边界', item, false)。industryDatas,按 统一社会信用代码 与 kewei_cydt_project 合并属性(如 trd_scope 经营范围等),再 addCompanyMarker(company)。initParkDatas() 内遍历 parkDatas,用 Turf 计算包含关系与统计,绘制 所有园区范围边界,并填充 parkList;延时后默认 changePark(parkList[0])。initParkDatas)对每个园区多边形:
properties.area:通过 $CryptoJS.calculateMultiPolygonAreaInHectare(geometry) 得到公顷数文案。isGeometryAContainsGeometryB(园区, 企业点) 判断是否入园。echartsDatas:按 properties.所属产业 三类(医药器械制造、高端智能装备、新一代信息技术)计数。barEchartsDatas:按 properties.专业 映射到「规上工业」「规上服务业」「其他」(无 专业 则归为其他)。主导产业;企业数量 为饼图三项之和。切换园区 changePark:fitBounds 该园区面,并把该园区上的 echartsDatas / barEchartsDatas 赋给右侧面板图表。
search():在 industryDatas 内存数组上按所选字段 includes 关键字过滤,去重信用代码,结果列表点击 panToLocation 飞行到企业点。
checkedLegends 变化时调用 appMap.changeMarkerState(产业名, state) 控制对应分组 marker 显隐。LayerControls 中「区县/乡镇/所有园区范围边界」开关 → appMap.changeLayerControl(item),在地图侧批量 addLayer / removeLayer 面与面心文字 marker。baseMapServices 与 AppMap 内 baseMapServices 键一致:shmap_blue_web、shmap_normal_web、arcgisImagery。政务瓦片 URL 含 proxyToken= + localStorage TOKEN。
handleSync → syncData():setTimeout 2 秒模拟,成功后更新 lastSyncTime。startAutoSync(定时 30 分钟)在 mounted 中注释掉,未对接真实刷新数据接口;若二次开发对接后端,应替换 syncData 并考虑重新拉取或热更新 industryDatas 等数据源。
industrialDistributionSum 中三类企业数为 写死的展示文案(如 30 / 114 / 124),与地图统计无联动;改版时可改为由 industryDatas 聚合或接口返回。
appMap.vueL.map 中心约 [31.146..., 121.111...],minZoom 9,maxZoom 18,去掉默认 zoom 控件。loadBaseMap(activeBaseMap):L.tileLayer 或预留 wms / esriVector。zoomend:缩放 ≥15 显示企业 marker 上的 .title 文字,否则隐藏(jQuery 操作 class)。addCompanyMarker:L.divIcon 拼 HTML,图标取自 legendsTypes[所属产业].imageUrl;所属产业 必须在 legendsTypes 中有配置,否则运行时会报错。trd_scope)。this.markers[产业名][企业title] = marker。pieaddParkPolygon(title, data, toCenter):用 publicFun.latLngsToReverse2 处理坐标后 L.geoJSON,样式颜色来自 layerColor[title]。$emit('changePark', data);园区 Popup 含主导产业、企业数、parkInfo[园区名] 的简介文案(硬编码在 appMap.vue 的 parkInfo 对象)。changeLayerControl(item):根据 item.name 找到 layerControlPolygon[item.name] 下所有 key,同步切换 polygon 与 markers['polygon'][key] 标签点。
industryDatas.jsgeometry 为 Point,坐标 [lng, lat]。properties 至少包含:企业名称、企业地址、统一社会信用代码、所属产业、专业(用于柱状分类)等。kewei_cydt_project.jsuni_sc_id 与企业的 统一社会信用代码 匹配,Object.assign 合并到 properties,供 Popup 中经营范围等展示。parkDatas.jsproperties.name2 为园区展示名(与 parkInfo、列表、统计 key 一致)。qpDivisionDatas:properties.quxian 作为 title。qpStreetDatas:properties.zhenjie 作为 title。publicFunction.js)与地图强相关导出包括:
latLngsToReverse2:多级坐标数组处理(与 Leaflet GeoJSON .latLng 顺序适配有关,需与现有数据坐标系一致)。calculateMultiPolygonAreaInHectare:基于 Turf 的面积换算公顷。isGeometryAContainsGeometryB:判断企业点是否落在园区/行政面内。二次开发若更换坐标系(WGS84 / GCJ-02 / 地方坐标),需统一修正 数据 与 底图 或在此处增加纠偏。
config.js 中 lonCorrectParams / latCorrectParams 注释为 WGS84→ 上海 2000 类偏移,需在代码中确认是否被实际调用(当前 qpjyj 主路径未直接引用)。
publicPath: './':适合静态资源相对路径部署(子目录或本地文件)。configureWebpack.resolve.fallback.zlib:指向 browserify-zlib,与部分打包依赖有关。industryDatas / parkDatas 等改为 API + 前端缓存,同步按钮调用真实任务;注意 TOKEN 与跨域。legendsTypes、左侧静态数、图例 checkbox、industrialDistribution 多处硬编码不一致。config.js 中 URL 抽为环境变量或部署时注入;开发可用 proxy_oauth 同源代理。request.js 中未使用的 post / ls 引用可修复或删除以免误用。systemConfig 迁入模块并在 vue.config 中定义 ProvidePlugin 或显式 import,便于类型检查。windowsSize state,可在布局中进一步使用;地图 resize 已监听 invalidateSize。界面三套换肤由 左下角底图 决定(标准版政务 → 白天;暗蓝色政务 → 黑夜;卫星影像 → 卫星专用暗色 UI cyan,仅叠层、不改影像),主题配置 按当前模式编辑 Token;持久化见 THEME.md。
| 用途 | 路径 |
|---|---|
| 入口 | src/main.js |
| 登录与 token | src/App.vue、src/utils/encrypt.js、src/api/common.js |
| 全局配置(非打包) | public/static/config/config.js |
| 主界面 | src/views/qpjyj.vue |
| 地图 | src/components/map/appMap.vue |
| 企业数据 | src/views/industryDatas.js |
| 园区数据 | src/views/parkDatas.js |
| 工商扩展 | src/views/kewei_cydt_project.js |
| 几何工具 | src/utils/publicFunction.js |
| HTTP | src/utils/request.js |
| 主题 Token | src/utils/uiTheme.js、docs/THEME.md |
文档版本:与仓库当前代码同步整理;若后续有路由拆分、接口落地或数据迁移,请在本文件追加「变更记录」小节。