zmmlet

zmmlet 查看完整档案

郑州编辑  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

不会建模的ui设计师不是一个好前端

个人动态

zmmlet 发布了文章 · 2020-02-12

geoServer + tomcat + .shp + jdk 搭建离线地图服务

对应版本和化境变量
系统windows10家庭版
jdk 1.8.0_192官网安装及环境变量添加,网上教程很多,不在赘述
tomcat 8.5.50官网
geoserver  2.16.1 GeoServer 是 OpenGIS Web 服务器规范的 J2EE 实现,利用 GeoServer 可以方便的发布地图数据,允许用户对特征数据进行更新、删除、插入操作,通过 GeoServer 可以比较容易的在用户之间迅速共享空间地理信息 由于Geoserver依赖于jdk环境和tomcat环境,所以需要先安装jdktomcat
.shp提供数据,说一下几种相关的数据格式的含义

文件名含义必要性
shp存储矢量数据的空间信息必须
shx要素几何特征的索引文件必须
dbf存储适量数据的属性信息必须
sbn/sbx存储要素空间索引的文件
fbn/fbx存储只读形状文件的功能的空间索引文件
ain/aih存储表或主题属性表中活动字段的属性索引的文件
atx为ArcCatalog中创建的每个shapefile或dBASE属性索引创建.atx文件
ixs读写shapefile的地理编码索引
mxs读写shapefile的地理编码索引(ODB)格式
prj存储坐标系信息的文件,由ArcGIS使用
xmlArcGIS的元数据-存储有关的shapefile的信息

地图由图层创建,图层大致分类点线面三类

查看jdk是否安装成功

win+R 输入 cmd 进入命令终端输入 java -version点击回车出现对应版本号说明jdk安装和环境变量配置成功
image.png

查看tomcat环境变量和简单配置

简单说一下tomcat文件夹的作用
/bin                存放启动和关闭tomcat的脚本文件
/conf              存放Tomcat服务器的各种配置文件,其中包括server.xml(Tomcat的主要配置文件)、tomcat-user.xml和web.xml等配置文件
/lib                 存放tomcat与web应用的Jar包
/logs               存放Tomcat的日志文件
/temp             存放Tomcat运行时候产生的临时文件
/webapps        当发布Web应用程序的时候,通常把Web应用程序的目录以及文件放到这个目录下
/work              Tomcat将JSP产生的Servlet源文件和字节码存放在这个文件目录下

环境变量添加

这里的变量值就是tomcat解压的文件夹路径

新建 CATALINA_BASE,变量值:D:myCodeapacheTomcat
新建 CATALINA_HOME,变量值:D:myCodeapacheTomcat
编辑 PATH,添加变量值:%CATALINA_HOME%lib;%CATALINA_HOME%bin;

查看

找到tomcat配置目录找到bin目录下的startup.bat点击运行,路径如下,
D:myCodeapacheTomcatbinstartup.bat
在浏览器中输入 http://localhost:8080/ 出现如下图页面则表示tomcat服务配置成功
Image [1].png

端口配置

tomcat默认端口为8080如果出现冲突可在tomcat-->conf-->servar.html文件中的port="8080"修改为port="8081"修改后再次重启访问即可
Image [2].png

tomcat服务启动出现乱码

找到tomcat-->conf-->logging.properties如果开始时UTF-8 就把这一行删除或者改为GBK,系统是默认是支持GBK的, 所以tomcat升级之后使用了UTF-8 和控制台不一致导致乱码,修改的后重启tomcat服务即可
Image [3].png

如果需要优化连接池配置和优化连接参数以及将tomcat注册为服务,自行百度配置,此处只是简单配置不做详细讲解

GeoServer 安装部署

方案一、下载安装包直接进行下一步,下一步,下一步选择对应的依赖即可完成,不在详细描述,着重看第二个方案

Image [4].png

方案二、下载zip源代码解压包,直接部署到tomcat里面运行geosever

Image [5].png

geoServer部署访问

众所周知tomcat是支持war包部署的,将下载的zip文件解压,把geoserver.war包拿出来扔到comcat --> webapps下,启动tomcat服务即可,由于我前面把tomcat端口修改为8081,访问时在浏览器输入`
http://127.0.0.1:8081/geoserver/web/看到如下图界面则表示geoserver部署成功,然后使用geoserve服务默认的账号密码进行登陆,默认账号admin密码geoserver`
Image [6].png

geoServer默认账号密码修改

在左侧导航中找到图中1的菜单项点击,然后点击图片中的2,最后点击账号进入新的页面
Image [7].png
将旧密码删除,设定为自己的密码,点击最下面的保存,即可
Image [8].png

geoServer新建工作区

点击工作区,点击添加新的工作区填写工作区名称,命名空间url地址,这个地址在地图发布后可以调用不同的图层,一定要填写
Image [9].png

geoServer 新建数据源

这里涉及到的数据下载会在文章最后声明
数据下载后解压将其放到tomcat --> webapps --> geoserver --> data

选择数据存储点击添加新的数据存储选择s矢量数据源下的Shapefile(.shp)格式
Image [10].png
选择工作区,填入数据源名称,选择好字符编码,字符编码应当根据数据源来定,选择对应的.shp格式文件,然后保存
Image [11].png

geoServer图层发布和图层编辑

新建数据存储保存后,出现如下图页面,点击发布
Image [12].png
发布后进行图层编辑,在下面找到定义SRS点击查找在弹框中输入4326回车选中,然后在边框中选择从数据中计算Compute from native bounds最后点击保存
Image [13].png
Image [14].png

geoServer图层预览

点击Layer Preview找到刚才保存的图层点击OpenLayers
Image [15].png
在浏览器出现如图表示一个简单的离线地图已经发布完成,如果需要发布多个图层,重复如上步骤即可
Image [16].png

geoServer图层样式

