# vue-cesium-template **Repository Path**: matao_2018/vue-cesium-template ## Basic Information - **Project Name**: vue-cesium-template - **Description**: vue+cesium 项目模板 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 8 - **Forks**: 10 - **Created**: 2020-04-01 - **Last Updated**: 2025-09-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 前端 README > 其中,\* 表示部分为需严格遵守内容,其余为推荐内容。 > > 该规范使用的项目模板为 : vue-cesium-template 参考文档:[腾讯代码规范](https://tgideas.qq.com/doc/frontend/spec/common/) [凹凸实验室代码规范](https://guide.aotu.io/docs/html/note.html) [Vue 官方风格指南](https://cn.vuejs.org/v2/style-guide/index.html) #### 目录结构 ``` ├── public │ ├── images // 静态图片资源 │ ├── global.config.js // 全局配置文件 ├── src // 生产目录 │ ├── api // 统一暴露的服务接口 │ ├── assets // 所有静态资源文件 │ ├── CustomSource // Cesium 源码内容改造 │ ├── directive // Vue 自定义指令 │ ├── earth // cesium 方法封装 │ ├── router // 路由 │ ├── store // vuex状态管理器 │ ├── styles // 全局样式文件 │ ├── utils // 全局通用工具方法 │ │ ├── common.js // 通用的坐标转换类方法 │ │ ├── dataCenterBus.js // 全局Vue事件总线 │ │ ├── LocalStorage.js // localStorage 封装 │ │ ├── request.js // Axios 封装 │ │ ├── SocketPlugin.js // webSocket 封装 │ │ ├── sysRequest.js // 带登录的 Axios封装 │ │ ├── utils.js // 全局通用工具类方法 │ ├── views // view │ ├── App.vue // 入口页面 │ └── main.js // 入口 加载组件 初始化等 ├── ThirdParty // 第三方其它依赖 ├── .browserslistrc // 浏览器兼容配置 ├── .eslintignore // eslint 忽略文件配置 ├── .eslintrc.js // eslint 配置项 ├── babel.config.js // Babel 的配置文件 ├── package-lock.json // node_modules目录下所有模块的具体来源和版本号 ├── package.json // 当前项目所依赖模块的版本信息 ├── README.md // 项目说明文件 ├── vue.config.js // 打包配置文件 ``` ## 1. 项目安装及运行 > 当前项目 node 版本 14.17.1, npm 版本 6.14.13 #### 依赖包安装 > 建议采用 cnpm install, npm 安装后可能出现 报错 “Cannot find module 'imagemin-gifsicle'” ,从 node_modules 删除 image-webpack-loader 文件夹,package.json 中删除 "image-webpack-loader": "^7.0.1", 重新运行 cnpm i image-webpack-loader --save-dev 即可。 ``` npm install ``` #### 运行 ``` npm run serve ``` #### 打包 ``` npm run build ``` #### 格式化 ``` npm run lint ``` --- ## 2. 代码规范及开发风格指南 ### 2.1 代码风格 本项目使用 eslint+prettier 来统一代码风格,并设置为**保存文件时自动根据规则格式化**,eslint 规则采用字节跳动前端代码规范,所有规则均已添加注释 > 在 vscode 中先安装插件 eslint 和 prettier 本项目的风格指南主要是参照`vue`官方的 [风格指南](https://cn.vuejs.org/v2/style-guide/index.html) ### 2.2 文件命名规则 \* ##### Component vue 组件 所有的 Component 文件都是以**大写开头 (PascalCase)**,这也是官方所[推荐的](https://cn.vuejs.org/v2/style-guide/index.html#%E5%8D%95%E6%96%87%E4%BB%B6%E7%BB%84%E4%BB%B6%E6%96%87%E4%BB%B6%E7%9A%84%E5%A4%A7%E5%B0%8F%E5%86%99%E5%BC%BA%E7%83%88%E6%8E%A8%E8%8D%90)。但除了 index.vue 例子: - `@/src/components/BaseimagePicker.vue` ##### js 文件 所有的`.js`文件都遵循**横线连接 (kebab-case)** ##### views 在`views`文件下,代表路由的`.vue`文件都使用**横线连接 (kebab-case)**,代表路由的文件夹也是使用同样的规则 例子: - `@/src/views/earth-home/index.vue` 使用横线连接 (kebab-case)来命名`views`主要是出于以下几个考虑。 - 横线连接 (kebab-case) 也是官方推荐的命名规范之一[文档](https://cn.vuejs.org/v2/style-guide/index.html#%E5%8D%95%E6%96%87%E4%BB%B6%E7%BB%84%E4%BB%B6%E6%96%87%E4%BB%B6%E7%9A%84%E5%A4%A7%E5%B0%8F%E5%86%99-%E5%BC%BA%E7%83%88%E6%8E%A8%E8%8D%90) - `views`下的`.vue`文件代表的是一个路由,所以它需要和`component`进行区分(component 都是大写开头) - 页面的 url 也都是横线连接的,比如 http://localhost:8181/#/earth-home,所以路由对应的 view 应该要保持统一 - 没有大小写敏感问题 --- ### 2.3 CSS 样式 1. 本项目使用 Scss, styles/varibles.scss 中是全局样式的声明,在组件中,全部使用 scoped \*,避免样式污染,需要修改 element 样式部分可使用 /deep/ 或者 >>> 深度作用选择器,或者在组件中新增没有 scoped 的 style 代码块,外层使用类名包裹 **样式穿透** - less 使用 **/deep/** ``` 复制代码 ``` - scss 使用 **::v-deep** ``` 复制代码 ``` - stylus 使用 **>>>** ``` ``` 2. 通用样式封装: 在 styles/public.scss 进行相关通用样式封装,包含 通用 element 样式、scss 变量、样式@mixin 封装。例如: ```css //自定义滚动条样式 @mixin scrollbar-custom { overflow-y: scroll; &::-webkit-scrollbar { /*滚动条整体样式*/ width: 4px; /*高宽分别对应横竖滚动条的尺寸*/ height: 15px; } &::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ border-radius: 5px; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); background-color: rgba(63, 214, 235, 0.5); scrollbar-arrow-color: red; } &::-webkit-scrollbar-track { /*滚动条里面轨道*/ border-radius: 10px; background: transparent; } } ``` 3. **className 命名规则 \*** 我们采用 BEM 思想的变种方式,即: BEM 也就是块(block)、元素(element)、修饰符(modifier),block 表示一个模块修饰符,如 header。element 表示元素如 item 或者 li、img 这样的元素。modifier 表示修饰符 如 current 、active 这样的状态或者 它具体对应的样式 如 border、bg、color 等。 我们采用三者用下滑线连接的方式表示类,如:**.menu_item_active** , 也可以只用两个单词连接, 如 **.table_border** 或者 **.li_item** 。也可以直接使用 状态类的修饰词 直接做为类名, 如 **.active** 、 **.checked**,这类额外注意不要放在全局导致样式冲突。 > class 一些常用的修饰词 > > - 布局类:header, footer, container, main, content, aside, page, section > - 包裹类:wrap, inner > - 区块类:region, block, box > - 结构类:hd, bd, ft, top, bottom, left, right, middle, col, row, grid, span > - 列表类:list, item, field > - 主次类:primary, secondary, sub, minor > - 大小类:s, m, l, xl, large, small > - 状态类:active, current, checked, hover, fail, success, warn, error, on, off > - 导航类:nav, prev, next, breadcrumb, forward, back, indicator, paging, first, last > - 交互类:tips, alert, modal, pop, panel, tabs, accordion, slide, scroll, overlay, > - 星级类:rate, star > - 分割类:group, seperate, divider > - 等分类:full, half, third, quarter > - 表格类:table, tr, td, cell, row > - 图片类:img, thumbnail, original, album, gallery > - 语言类:cn, en > - 论坛类:forum, bbs, topic, post > - 方向类:up, down, left, right > - 其他语义类:btn, close, ok, cancel, switch; link, title, info, intro, more, icon; form, label, search, contact, phone, date, email, user; view, loading... ### 2.4 注释规范 #### 2.4.1 单行注释 \* 一般用于简单的描述,如某些状态描述、属性描述等 注释内容前后各一个空格字符,注释位于要注释代码的上面,单独占一行 _推荐:_ ```
...
``` _不推荐:_ ```
...
...
``` #### 2.4.2 模块注释 \* 一般用于描述模块的名称以及模块开始与结束的位置 注释内容前后各一个空格字符,`` 表示模块开始,`` 表示模块结束,模块与模块之间相隔一行 _推荐写法:_ ```
...
...
``` _不推荐写法:_ ```
...
...
``` #### 2.4.3 嵌套模块注释 当模块注释内再出现模块注释的时候,为了突出主要模块,嵌套模块不再使用 ``` ``` 而改用 ``` ``` 注释写在模块结尾标签底部,单独一行。 ```
...
...
``` #### 2.4.4 函数/方法注释 \* > vscode 中可使用插件 **koroFileHeader**, ctrl+alt+i 生成 文件头部注释,ctrl+alt+t 生成方法注释 **[强制] 函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。** 解释: 当 `return` 关键字仅作退出函数/方法使用时,无须对返回值作注释标识。 **[强制] 参数和返回值注释必须包含类型信息,且不允许省略参数的说明。** **[建议] 当函数是内部函数,外部不可访问时,可以使用 `@inner` 标识。** 示例: ``` /** * 函数描述 * * @param {string} p1 参数1的说明 * @param {string} p2 参数2的说明,比较长 * 那就换行了. * @param {number=} p3 参数3的说明(可选) * @return {Object} 返回值描述 */ function foo(p1, p2, p3) { var p3 = p3 || 10; return { p1: p1, p2: p2, p3: p3 }; } ``` **[强制] 对 Object 中各项的描述, 必须使用 `@param` 标识。** 示例: ``` /** * 函数描述 * * @param {Object} option 参数描述 * @param {string} option.url option项描述 * @param {string=} option.method option项描述,可选参数 */ function foo(option) { // TODO } ``` #### 2.4.5 文件注释 参照: ```js /* * @Author: mat * @Date: 2021-03-29 07:57:37 * @LastEditTime: 2021-04-14 14:23:47 * @Description: Cesium 相关工具方法,包含坐标转换、定位等 */ ``` 2.4.6 复杂对象注释 参照: ```js /** * 服务器 * * @typedef {Object} namespaceA~Server * @property {string} host 主机 * @property {number} port 端口 */ ``` ### 2.5 Vue 项目中的代码规范 1. v-for 设置 key 值 \* 2. 避免 v-if 和 v-for 用一起 \* 3. 组件使用方式 \* ```vue ``` 4. props 的定义尽量详尽, 例如类型、必填项、默认值、校验规则 \* ```js props: { status: { type: String, required: true, default: '' } } ``` 5. 所有的 vue 项目,统一使用路由懒加载。例如:\* ```js { path: '/login', name: 'login', component: () => import('@/views/home/login') }, ``` 6. 组件文件中必须包含 name,name 必须是由多个单词组成,并且是驼峰形式 \* 7. 页面中样式尽量写在``中,避免引起多页面样式被覆盖。 \* 8. 覆盖饿了么组件样式时,统一加上父元素 class。 \* 9. this 复制统一使用 `let that = this`。\* 10. vue 中变量定义声明用 let 或 const。\* 11. 静态资源引用使用绝对路径 , 例如:background: url('/images/weather/menu-bg.png'); \* 12. 全局公用组件及方法的引用 推荐这样:\* ```js import { addIconMarker, removeAllIconMarker, addBoundInfoBox } from 'E/common' import { getRadarImgages, getRadarPm25Images, getDataGisImg } from 'A/weather' config.resolve.alias = { '@': resolve('src'), V: resolve('src/views'), C: resolve('src/components'), U: resolve('src/utils'), E: resolve('src/earth'), A: resolve('src/api'), } ``` 13. 组件选项顺序 \* ```vue export default { name: '', mixins: [], components: {}, props: {}, data() {}, computed: {}, watch: {}, created() {}, mounted() {}, destroyed() {}, methods: {} } ``` ### 2.6 其他规范: 1. **职责单一 ** \* 任何时候尽量是的一个函数就做一件事情,而不是将各种逻辑全部耦合在一起,提高单个函数的复用性和可读性 每个页面都会在加载完成时进行数据的请求并展示到页面 ``` created() { this.init(); }, methods: { // 将全部的请求行为聚合在init函数中 // 将每个请求单独拆分 init() { this.getList1() this.getList2() }, getList1() { // to do ... }, getList2() { // to do ... } } ``` 2. **策略模式** \* 策略模式的使用,避免过多的`if else`判断,也可以替代简单逻辑的`switch` ``` const formatDemandItemType = (value) => { switch (value) { case 1: return '基础' case 2: return '高级' case 3: return 'VIP' } } // 策略模式 const formatDemandItemType2 = (value) => { const obj = { 1: '基础', 2: '高级', 3: 'VIP', } return obj[value] } ``` ## 3. 请求封装 \* 本项目在 **utils/request.js** 中对 **axios** 进行简单封装,在 api 文件夹下对各个模块的接口进行单独声明,在组件中使用时先引入 ``` import {dbfslInfo, dbfslEntity} from '@/api/fsjc.js' ``` 后使用 ``` dbfslInfo().then(res => { console.log(res) }) ``` 如项目中有登录,需要在请求时在请求头添加 token 的,可参考如下封装 ``` import axios from 'axios' import { MessageBox, Message } from 'element-ui' import store from '@/store' import { getToken } from '@/utils/auth' // create an axios instance const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url // withCredentials: true, // send cookies when cross-domain requests timeout: 5000 // request timeout }) // request interceptor service.interceptors.request.use( config => { // do something before request is sent if (store.getters.token) { // let each request carry token // ['X-Token'] is a custom headers key // please modify it according to the actual situation config.headers['X-Token'] = getToken() } return config }, error => { // do something with request error console.log(error) // for debug return Promise.reject(error) } ) // response interceptor service.interceptors.response.use( /** * If you want to get http information such as headers or status * Please return response => response */ /** * Determine the request status by custom code * Here is just an example * You can also judge the status by HTTP Status Code */ response => { const res = response.data // if the custom code is not 20000, it is judged as an error. if (res.code !== 20000) { Message({ message: res.message || 'Error', type: 'error', duration: 5 * 1000 }) // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // to re-login MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { confirmButtonText: 'Re-Login', cancelButtonText: 'Cancel', type: 'warning' }).then(() => { store.dispatch('user/resetToken').then(() => { location.reload() }) }) } return Promise.reject(new Error(res.message || 'Error')) } else { return res } }, error => { console.log('err' + error) // for debug Message({ message: error.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } ) export default service ``` > 建议: view 中组件的结构可自行组织,建议将可共用的组件放在 components,类似像 BaseimagePicker.vue (底图选择组件) ## 4.Cesium 相关 \* 项目中 考虑 代码结构的低耦合性及复用性,将**Cesium**相关代码 统一在**earth**文件夹下,其中 - **index.js** 包含**cesium** 初始化相关方法 > 初始化、基本数据加载调用、全局事件声明,在 cesium 初始化组件中调用 - **utils.js** 包含**Cesium** 相关工具方法,包含坐标转换、定位等 > 世界坐标、地理坐标、屏幕坐标相互转换,弧度计算,距离计算,定位,WGS84、GCj02 坐标转换,获取视角对应层级,获取中心点坐标,度分秒转换 等相关方法 - **common.js** 包含**Cesium** 相关公用方法封装 > 图标、文字、模型、扫描波、风场、线、原生 entity、自定义信息框、geojson 等数据加载、聚合等相关方法 - **tool 文件夹** 中包含 其余工具类方法: 淹没分析、坡度坡向分析、罗盘 等 - 其余业务相关代码 在 earth 文件夹中新建对应文件夹 ![image-20210527140253391](C:\Users\mat\AppData\Roaming\Typora\typora-user-images\image-20210527140253391.png) ## 5. 项目相关的地址配置、地图服务配置放在 global.config.js 中 > 放弃环境变量的方式存储 是因为打包后无法做地址修改,得重新打包。放弃 json 文件配置是因为 json 中不方便书写注释。