想要像一个真正的地图一样我们需要添加一些样式,当你上传的样式文件比较多时,在关联操作时将带来很大的不便,尤其当你的一个geoserver服务器中,有多达几十个图层的。因此,建议样式和图层一一对应。这样方便维护。点击Style再点击Add a new style,然后填写名称选择对应的工作区这里我们选择复制一个官方的样式,稍微修改,修改后点击Validate按钮进行校验,最后提交样式设置完成
Image [17].png

图层组的创建

众所周知,一个完整的地图服务是有很多单个图层组成的,在geoserver中,我们通过使用图层组这一功能,把单个图层组合起来,一起发布,作为一个完整的地图服务。我们在图层组中进行图层叠加和样式绑定。点击图层组添加新图层组添加名称标题填写数据地图中的边界,添加图层选择对应的图层样式,点击保存
Image [18].png
Image [19].png
图层组的预览也是在Layer Preview中,找到刚才我们添加图层组点击OpenLayers预览会发现地图样式改变了
Image [20].png
至此就是geoServer离线地图服务器搭建的全部过程,服务搭建数据来源于网络,仅供交流学习,商用请自行进行商业授权,如有不足之处欢迎指正,谢谢。
数据下载:shp数据下载

查看原文

赞 0 收藏 0 评论 0

zmmlet 收藏了文章 · 2020-01-03

轻松搭建基于 SpringBoot + Vue 的 Web 商城应用

背景介绍

首先介绍下在本文出现的几个比较重要的概念:

函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费。函数计算更多信息 参考
Fun: Fun 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算、API 网关、日志服务等资源。它通过一个资源配置文件(template.yml),协助您进行开发、构建、部署操作。Fun 的更多文档 参考
litemall 是一个基于 Spring Boot、Vue、微信小程序等技术开发的商场系统。它包括 Spring Boot 后端 + Vue 管理员前端 + 微信小程序用户前端 + Vue 商城移动端。 更多参考

本文演示如何将该商城应用的 Spring Boot 后端、Vue 管理员前端、Vue 商城移动端三个组件迁移到函数计算

下面是一个已经将到函数计算应用示例效果演示。

效果演示

管理后台效果演示

打开 http://litemall.mofangdegisn.cn 显示登陆页面:

使用默认的账户即可登陆。完成后,会进入到后台管理页面:

可以在后台管理页面添加商品类目、上架商品、用户管理、系统管理等等。

移动端轻商城效果演示

使用手机打开网址 http://litemall.mofangdegisn.cn/vue/index.html ,可以打开轻商城:

可以在轻商城中浏览商品,并将喜欢的商品添加到购物车中(暂不支持支付):

架构图

项目部署

准备工作

  1. 从 aliyun 获取基础信息: accountId 可以从安全设置页面获取、ak 信息可以从安全信息管理页面获取
  2. 下载 Fun 工具: 我们会使用 Fun 工具完成项目的部署工作。这里建议直接下载二进制可执行程序。
  3. 配置 Fun 工具: 下载完成后,执行 fun config 配置 aliyun accountId、ak 以及 region 等信息。如果域名没有备案,这里 region 只能选择海外集群。如果域名已经备案,则没有限制。
  4. 域名: 比如本文使用的 litemall.mofangdegisn.cn 域名。在域名所在的控制台添加一个 CNAME 域名解析,将记录值填写为 1911504709953557.cn-hangzhou.fc.aliyuncs.com,然后将这里的 1911504709953557 替换成自己的 accountid,cn-hangzhou 替换为自己在上一步配置的 region。
  5. Mysql: 可以是自己搭建的 MYSQL 数据库,也可以使用 aliyun RDS 数据库,准备好 MYSQL 的用户名以及密码。如果仅仅是 demo 示例,可以将 rds 白名单设置为 0.0.0.0/0,并申请外网地址,如果是非示例场景,需要为函数计算配置 VPC 访问,可以参考这里的教程配置 VPC 访问 RDS。本文的示例为 demo 性质,因此使用的是 0.0.0.0/0 的方式。

克隆项目

执行下面的命令克隆项目:

git clone git@github.com:tanhe123/litemall.git

如果没有安装 Git,也可以直接在页面点击 Downlaoad Zip 直接下载代码并解压:

为域名创建 CNAME

为我们准备好的域名,添加 CNAME 记录

导入数据库

在 MYSQL 数据库上创建一个名为 litemall 的 database,然后将 litemall-db/sql 中的 litemall_table.sql 以及 litemall_data.sql 两个文件导入到该数据库中。

如果使用的是 aliyun RDS,可以直接通过下面的方法导入:

修改 template.yml 中的配置

修改 template.yml 中的 SPRING_DATASOURCE_DRUID_URL 为数据库地址,修改 SPRING_DATASOURCE_DRUID_USERNAME 为数据库用户名,修改 SPRING_DATASOURCE_DRUID_PASSWORD 为用户名密码。

最后将 template.yml 中的域名 litemall.mofangdegisn.cn 替换为自己域名。

安装商城 Vue 管理员后端 + Vue 商城移动端的 npm 依赖

对于 linux 或者 mac,可以直接执行项目内的 ./install.sh,该命令会分别进入到 litemall-admin 以及 litemall-vue 执行 cnpm install。

编译 Java 项目并部署

假如我们要使用的域名是 http://litemall.mofangdegisn.cn ,执行以下命令:

DOMAIN=http://litemall.mofangdegisn.cn ./deploy.sh

需要将上面的域名替换为用户自己的域名,执行完毕后,完成部署。

打开配置的域名即可看到效果。

总结

通过本文介绍的技巧,我们实现了快速部署商城应用到函数计算


本文作者:tanhe123

阅读原文

本文为阿里云内容,未经允许不得转载。

查看原文

zmmlet 关注了专栏 · 2019-12-28

JEECG

一款基于代码生成器的快速开发平台!前后端分离架构 SpringBoot 2.x,Mybatis,Shiro,JWT,Vue&Ant Design。强大的代码生成器让前端和后台代码一键生成,不需要写任何代码,全栈开发福音!! 平台宗旨是提高UI能力同时,降低前后分离的开发成本,JeecgBoot还独创在线开发模式,No代码概念,一系列在线智能开发:在线配置表单、在线配置报表、在线设计流程等等。

关注 31

zmmlet 收藏了文章 · 2019-12-21

记一次 React + Koa + Mysql 构建个人博客

前言

由于一直在用 vue 写业务,为了熟悉下 react 开发模式,所以选择了 react。数据库一开始用的是 mongodb,后来换成 mysql 了,一套下来感觉 mysql 也挺好上手的。react-router、koa、mysql 都是从0开始接触开发的,期间遇到过很多问题,印象最深的是 react-router 参考官方文档配置的,楞是跑不起来,花费了好几个小时,最后才发现看的文档是v1.0, 而项目中是v4.3, 好在可参考的资料比较多,问题都迎刃而解了。

博客介绍

  • 前端项目通过 create-react-app 构建,server端通过 koa-generator 构建
  • 前后端分离,博客页、后台管理都在 blog-admin 里,对含有 /admin 的路由进行登录拦截
  • 前端: react + antd + react-router4 + axios
  • server端: koa2 + mysql + sequelize
  • 部署:server端 运行在 3000 端口,前端 80 端口,nginx设置代理

预览地址

web端源码

server端源码

喜欢或对你有帮助,欢迎 star

功能

  • [x] 登录
  • [x] 分页
  • [x] 查询
  • [x] 标签列表
  • [x] 分类列表
  • [x] 收藏列表
  • [x] 文章列表
  • [x] 发布文章时间轴
  • [x] 文章访问次数统计
  • [x] 回到顶部
  • [x] 博客适配移动端
  • [ ] 后台适配移动端
  • [ ] 对文章访问次数进行可视化
  • [ ] 留言评论
  • [ ] 渲染优化、打包优化

效果

标签

分类

收藏

文章

编辑

博客页

响应式


运行项目

前端

git clone https://github.com/gzwgq222/blog-admin.git
cd blog-admin
npm install

localhost:2019

server 端

本地安装 mysql,新建 dev 数据库

git clone https://github.com/gzwgq222/blog-server.git
cd blog-server
npm install

server 端

前端 react + antd 开发,较为平缓,在此就不再叙述。主要记录下 koa + mysql 相关事宜

全局安装 koa-generator
npm install -g koa-generato
创建 node-server 项目
koa node-server 
安装依赖
cd node-server 
npn install
运行
npm dev

出现 Hello Koa 2! 表示运行成功

先看routes文件

index.js

const router = require('koa-router')()
router.get('/', async (ctx, next) => {
  await ctx.render('index', {
    title: 'Hello Koa 2!'
  })
})
router.get('/string', async (ctx, next) => {
  ctx.body = 'koa2 string'
})
router.get('/json', async (ctx, next) => {
  ctx.body = {
    title: 'koa2 json'
  }
})
module.exports = router

users.js

const router = require('koa-router')()
router.prefix('/users')
router.get('/', function (ctx, next) {
  ctx.body = 'this is a users response!'
})
router.get('/bar', function (ctx, next) {
  ctx.body = 'this is a users/bar response'
})
module.exports = router

分别访问下列路由

localhost:3000/string
localhost:3000/users
localhost:3000/bar

大概你已经猜到了,koa-router 定义路由访问时返回相应的内容,那我们只需要把相应的 data 返回去就行了,只是我们的数据得从数据库查询出来。

本地安装 mysql

项目安裝 mysql

npm install mysql --save
项目安裝 sequelize

sequelize 是 ORM node框架,对SQL查询语句的封装,让我们可以用OOP的方式操作数据库

npm install --save sequelize
新建 sequelize.js,建立连接池
const Sequelize = require('sequelize');
const sequelize = new Sequelize('dev', 'root', '123456', {
  host: 'localhost',
  dialect: 'mysql',
  operatorsAliases: false,
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
})
sequelize
  .authenticate()
  .then(() => {
    console.log('MYSQL 连接成功......');
  })
  .catch(err => {
    console.error('链接失败:', err);
  });
// 根据模型自动创建表
sequelize.sync()
module.exports = sequelize
创建 model、controllers 文件夹 定义model:定义表结构;controller:定义对数据库的查询方法

以 tag.js 为例

model => tag.js

const sequelize = require('../sequelize ')
const Sequelize = require('sequelize')
const moment = require('moment') // 日期处理库
// 定义表结构
const tag = sequelize.define('tag', { 
  id: {
    type: Sequelize.INTEGER(11), // 设置字段类型
    primaryKey: true, // 设置为主建
    autoIncrement: true // 自增
  },
  name: {
    type: Sequelize.STRING,
    unique: { // 唯一
      msg: '已添加'
    }
  },
  createdAt: {
    type: Sequelize.DATE,
    defaultValue: Sequelize.NOW,
    get() {
      // this.getDataValue 获取当前字段value
      return moment(this.getDataValue('createdAt')).format('YYYY-MM-DD HH:mm')
    }
  },
  updatedAt: {
    type: Sequelize.DATE,
    defaultValue: Sequelize.NOW,
    get() {
      return moment(this.getDataValue('updatedAt')).format('YYYY-MM-DD HH:mm')
    }
  }
},
{
  // sequelize会自动使用传入的模型名(define的第一个参数)的复数做为表名 设置true取消默认设置
  freezeTableName: true
})
module.exports = tag

controller => tag.s 定义了 create、findAll、findAndCountAll、destroy 方法

const Tag = require('../model/tag')
const Op = require('sequelize').Op
const listAll = async (ctx) => {
  const data = await Tag.findAll()
  ctx.body = {
    code: 1000,
    data
  }
}
const list = async (ctx) => {
  const query = ctx.query
  const where = {
    name: {
      [Op.like]: `%${query.name}%`
    }
  }
  const {rows:data, count: total } = await Tag.findAndCountAll({
    where,
    offset: (+query.pageNo - 1) * +query.pageSize,
    limit: +query.pageSize,
    order: [
      ['createdAt', 'DESC']
    ]
  })
  ctx.body = {
    data,
    total,
    code: 1000,
    desc: 'success'
  }
}
const create = async (ctx) => {
  const params = ctx.request.body
  if (!params.name) {
    ctx.body = {
      code: 1003,
      desc: '标签不能为空'
    }
    return false
  }
  try {
    await Tag.create(params)
    ctx.body = {
      code: 1000,
      data: '创建成功'
    }
  }
  catch(err) {
    const msg = err.errors[0]
    ctx.body = {
      code: 300,
      data: msg.value + msg.message
    }
  }
}
const destroy = async ctx => {
  await Tag.destroy({where: ctx.request.body})
  ctx.body = {
    code: 1000,
    desc: '删除成功'
  }
}
module.exports = {
  list,
  create,
  listAll,
  destroy
在 routers 文件夹 index.js 中引入定义好的 tag controller ,定义路由
const router = require('koa-router')()
const Tag = require('../controllers/tag')
// tag
router.get('/tag/list', Tag.list)
router.get('/tag/list/all', Tag.listAll)
router.post('/tag/create', Tag.create)
router.post('/tag/destroy', Tag.destroy)
module.exports = router
/* 如每个 route 是单独的文件,可以使用 router.prefix 定义路由前缀
router.prefix('/tag')
router.get('/list', Tag.list)
router.get('/list/all', Tag.listAll)
router.post('/create', Tag.create)
router.post('/destroy', Tag.destroy)
*/

因为 app 中 已经引入 routers 中的 index.js 调用了 app.use了,所以此处不需再引入
在浏览器里输入 localhost:3000/tag/list 就可以看到返回的数据结构了,只不过 data 为空数组,因为我们还没添加进去任何数据
到这里,model 定义表结构、sequelize操作数据库、koa-router 定义路由 这一套流程算是完成了,其他表结构,接口 都是一样定义的

总结

之前没有写过 node server 和 react,算是从零搭建该博客,踩了一些坑,也学到了很多东西,譬如react 开发模式、react-router、sequelize 操作mysql的crud、koa、nginx的配置等等。

麻雀虽小,也是一次完整的前后端开发体验,脱离了浏览器的限制,像海贼王一样,打开了新世界的大门,寻找 onepiece ......

web端源码

server端源码

详细的 server 端说明

后续会在个人博客中添加关于此次部署文章

Links

初尝 react + Node,错误之处还望斧正,欢迎提 issue

查看原文

zmmlet 关注了用户 · 2019-12-21

justjavac @justjavac

会写点 js 代码

关注 14505

zmmlet 赞了文章 · 2019-12-04

前端常用的 59 个工具类【持续更新】

js-logo.jpg

前言

前端开发有时会处理一部分后台返回的数据,或者根据数据判断做一些处理; 这个时候就非常有必要将一些常用的工具类封装起来;
本文根据常用的一些工具类封装了 59 个方法,当然还有很多用的较少前期没有录入,后期持续跟新;
源码地址,utils-lan 源码地址,欢迎 star!

使用

1.方法一

npm i -S utils-lan  
import utils from 'utils-lan'  
console.log(utils.arrJudge(['1','2']))

2.方法二
git clone utils-lan 源码地址下来导入项目;

3.关于类名
是根据字面量来命名的,方法首个驼峰表示所属类型,后面是方法作用
如 arrAndSet 一看就是数组的方法,是处理交集的;
如果实在难以忍受,可以采用方法 2,导入本地对项目进行更改.
给大家推荐一款 bug 管理工具,请戳
bug 管理工具

arr

1.arrAndSet

并集

/**
 * 数组并集,只支持一维数组
 * @param {Array} arrOne
 * @param {Array} arrTwo
 */
export const arrAndSet = (arrOne, arrTwo) => {
  return arrOne.concat(arrTwo.filter(v => !arrOne.includes(v)))
}

2.arrIntersection

交集

/**
 * 数组交集,只支持一维数组
 * @param {Array} arrOne
 * @param {Array} arrTwo
 */
export const arrIntersection = (arrOne, arrTwo) => {
  return arrOne.filter(v => arrTwo.includes(v))
}

3.arrDifference

差集

/**
 * 数组差集,只支持一维数组
 * @param {Array} arrOne
 * @param {Array} arrTwo
 * eg: [1, 2, 3] [2, 4, 5] 差集为[1,3,4,5]
 */
export const arrDifference = (arrOne, arrTwo) => {
  return arrOne.concat(arrTwo).filter(v => !arrOne.includes(v) || !arrTwo.includes(v))
}

4.arrTwoToArrObj

两个数组合并成一个数组对象

/**
 * 两个数组合并成一个对象数组,考虑到复杂度,所以目前支持两个一维数组
 * @param {Array} arrOne
 * @param {Array} arrTwo
 * @param {oneKey} oneKey 选填,如果两个都未传,直接以 arrOne 的值作为 key,arrTwo 作为 value
 * @param {twoKey} twoKey
 */
export const arrTwoToArrObj = (arrOne, arrTwo, oneKey, twoKey) => {
  if(!oneKey&&!twoKey){
    return arrOne.map((oneKey, i) => ({ [oneKey]:arrTwo[i] }))
  }else{
    return arrOne.map((oneKey, i) => ({ oneKey, twoKey: arrTwo[i] }))
  }
}

5.arrObjSum

数组对象求和

/**
 * 数组对象求和
 * @param {Object} arrObj 数组对象
 * @param {String} key 数组对应的 key 值
 */
export const arrObjSum = (obj, key) => {
  return arrObj.reduce((prev, cur) => prev + cur.key, 0)
}

6.arrConcat

数组合并

/**
 * 数组合并,目前合并一维
 * @param {Array} arrOne 数组
 * @param {Array} arrTwo 数组
 */
export const arrConcat = (arrOne, arrTwo) => {
  return [...arrOne, ...arrTwo]
}

7.arrSum

数组求和

/**
 * 数组求和
 * @param {Array} arr 数组
 */
export const arrSum = arr => {
  return arr.reduce((prev, cur)=> {
    return prev + cur
  }, 0)
}

8.arrIncludeValue

数组是否包含某值

/**
 * 数组是否包含某值
 * @param {Array} arr 数组
 * @param {}  value 值,目前只支持 String,Number,Boolean
 */
export const arrIncludeValue = (arr,  value) => {
  return arr.includes( value)
}

9.arrMax

数组最大值

/**
 * 数组最大值
 * @param {Array} arr  数组
 */
export const arrMax = arr => {
  return Math.max(...arr)
}

10.arrRemoveRepeat

数组去重

/**
 * 数组去重
 * @param {Array} arr  数组
 */
export const arrRemoveRepeat = arr => {
  return Array.from(new Set(arr))
}

11.arrOrderAscend

数组排序

/**
 * 数组排序
 * @param {Array} arr  数组
 * @param {Boolean} ascendFlag   升序,默认为 true
 */
export const arrOrderAscend = (arr, ascendFlag=true) => {
  return arr.sort((a, b) => {
    return ascendFlag ? a - b : b - a
  })
}

12.arrJudge

判断是否是数组

/**
 * 判断是否是数组
 * @param {Array}} arr 数组
 */
export const arrJudge = arr => {
  if (Array.isArray(arr)) {
    return true
  }
}

check

13.checkNum

判断是否是数字

/**
 *  判断是否是数字
 * @param {Number} data
 */
export const checkNum = data => {
  const reg = /^\d{1,}$/g
  if (reg.test(data)) return true
}

14.checkLetter

判断是否是字母

/**
 *  判断是否是字母
 * @param {Number} data
 */
export const checkLetter = data => {
  const reg = /^[a-zA-Z]+$/g
  if (reg.test(data)) return true
}

15.checkLowercaseLetter

判断是否全部是小写字母

/**
 *  判断是否全部是小写字母
 * @param {Number} data
 */
export const checkLowercaseLetter = data => {
  const reg = /^[a-z]+$/g
  if (reg.test(data)) return true
}

16.checkCapitalLetter

判断是否是大写字母

/**
 *  判断是否是大写字母
 * @param {Number} data
 */
export const checkCapitalLetter = data => {
  const reg = /^[A-Z]+$/g
  if (reg.test(data)) return true
}

17.checkNumOrLetter

判断是否是字母或数字

/**
 * 判断是否是字母或数字
 * @param {Number || String} data  字符或数字
 */
export const checkNumOrLetter = data => {
  const reg = /^[0-9a-zA-Z]*$/g
  if (reg.test(data)) return true
}

18.checkChinese

判断是否是中文

/**
 * 判断是否是中文
 * @param {String} data  中文
 */
export const checkChinese = data => {
  const reg = /^[\u4E00-\u9FA5]+$/g
  if (reg.test(data)) return true
}

19.checkChineseNumberLettter

判断是否是中文,数字或字母

export const checkChineseNumberLettter = data => {
  const reg = /^[a-zA-Z0-9\u4e00-\u9fa5]+$/g
  if (reg.test(data)) return true
}

20.checkEmail

判断是否是邮箱地址

/**
 * 判断是否是邮箱地址
 * @param {String} data
 */
export const checkEmail = data => {
  const reg = /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/g
  if (reg.test(data)) return true
}

21.checkTelphone

判断是否是手机号

/**
 * 判断是否是手机号,只要是13,14,15,16,17,18,19开头即可
 * @param {String} data
 */
export const checkTelphone = data => {
  const reg = /^((\+|00)86)?1[3-9]\d{9}$/g
  if (reg.test(data)) return true
}

22.checkUrl

判断是否是正确的网址

/**
 * 判断是否是正确的网址
 * @param {String} url 网址
 */
export const checkUrl = url => {
  const a = document.createElement('a')
  a.href = url
  return [
    /^(http|https):$/.test(a.protocol),
    a.host,
    a.pathname !== url,
    a.pathname !== `/${url}`
  ].find(x => !x) === undefined
}

client

23.checkBrowser

/**
 * 判断是浏览器内核
 */
export const checkBrowser = () => {
  const u = navigator.userAgent;
  const obj = {
    trident: u.indexOf("Trident") > -1, //IE内核
    presto: u.indexOf("Presto") > -1, //opera内核
    webKit: u.indexOf("AppleWebKit") > -1, //苹果、谷歌内核
    gecko: u.indexOf("Gecko") > -1 && u.indexOf("KHTML") == -1, //火狐内核
  }
  return Object.keys(obj)[Object.values(obj).indexOf(true)]
};

24.checkIosAndroidIpad

判断是终端类型,值有ios,android,iPad

/**
 * 判断是终端类型,值有ios,android,iPad
 */
export const checkIosAndroidIpad = () => {
  const u = navigator.userAgent;
  const obj = {
    ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
    android: u.indexOf("Android") > -1 || u.indexOf("Linux") > -1, //android终端或者uc浏览器
    iPad: u.indexOf("iPad") > -1, //是否iPad
  }
  return Object.keys(obj)[Object.values(obj).indexOf(true)]
};

25.checkWeixinQqUc

判断是否是微信,qq 或 uc

/**
 * 判断是否是微信,qq 或 uc
 */
export const checkWeixinQqUc = () => {
 
  const u = navigator.userAgent;
  const obj = {
    weixin: u.indexOf("MicroMessenger") > -1, //是否微信
    qq: u.match(/QQ/i) == "qq"&&!u.indexOf('MQQBrowser') > -1, //是否QQ
    uc: u.indexOf('UCBrowser') > -1
  }
  return Object.keys(obj)[Object.values(obj).indexOf(true)]
};

26.checkIsIphoneX

检查是否是 IphoneX

/**
 * 检查是否是 IphoneX
 */
export const checkIsIphoneX = () => {
  const u = navigator.userAgent;
  const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
  if (isIOS && screen.height >= 812) {
    return true;
  }
};

file

27.fileFormatSize

格式化文件单位

/**
 * 格式化文件单位
 * @param {String || Number} size  文件大小(kb)
 */
export const fileFormatSize = size => {
  var i
  var unit = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
  for (i = 0; i < unit.length && size >= 1024; i++) {
    size /= 1024
  }
  return (Math.round(size * 100) / 100 || 0) + unit[i]
}

obj

28.objIsEqual

判断两个对象是否相等,目前只支持对象值为简单数据类型的判断

/**
 * 判断两个对象是否相等,目前只支持对象值为简单数据类型的判断
 * @param {Object} oneObj  对象
 * @param {Object} twoObj 对象
 */
export const objIsEqual = (oneObj, twoObj) => {
  return JSON.stringify(oneObj) === JSON.stringify(twoObj)
}

29.objDeepClone

对象深度克隆;
1.JSON.stringify深度克隆对象;
2.无法对函数 、RegExp等特殊对象的克隆;
3.会抛弃对象的constructor,所有的构造函数会指向Object;
4.对象有循环引用,会报错

/**
 * 对象深度克隆,
 * JSON.stringify深度克隆对象
 * 无法对函数 、RegExp等特殊对象的克隆,
 * 会抛弃对象的constructor,所有的构造函数会指向Object
 * 对象有循环引用,会报错
 * @param {Object}  obj 克隆的对象
 */
export const objDeepClone = obj => {
  return clone(obj)
}

const isType = (obj, type) => {
  if (typeof obj !== 'object') return false;
  // 判断数据类型的经典方法:
  const typeString = Object.prototype.toString.call(obj);
  let flag;
  switch (type) {
    case 'Array':
      flag = typeString === '[object Array]';
      break;
    case 'Date':
      flag = typeString === '[object Date]';
      break;
    case 'RegExp':
      flag = typeString === '[object RegExp]';
      break;
    default:
      flag = false;
  }
  return flag;
};

/**
* deep clone
* @param  {[type]} parent object 需要进行克隆的对象
* @return {[type]}        深克隆后的对象
*/
const clone = parent => {
  // 维护两个储存循环引用的数组
  const parents = []
  const children = []

  const _clone = parent => {
    if (parent === null) return null
    if (typeof parent !== 'object') return parent

    let child, proto

    if (isType(parent, 'Array')) {
      // 对数组做特殊处理
      child = []
    } else if (isType(parent, 'RegExp')) {
      // 对正则对象做特殊处理
      child = new RegExp(parent.source, getRegExp(parent))
      if (parent.lastIndex) child.lastIndex = parent.lastIndex
    } else if (isType(parent, 'Date')) {
      // 对Date对象做特殊处理
      child = new Date(parent.getTime())
    } else {
      // 处理对象原型
      proto = Object.getPrototypeOf(parent)
      // 利用Object.create切断原型链
      child = Object.create(proto)
    }

    // 处理循环引用
    const index = parents.indexOf(parent)

    if (index !== -1) {
      // 如果父数组存在本对象,说明之前已经被引用过,直接返回此对象
      return children[index]
    }
    parents.push(parent)
    children.push(child)

    for (const i in parent) {
      // 递归
      child[i] = _clone(parent[i])
    }

    return child
  }
  return _clone(parent)
}

storage

30.localStorageSet

localStorage 存贮
目前对象值如果是函数 、RegExp等特殊对象存贮会被忽略

/**
 * localStorage 存贮
 * 目前对象值如果是函数 、RegExp等特殊对象存贮会被忽略
 * @param {String} key  属性
 * @param {Object} value 值
 */
export const localStorageSet = (key, value) => {
  if (typeof (value) === 'object') value = JSON.stringify(value)
  localStorage.setItem(key, value)
}

31.localStorageGet

localStorage 获取

/**
 * localStorage 获取
 * @param {String} key  属性
 */
export const localStorageGet = (key) => {
  return JSON.parse(localStorage.getItem(key))
}

32.localStorageRemove

localStorage 移除

/**
 * localStorage 移除
 * @param {String} key  属性
 */
export const localStorageRemove = (key) => {
  localStorage.removeItem(key)
}

33.localStorageSetExpire

localStorage 存贮某一段时间失效

/**
 * localStorage 存贮某一段时间失效
 * @param {String} key  属性
 * @param {*} value 存贮值
 * @param {String} expire 过期时间,毫秒数
 */
export const localStorageSetExpire = (key, value, expire) => {
  if (typeof (value) === 'object') value = JSON.stringify(value)
  localStorage.setItem(key, value)
  setTimeout(() => {
    localStorage.removeItem(key)
  }, expire)
}

34.sessionStorageSet

sessionStorage 存贮

/**
 * sessionStorage 存贮
 * @param {String} key  属性
 * @param {*} value 值
 */
export const sessionStorageSet = (key, value) => {
  if (typeof (value) === 'object') value = JSON.stringify(value)
  sessionStorage.setItem(key, value)
}

35.sessionStorageGet

sessionStorage 获取

/**
 * sessionStorage 获取
 * @param {String} key  属性
 */
export const sessionStorageGet = (key) => {
  return JSON.parse(sessionStorage.getItem(key))
}

36.sessionStorageRemove

sessionStorage 删除

/**
 * sessionStorage 删除
 * @param {String} key  属性
 */
export const sessionStorageRemove = (key, value) => {
  sessionStorage.removeItem(key, value)
}

37.sessionStorageSetExpire

sessionStorage 存贮某一段时间失效

/**
 * sessionStorage 存贮某一段时间失效
 * @param {String} key  属性
 * @param {*} value 存贮值
 * @param {String} expire 过期时间,毫秒数
 */
export const sessionStorageSetExpire = (key, value, expire) => {
  if (typeof (value) === 'object') value = JSON.stringify(value)
  sessionStorage.setItem(key, value)
  setTimeout(() => {
    sessionStorage.removeItem(key)
  }, expire)
}

38.cookieSet

cookie 存贮

/**
 * cookie 存贮
 * @param {String} key  属性
 * @param {*} value  值
 * @param String expire  过期时间,单位天
 */
export const cookieSet = (key, value, expire) => {
  const d = new Date()
  d.setDate(d.getDate() + expire)
  document.cookie = `${key}=${value};expires=${d.toGMTString()}`
}

39.cookieGet

cookie 获取

/**
 * cookie 获取
 * @param {String} key  属性
 */
export const cookieGet = (key) => {
  const cookieStr = unescape(document.cookie)
  const arr = cookieStr.split('; ')
  let cookieValue = ''
  for (var i = 0; i < arr.length; i++) {
    const temp = arr[i].split('=')
    if (temp[0] === key) {
      cookieValue = temp[1]
      break
    }
  }
  return cookieValue
}

40.cookieRemove

cookie 删除

/**
 * cookie 删除
 * @param {String} key  属性
 */
export const cookieRemove = (key) => {
  document.cookie = `${encodeURIComponent(key)}=;expires=${new Date()}`
}

str

41.strTrimLeftOrRight

去掉字符左右空格

/**
 * 去掉字符左右空格
 * @param {String} str 字符
 */
export const strTrimLeftOrRight = str => {
  return str.replace(/(^\s*)|(\s*$)/g, "")
}

42.strInclude

判断字符是否包含某值

/**
 * 判断字符是否包含某值
 * @param {String} str 字符
 * @param {String} value 字符
 */
export const strInclude = (str, value) => {
  return str.includes(value)
}

43.strBeginWith

判断字符是否以某个字符开头

/**
 * 判断字符是否以某个字符开头
 * @param {String} str 字符
 * @param {String} value 字符
 */
export const strBeginWith = (str, value) => {
  return str.indexOf(value) === 0
}

44.strReplace

全局替换某个字符为另一个字符

/**
 * 全局替换某个字符为另一个字符
 * @param {String} str 字符
 * @param {String} valueOne 包含的字符
 * @param {String} valueTwo 要替换的字符,选填
 */
export const strReplace = (str, valueOne, valueTwo) => {
  return str.replace(new RegExp(valueOne,'g'), valueTwo)
}

45.strToCapital

将字母全部转化成大写

/**
 * 将字母全部转化成大写
 * @param {String} str 字符
 */
export const strToCapital = (str) => {
  return str.toUpperCase()
}

46.strToLowercase

将字母全部转化成小写

/**
 * 将字母全部转化成小写
 * @param {String} str 字符
 */
export const strToLowercase = (str) => {
  return str.toLowerCase()
}

47.strToCapitalLetter

将字母全部转化成以大写开头

/**
 * 将字母全部转化成以大写开头
 * @param {String} str 字符
 */
export const strToCapitalLetter = (str) => {
  const strOne = str.toLowerCase()
  return strOne.charAt(0).toUpperCase() + strOne.slice(1)
}

thrDeb

48.throttle

节流

/**
 * 节流
 * @param {*} func 执行函数
 * @param {*} delay 节流时间,毫秒
 */
export const throttle = function(func, delay) {
  let timer = null
  return function() {
    if (!timer) {
      timer = setTimeout(() => {
        func.apply(this, arguments)
        // 或者直接 func()
        timer = null
      }, delay)
    }
  }
}

49.debounce

防抖

/**
 * 防抖
 * @param {*} fn 执行函数
 * @param {*} wait 防抖时间,毫秒
 */
export const debounce = function(fn, wait) {
  let timeout = null
  return function() {
    if (timeout !== null) clearTimeout(timeout)// 如果多次触发将上次记录延迟清除掉
    timeout = setTimeout(() => {
      fn.apply(this, arguments)
      // 或者直接 fn()
      timeout = null
    }, wait)
  }
}

time

50.getYear

获取年份

/**
 * 获取年份
 */
export const getYear = () => {
  return new Date().getFullYear()
}

51.getMonth

获取月份

/**
 * 获取当前月份
 * @param {Boolean} fillFlag 布尔值,是否补 0,默认为 true
 */
export const getMonth = (fillFlag=true) => {
  const mon = new Date().getMonth() + 1
  const monRe = mon
  if (fillFlag) mon < 10 ? `0${mon}` : mon
  return monRe
}

52.getDay

获取日

/**
 * 获取日
 * @param {Boolean} fillFlag 布尔值,是否补 0
 */
export const getDay = (fillFlag=true) => {
  const day = new Date().getDate()
  const dayRe = day
  if (fillFlag) day < 10 ? `0${day}` : day
  return dayRe
}

53.getWhatDay

星期几

/**
 * 获取星期几
 */
export const getWhatDay = () => {
  return new Date().getDay() ? new Date().getDay() : 7
}

54.getMonthNum

获取当前月天数

/**
 * 获取当前月天数
 * @param {String} year 年份
 * @param {String} month 月份
 */
export const getMonthNum = (year, month) => {
  var d = new Date(year, month, 0)
  return d.getDate()
}

55.getYyMmDdHhMmSs

获取当前时间 yyyy-mm-dd,hh:mm:ss

/**
 * 获取当前时间 yyyy-mm-dd,hh:mm:ss
 */
export const getYyMmDdHhMmSs = () => {
  const date = new Date()
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hours = date.getHours()
  const minu = date.getMinutes()
  const second = date.getSeconds()
  const arr = [month, day, hours, minu, second]
  arr.forEach(item => {
    item < 10 ? '0' + item : item
  })
  return (
    year +
    '-' +
    arr[0] +
    '-' +
    arr[1] +
    ' ' +
    arr[2] +
    ':' +
    arr[3] +
    ':' +
    arr[4]
  )
}

56.timesToYyMmDd

时间戳转化为年月日

/**
 * 时间戳转化为年月日
 * @param times 时间戳
 * @param ymd 格式类型(yyyy-mm-dd,yyyy/mm/dd)
 * @param hms 可选,格式类型(hh,hh:mm,hh:mm:ss)
 * @returns {年月日}
 */
export const timesToYyMmDd = (times, ymd,  hms) => {
  const oDate = new Date(times)
  const oYear = oDate.getFullYear()
  const oMonth = oDate.getMonth() + 1
  const oDay = oDate.getDate()
  const oHour = oDate.getHours()
  const oMin = oDate.getMinutes()
  const oSec = oDate.getSeconds()
  let oTime // 最后拼接时间
  // 年月日格式
  switch (ymd) {
    case 'yyyy-mm-dd':
      oTime = oYear + '-' + getzf(oMonth) + '-' + getzf(oDay)
      break
    case 'yyyy/mm/dd':
      oTime = oYear + '/' + getzf(oMonth) + '/' + getzf(oDay)
      break
  }
  // 时分秒格式
  switch (hms) {
    case 'hh':
      oTime = ' '+oTime + getzf(oHour)
      break
    case 'hh:mm':
      oTime = oTime + getzf(oHour) + ':' + getzf(oMin)
      break
    case 'hh:mm:ss':
      oTime = oTime + getzf(oHour) + ':' + getzf(oMin) + ':' + getzf(oSec)
      break
  }
  return oTime
}

57.YyMmDdToTimes

将年月日转化成时间戳

/**
 * 将年月日转化成时间戳
 * @param {String} time yyyy/mm/dd 或yyyy-mm-dd 或yyyy-mm-dd hh:mm 或yyyy-mm-dd hh:mm:ss
 */
export const YyMmDdToTimes = (time) => {
  return new Date(time.replace(/-/g, '/')).getTime()
}

58.compareTimeOneLessTwo

/**
 *  比较时间 1 小于时间 2
 * @param {String} timeOne  时间 1
 * @param {String} timeTwo  时间 2
 */
export const compareTimeOneLessTwo = (timeOne, timeTwo) => {
  // 判断 timeOne 和 timeTwo 是否
  return new Date(timeOne.replace(/-/g, '/')).getTime()<new Date(timeTwo.replace(/-/g, '/')).getTime()
}

url

59.getQueryString

获取 url 后面通过?传参的参数~~~~

/**
 *  获取 url 后面通过?传参的参数
 * @param {String} name
 */
export function getQueryString(name) {
  const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
  const url = window.location.href
  const search = url.substring(url.lastIndexOf('?') + 1)
  const r = search.match(reg)
  if (r != null) return unescape(r[2])
  return null
}

总结

码字不易,持续更新中,欢迎 start!
给大家推荐一款 bug 管理工具,请戳
bug 管理工具

查看原文

赞 70 收藏 59 评论 13

zmmlet 关注了用户 · 2019-12-04

火狼 @huolang_5a14e07d2f2ff

vue,react,小程序,ts,php,node乱炖

关注 3194

zmmlet 关注了用户 · 2019-11-28

hfhan @hfhan

砥砺前行

关注 19590

zmmlet 赞了回答 · 2019-11-28

解决高德地图渲染问题

this指向问题,把search('北京市', function (status, result)这行的这个函数改为箭头函数

关注 2 回答 1

zmmlet 提出了问题 · 2019-11-28

解决高德地图渲染问题

地图渲染问题
1.能得到对应的经纬度和二维数组
2.能打印出GDMap不为null
3.渲染报错为:Uncaught TypeError: Cannot read property 'GDMap' of undefined

<template>
  <div class="map">
    <div id="GDMap" v-loading="loading"></div>
  </div>
</template>

<script>
import loadMap from '@/api/loadMap'
export default {
  data () {
    return {
      // 地图实例
      GDMap: null,
      // 加载的一些插件
      plugins: [
        'AMap.OverView',
        'AMap.MouseTool',
        'AMap.PolyEditor',
        'AMap.RectangleEditor',
        'AMap.PlaceSearch',
        'AMap.DistrictLayer',
        'AMap.CustomLayer',
        'AMap.DistrictSearch',
        'AMap.Polygon',
        'AMap.OverlayGroup'
      ],
      key: 'c5eac55551560531336988396dacbf53',
      v: '1.4.14',
      loading: true,
    }
  },
 mounted () {
    loadMap(this.key, this.plugins, this.v)
      .then(AMap => {
        this.GDMap = new AMap.Map('GDMap', {
          zoom: 6,
          center: [116.397428, 39.90923],
          mapStyle: 'amap://styles/dark',
          resizeEnable: true, //监控地图容器尺寸变化
        })
        this.GDMap.on('complete', () => {
          // eslint-disable-next-line no-console
          console.log('地图加载成功')
          this.loading = false
        })
        new AMap.DistrictSearch({
          extensions: 'all',
          subdistrict: 0
        }).search('北京市', function (status, result) {
          var outer = [
            new AMap.LngLat(-360, 90, true),
            new AMap.LngLat(-360, -90, true),
            new AMap.LngLat(360, -90, true),
            new AMap.LngLat(360, 90, true),
          ];
          // 完整行政区边界坐标点
          var holes = result.districtList[0].boundaries
          var pathArray = [
            outer
          ];
          pathArray.push.apply(pathArray, holes)
          var polygon = new AMap.Polygon({
            pathL: pathArray,
            strokeColor: '#00eeff',
            strokeWeight: 1,
            fillColor: '#71B3ff',
            fillOpacity: 0.5
          });
          polygon.setPath(pathArray);

      // eslint-disable-next-line no-console
      console.log(pathArray, "--PATH--")

      // 渲染地图行政区轮廓 ? 有问题
      setTimeout(() => {
        this.GDMap.add(polygon)
      }, 10000)
    })
    // eslint-disable-next-line no-console
    console.log(this.GDMap, '--GDMap--')

  })
  .catch(() => {
    // eslint-disable-next-line no-console
    console.log('地图加载失败!')
    this.loading = false
  })
},
  methods: {

  },
}
</script>

<style>
#GDMap {
  width: 1200px;
  height: 500px;
  position: relative;
}
</style>

关注 2 回答 1

认证与成就

  • 获得 19 次点赞
  • 获得 9 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 9 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2019-02-25
个人主页被 795 人浏览