英雄管理系统

项目要求

a.注册页要有验证码,账号重复、密码重复、验证码错误要提示
b.登录页面用户名和密码要正确,不正确要提示
c.进入主页面,显示查找、显示新增、头像、姓名、技能、操作(编辑和删除)
d.点击查找可以快速找到列表中的信息,没有信息要显示
e.编辑和新增包括姓名、技能、头像、保存
f.点击删除,删除的头像、姓名、技能、操作(编辑和删除)在后端保存,不能够真正的删除(软删除)
g.页面要求简洁、美观、大方

项目代码下载

英雄管理系统(完善)下载地址

实现效果展示

  • 总体效果
  • 注册页面
  • 登录界面
  • 查找界面
  • 新添界面
  • 编辑界面
  • 删除界面

项目准备阶段

  • 首先,我们要从王者荣耀官网上爬取一定数量的内容,为之后做准备爬取王者荣耀.js
  • 导包

const express = require(“express”);
const hm = require(“mysql-ithm”);
const cors = require(“cors”);
const multer = require(“multer”);
var bodyParser = require(“body-parser”);
var svgCaptcha = require(‘svg-captcha’); //验证码插件
const cookieSession = require(“cookie-session”);

  • 连接数据库
hm.connect({host: 'localhost',//数据库地址port: '3306',user: 'root',//用户名,没有可不填password: '123',//密码,没有可不填database: 'cqmanager503'//数据库名称
});
  • 创建英雄模型和用户模型
// 英雄模型
let heroModel = hm.model("hero", {heroName: String,heroSkill: String,heroIcon: String,isDelete: String,
});
// 用户模型
let userModel = hm.model('users', {username: String,password: String
});
  • 托管静态资源
app.use(express.static('www'));
app.use(express.static('uploads'));
app.use(express.static('static'));
  • 配置中间件
app.use(cors());
// 4.1 body-parser:解析post参数,给req添加属性body,存储解析好的post参数
app.use(bodyParser.urlencoded({ extended: false }));
// 4.4 cookie-session中间件:给req添加session成员
app.use(cookieSession({name: 'session',keys: ['1', '2'],//加密(盐)// 有效期maxAge: 7 * 24 * 60 * 60 * 1000 // 7*24 hours
}));
  • 开启服务器
app.listen(4399, () => {console.log('服务器开启成功');
});

参数说明

  • API接口
接口说明 URL 请求方式 请求参数 返回值
查询英雄列表 /hero/list get search :英雄名称,不传返回所有 [heros:{英雄列表}]
查询英雄详情 /hero/info get id:英雄id {data:英雄详情}
编辑英雄 /hero/update post name,skill, icon,id {code: 200)
删除英雄 /hero/delete post id {code: 200)
新增英雄 /hero/add post name,skill, icon {code: 200)
验证码 /captcha get 验证码图片
用户注册 /user/register post username, password, code:验证码 {code:200|401|402}
用户登录 /user/login post username, password {code:200|401|402}
退出登录 /logout get
  • 服务器
服务器说明 作用描述
http://127.0.0.1:4399 服务器基地址
200 请求成功状态码
401 用户名已存在或者用户名错误
402 密码错误或者验证码错误
500 服务器内部错误
302 服务器重定向

服务端流程

查询英雄列表

请求并且判断是否传入参数

  • 没有传入查询参数

    • 要查询所有的英雄

      • 判断是否查询到

        • 查询到

          • 返回服务器内部错误
        • 没有查询到
          • 返回内部
  • 有传入查询参数
    • 模糊查询,还有一个并且语法 and isDelete = ‘false’

      • 判断是否查询到

        • 查询到

          • 返回服务器内部错误
        • 没有查询到
          • 返回内部
// 5.1 查询英雄列表(查询没有删除所有的英雄)
app.get('/hero/list', (req, res) => {// (1) 请求let { search } = req.query;//console. log(search);//有查询参数就是有值的,没有查询参数就是undefined.// b.判断// (2) 处理(查询数据库)if (!search) {//如果进到这里来了, 说明没有查询参数,我就要查询出所有的英雄。heroModel.find('isDelete="false" ',(err, results) => {if (err) {res.send({code: 500,msg: '服务器内部错误'});} else {// (3) 响应res.send({code: 200,heros: results})}});} else {// 如果有search,则根据条件查询数据(包含查询)heroModel.find(`heroname like "%${search}%" and isDelete="false"`, (err, results) => {if (err) {res.send({code: 500,msg: '服务器内部错误'});} else {// (3) 响应res.send({code: 200,heros: results})}});}
});

新增英雄

这里需要用到 multer 模块
app.post(’/profile’, upload.single(‘avatar’), function (req, res, next) {
    // req.file is the avatar file
    // req.body will hold the text fields, if there were any
})

  • 这里需要接收用户新增的英雄名,英雄技能,英雄头像
  • 将接受到的参数插入到数据库中
    • 判断是否接受到

      • 接收到

        • 返回新增成功
      • 没有接收到
        • 返回服务器内部错误
// 5.5 新增英雄
app.post("/hero/add", upload.single("heroIcon"), (req, res) => {//a.接收用户新增的英雄名,英雄技能,英雄头像let { heroName, heroSkill, isDelete = "false" } = req.body;let heroIcon = req.file.filename;//b.插入到数据库中heroModel.insert({ heroName, heroSkill, heroIcon, isDelete },(err, results) => {if (err) {res.send({code: 500,msg: "服务器内部错误" + err,});} else {res.send({code: 200,msg: "新增成功",});}});
});

根据 ID 查询英雄详情

  • 接收传递过来的英雄ID
  • 根据id查询英雄的详细信息
    • 判断查询信息

      • 没有错误,且有数据

        • 则返回data: results[0]
      • 有错误
        • 返回服务器内部错误
      • 无错误,但没有英雄
        • 返回没有此英雄,或已被删除!
// 5.2 查询英雄的详情(编辑的第一步:根据ID查询,显示到编辑页)
app.get("/hero/info", (req, res) => {// a. 接收传递过来的英雄IDlet { id } = req.query;// b.根据id查询英雄的详细信息heroModel.find(`id=${id} and isDelete="false"`, (err, results) => {if (err == null && results.length != 0) {res.send({code: 200,data: results[0],});} else if (err) {res.send({code: 500,mgs: "服务器内部错误"});} else {res.send({code: 201,mgs: "没有此英雄,或已被删除!",});}});
});

英雄编辑

  • 判断是否修改了头像

    • 修改了头像

      • obj 对象里面就有id, heroName,heroSkill , heroIcon
    • 没有修改头像
      • obj 对象里面就只有id,heroName, heroSkill

这里要调用一下mysq1-ithm模块,使用其中的方法吧数据更新带数据库中

  • 判断是否更新到数据库

    • 更新了

      • 返回修改成功
    • 没有更新
      • 返回服务器内部错误
// 5.3 编辑英雄
app.post("/hero/update", upload.single("heroIcon"), (req, res) => {//如果不改头像,只改名字和技能.我们希望这种需求也是可以的。//赋值let { id, heroName, heroSkill } = req.body;let obj = {heroName,heroSkill,};//如果修改了头像,那obj对象里面就有id, heroName,heroSkill , heroIcon//如果没有修改头像,那obj对象里面就只有id,heroName, heroSkillif (req.file != undefined) {//能够进到这里来 ,说明传了修改后的头像进来。obj.heroIcon = 'http://127.0.0.1:4399/' + req.file.filename;}//调用mysq1-ithm模块中的方法,把数据更新到数据库中.heroModel.update(`id=${id}`, obj, (err, results) => {if (err) {res.send({code: 500,msg: "服务器内部错误"});} else {res.send({code: 200,msg: "修改成功",});}});
});

英雄删除(软删除)

实际上修改的是当前id的英雄isDelete为true

  • 接收前端传递过来的要删除的英雄id
  • 调用mysql-ithm模块中的方法,来完成
    • 判断是否删除英雄(改为true)

      • isDelete为true

        • 返回删除成功
      • isDelete不为true
        • 返回服务器内部错误
// 5.4 删除英雄(软删除,实际上修改的是当前id的英雄isDelete为true)
app.post("/hero/delete", (req, res) => {// a.接收前端传递过来的要删除的英雄idlet  { id } = req.body;//b.调用mysql-ithm模块中的方法,来完成heroModel.update(`id=${id}`, { isDelete: "true" }, (err, results)=> {if (err) {res.send({code: 500,msg: "服务器内部错误"});} else {res.send({code: 200,msg: "删除成功"});}});
});

验证码

利用 svg-captcha :验证码插件(因为不是每个地方都会用到,不需要像中间件那样要用app.use())

  • 创建一个验证码
  • 返回验证码(实际上就是一个svg格式的图片)
  • 响应给客户端
// 5.6 验证码
// svg-captcha:验证码插件(因为不是每个地方都会用到,不需要像中间件那样要用app.use())
// (2)声明全局变量存储验证码文本
//b.搞一个全局变量来保存一下这个验证码文字
let captchaText = '';
//c.使用
app.get('/captcha', (req, res) => {// //创建一个验证码var captcha = svgCaptcha.create();// console.log(captcha);// 文本:服务器存起来用于注册接口验证//返回验证码captchaText = captcha.text;// 图片:响应给客户端// 返回验证码,实际上就是一个svg格式的图片res.type('svg');res.status(200).send(captcha.data);
});

用户注册

  • 获取前端传递过来的用户名/加密的密码/验证码
  • 验证验证码输入的是否正确
    • 不正确

      • 返回验证码错误
    • 正确
      • 判断用户名是否已经被注册

        • 无法判断

          • 返回服务器内部错误-查询用户名是否存在
        • 可以判断
          • 如果用户名存在

            • 返回用户名已存在
          • 如果用户名不存在
            • 判断是否接受

              • 接受到

                • 返回注册成功
              • 无法接受
                • 返回服务器内部错误-注册时错误

常用的加密方式

// 5.7 用户注册
app.post("/user/register", (req, res) => {//a.获取前端传递过来的用户名/加密的密码/验证码let { username, password, code } = req.body;console.log(username, password, code);//b.验证验证码输入的是否正确.if (code.toLocaleLowerCase() != captchaText.toLocaleLowerCase()) {res.send({code: 402,msg: "验证码错误",});} else {//进到这里来了, 说明验证码是对的,那就要开始注册了.//要不要去数据库中判断一下以前这个用户名是否已经被注册了?userModel.find(`username="${username}"`, (err, results) => {if (err) {res.send({code: 500,msg: "服务器内部错误-查询用户名是否存在",});} else {//说明可以查询成功,但是还要看看查出来有没有结果.if (results.length > 0) {// 用户名是否存在res.send({code: 401,msg: "用户名已存在",});} else {//该用户名不存在,不存在就往册呀(增加/插入操作)userModel.insert({username,password,}, (err, results) => {// 注册时的错误判断if (err) {res.send({code: 500,msg: "服务器内部错误-注册时错误'",});} else {res.send({code: 200,msg: "注册成功",});}});}}});}
});

用户登录

  • 先获取用户登录时候,传递过来的用户名和加密后的密码
  • 去数据库中判断有没有这样的账号和密码.
    • 判断是否查询成功

      • 查询失败

        • 返回服务器内部错误
      • 查询成功
        • 返回是否有数据

          • 有数据

            • 返回登录成功
          • 没有数据
            • 返回账号或密码错误
// 5.8 用户登录
app.post("/user/login", (req, res) => {//a.先获取用户登录时候,传递过来的用户名和加密后的密码let { username, password } = req.body;//b.去数据库中判断有没有这样的账号和密码.userModel.find(`username="${username}" and password="${password}"`, (err, results) => {//判断if (err) {res.send({code: 500,msg: "服务器内部错误",});} else {//判断查成功的结果,有没有数据if (results.length > 0) {// 发送的session的键是user,值是一个对象,对象里面包含账号密码.req.session.user = { username, password };res.send({code: 200,msg: "登录成功",});} else {res.send({code: 401,msg: "账号或密码错误",});}}});
});

检测是否登录

  • 判断是否登录

    • 登录了

      • 响应回去的就是有内容的
    • 没有登录
      • 响应回去的就是没有内容的
// 5.0 判断有没有登录
app.get("/isLogin", (req, res) => {//如果你登录了, 那你响应回去的就是有内容的.//如果你没有登录,那你响应回去的就是没有内容的.res.send(req.session.user);
});

退出登录

  • 清除session
  • 使用重定向技术刷新首页
// 5.9 退出登录
app.get('/logout', (req, res) => {// (1) 清除sessionreq.session = null;// (2) 使用重定向技术刷新首页res.writeHead(302, {Location: './login.html'});res.end();
});

客户端流程

查询英雄列表

  • 获取传递过来的英雄id
  • 发送ajax请求
  • 对应的信息显示在对应的页面标签上,
//  一、根据ID发送Ajax请求,获取详细信息 并显示在页面标签上
//1. 获取传递过来的英雄id
var id = window.location.search.split('=')[1]
//2.发送ajax请求
$.ajax({url: 'http://127.0.0.1:4399/hero/info',type: 'get',data: { id },success: function (backData) {//对应的信息显示在对应的页面标签上,if (backData.code == 200) {$('#id').val(id)//隐藏域存放id$('#name').val(backData.data.heroName)$('#skill').val(backData.data.heroSkill)$('#iconImg').attr('src', backData.data.heroIcon)}}
})

新增英雄

  • 图片预览

    • 获取用户选择的图片
    • 创建一个url
    • 把url赋值给预览用的img的src属性
  • 完成新增
    • 给新增按钮设置一个点击事件
    • 去掉默认提交行为
    • 创建一个FormData对象,获取新增的英雄的信息(名字,技能,头像)
    • 发送ajax请求
    • 跳转首页
// 入口函数
$(function () {// 1. 图片预览$('#icon').on('change', function () {// 1. 获取用户选择的图片var file = this.files[0]// 2. 创建一个urlvar url = URL.createObjectURL(file)// 3. 把url赋值给预览用的img的src属性$('#iconImg').attr('src', url)})// 2. 完成新增//1.给新增按钮设置一个点击事件$('.btn-insert').on('click', function (e) {//2.去掉默认提交行为e.preventDefault()//3.创建一个FormData对象,获取新增的英雄的信息(名字,技能,头像)// var fd = new FormData(document.querySelector('form'))var fd = new FormData($('#form')[0])//form表单是dom元素,form表单中需要获取数据的标签都应该有name属性并且name属性的值应该和接口参数值一致//4.发送ajax请求.$.ajax({url:'http://127.0.0.1:4399/hero/add',type:'post',dataType:'json',data:fd,contentType: false,processData: false,success: function(backData){console.log(backData);if (backData.code==200) {alert('新增成功');// 跳转首页window.location.href='./index.html';}}});})
})

根据 ID 查询英雄详情

  • 给查询按钮设置一个点击事件
  • 去掉默认的提交行为
  • 获取用户输入的要查询的关键词
  • 发送ajax请求,获取数据
  • 通过模板引擎渲染页面
//二:查询符合条件(英雄名包含查询关键词)的所有英雄
//1.给查询按钮设置一个点击事件.
$('#searchBtn').on('click', function (e) {//2.去掉默认的提交行为e.preventDefault()//3.获取用户输入的要查询的关键词let search = $('#search').val().trim()//4.发送ajax请求,获取数据$.ajax({type: 'get',url: 'http://127.0.0.1:4399/hero/list',data: { search },success: function (backData) {// console.log(backData);if(backData.heros.length == 0){$('tbody'). html ('没有数据');return;}if(backData.code == 200){//5.通过模板引擎渲染// 调用模板引擎渲染页面var resHtml = template('cq',backData);$('tbody'). html (resHtml);} else {alert('出问题了')}}});
})

英雄编辑

  • 给编辑按钮设置一个点击事件
  • 去掉默认的提交行为
  • 获取編辑后的英雄信息(FormData对象获取)
  • 发送ajax请求,完成編辑
  • 完成了编辑,提示一下跳转到首页
// 二:头像预览
$('#heroIcon').on('change', function () {var file = this.files[0]var url = URL.createObjectURL(file)$('#iconImg').attr('src', url)
})
// 保存按钮事件
// 1. 给编辑按钮设置一个点击事件
$('.btn-save').on('click', function (e) {//2.去掉默认的提交行为e.preventDefault()//3.获取編辑后的英雄信息(FormData对象获取)var fd = new FormData(document.querySelector('form'))// form表单是dom元素,要获取值的标签要有name属性,name属性的值要和接口参数一致//4.发送ajax请求,完成編辑$.ajax({type: 'post',url: 'http://127.0.0.1:4399/hero/update',// data是FormData对象,不要忘记2个false.contentType: false,processData: false,data: fd,success: function (backData) {if (backData.code == 200) {//5.完成了编辑,提示一下跳转到首页alert('编辑成功')window.location.href = '/index.html'}}})
})

英雄删除

  • 注册点击事件
  • 获取当前点击的这个删除按钮自定义属性保存的英雄id
  • 发送ajax请求,把id传过去
  • 删除成功了,就重 新加载一下数据,或者刷新一下页面
//1.注册点击事件.
$('tbody').on('click', '.btn-delete', function () {if (confirm( '你确定要删除吗?')) {//2.获取当前点击的这个删除按钮自定义属性保存的英雄idvar id = $(this).attr('data-id')//3.发送ajax请求,把id传过去$.ajax({type: 'post',url: 'http://127.0.0.1:4399/hero/delete',data: {id},success: function (backData) {if (backData.code == 200) {//4. 删除成功了,就重 新加载一下数据,或者刷新一下页面alert('删除成功')getData()}}})}
})

验证码

  • 点击验证码图片刷新验证码

    • 验证码不能使用ajax发送请求

      • 原因:验证码服务器返回的不是字符串,而是图片二进制数据
    • 验证码只需重设img标签的src属性即可
      • 问题:img标签自带缓存功能,如果src一致,则只发一次请求
      • 解决方案:添加随机参数
// 1.点击验证码图片刷新验证码
$('.code').on('click', function () {$(this).attr('src', 'http://127.0.0.1:4399/captcha?sb=' + Math.random());
});

用户注册

  • 注册按钮的点击事件
  • 取消默认的提交行为
  • 获取用户注册时候输入的用户名/密码/验证码
  • 在密码加密之后获取密码,获取到的就是密文
  • 发送ajax请求,完成注册
//二:注册
// 2.注册按钮的点击事件
$('#register').on('click', function (e) {// 2.取消默认的提交行为e.preventDefault();// 3.获取用户注册时候输入的用户名/密码/验证码let username = $('#username').val().trim()//账号let code = $('#code').val().trim()//验证码$('#password').val(md5($('#password').val().trim(), 'dg'))//密码//在密码加密之后获取密码,获取到的就是密文let password = $('#password' ).val().trim();console . log(password) ;// md5加密 md5();// 第一个参数:要加密的明文// 第二个参数:加盐(作用:增加密码的复杂度;特点:同样的明文,盐不同,得到的密文不同)// 细节:尽量不在控制台打印用户的明文和密码// let password = $('#password').val();// let miwen = md5(password,'jane');// 取出表单数据,加密完之后,重新赋值给表单/*FormData:(1)自动获取每个表单的name和value拼接成参数 (2)上传文件$('#form').serialize():(1)自动获取每个表单的name和value拼接成参数*///4.发送ajax请求,完成注册$.ajax({url: 'http://127.0.0.1:4399/user/register',type: 'post',// dataType: 'json',data: {username,password,code},success: function (backData) {if (backData.code == 200) {alert('注册成功');// 跳转首页window.location.href = "./login.html";} else {alert(backData.msg);}}});
})

用户登录

  • 给登录按钮设置一个点击事件
  • 去掉默认的提交行为
  • 获取用户输入的账号和密码(要和注册的时候一样的加密规则的加密后的密码)
  • 把用户输入的密码用md5加盐的方式加密后,重新赋值给密码输入框
  • 发送ajax请求,完成登录
$(function () {//一:登录//1.给登录按钮设置一个点击事件$('.btn-login').on('click', function (e) {//2.去掉默认的提交行为e.preventDefault()//3.获取用户输入的账号和密码(要和注册的时候一样的加密规则的加密后的密码)let username = $('#username').val().trim()// 把用户输入的密码用md5加盐的方式加密后,重新赋值给密码输入框$('#password').val(md5($('#password').val().trim(), 'dg'))let password = $('#password').val().trim()//4.发送ajax请求,完成登录$.ajax({type: "post",url: 'http://127.0.0.1:4399/user/login',data: { username, password },success: function (backData) {if (backData.code == 200) {alert('登录成功');window.location.href = './index.html'} else {alert(backData.msg)}}})})
})

检测是否登录

在页面加载后自动发送请求判断是否登陆

<script>(function () {$.ajax({type: 'get',url: '/isLogin',success: function (backData) {if (backData == '') {alert('没有登陆')window.location.href = '/login.html'}}})})()
</script>

[Node.js] mySQL数据库 -- 英雄管理系统(完善)相关推荐

  1. [Node.js] mySQL数据库 -- 英雄英雄管理系统接口

    新增接口 // 1.写一个新增接口 // 参数:heroName heroSkill,heroIcon(文件),使用muter从前端接收 app.post("/hero/add", ...

  2. node.js+MySql数据库+HTML实现内部查重系统

    node.js+MySql数据库+HTML实现内部查重系统 实现目标: 1.将每个人的项目登记,存入MySql数据库 2.在填写时进行实时正则判断,判断每项输入格式是否正确,方便之后进行查重对比 3. ...

  3. [Node.js] mySQL数据库 -- 数据库的基本操作

    数据库介绍 什么是数据库 存储数据的仓库(文件夹) 数据库操作 打开phpstudy,点击MySQL管理器,点击MySQL-Front,弹出弹框 点击新建,创建新的账号和密码(这里是我的数据库) 在左 ...

  4. [Node.js] mySQL数据库 -- promise

    promise介绍 promise就是用来解决回调地狱的 1.主要用于异步计算 2.可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果 3.可以在对象之间传递和操作promise,帮助我们处 ...

  5. [Node.js] mySQL数据库 -- NPM包

    CommonJS 1.导入模块用require 类比于script src= 2.暴露出去(导出) exports (function(window){ let jQuery-{}; window. ...

  6. Node.js+MySQL开发的B2C商城系统源码+数据库(微信小程序端+服务端),界面高仿网易严选商城

    下载地址:Node.js+MySQL开发的B2C商城系统源码+数据库(微信小程序端+服务端) NideShop商城(微信小程序端) 界面高仿网易严选商城(主要是2016年wap版) 测试数据采集自网易 ...

  7. Node.js SQL数据库操作 (上)(操作MySQL数据库及 数据库连接池)

    文章目录 Node.js MySQL驱动 操作 MySQL 数据库 连接 MySQL 数据库 增删改查操作 防止 SQL 注入攻击 数据库连接池操作 Node.js MySQL驱动 Node.js的原 ...

  8. node mysql商城开发_NideShop:基于Node.js+MySQL开发的微信小程序商城开源啦

    NideShop:基于Node.js+MySQL开发的微信小程序商城开源啦 发布时间:2020-04-14 04:23:37 来源:51CTO 阅读:2894 作者:ch10mmt 高仿网易严选的微信 ...

  9. node.js+mysql实现分库分表存查数据:

    node.js+mysql实现分库分表: 1.分库分表使用场景: 互联网项目中常用到的关系型数据库,如MySQL,随着用户和业务的增长,传统的单库单表模式难以满足大量的业务数据存储以及查询,单库单表中 ...

最新文章

  1. Redhat Linux 7.2 打开或关闭防火墙
  2. 作为一个前端,可以如何机智地弄坏一台电脑?
  3. C++的拷贝构造函数、operator=运算符重载,深拷贝和浅拷贝、explicit关键字
  4. Web应用开发中的几个问题
  5. Matlab代码提示“svmtrain已删除 请改用fitcsvm”,以及svmpredict没有返回结果label和精度accuracy的解决办法
  6. knn算法(分类)-机器学习
  7. (01)odoo模型中调用窗体动作
  8. 怎样用js结合h5画出多头像组合头像
  9. 拓端tecdat|R语言泰坦尼克号随机森林模型案例数据分析
  10. Java调用python传参数并获取python返回的值
  11. 文字超出部分用省略号表示
  12. LeetCode——150. 逆波兰表达式求值(Evaluate Reverse Polish Notation)[中等]——分析及代码(Java)
  13. html页面div的显示/隐藏
  14. 输出满足某种条件的素数(C语言)
  15. 地图裁剪器,可以将图片裁剪成瓦片数据,主要用途是将高清卫星图像裁剪成瓦片图,可以做离线地图的开发,基于墨卡托坐标
  16. turtle简单绘图
  17. 不花钱,降低数据中心PUE的八个办法
  18. spyder python 使用_如何在spyder中使用vpython?
  19. springBoot集成websocket报java.lang.IllegalStateException: Failed to register @ServerEndpoint class:错误
  20. 经纬度中的度分秒转化为小数形式

热门文章

  1. linux里强制覆盖,Linux cp 强制覆盖(示例代码)
  2. python语言编写一个生成九宫格图片的代码_python简单实现9宫格图片实例
  3. c语言中字符串数组应用,C语言中字符变量字符串和字符数组应用.doc
  4. ibatis resultclass java.util.list_mybatis 动态sql返回一个List封装类报错求解决方法
  5. 最详细的Eigen笔记
  6. 四种引用类型(强引用、软引用、弱引用、虚引用)的简单介绍
  7. Java基础 选择语句,循环结构数组
  8. 谷歌浏览器的 vue插件工具
  9. OSPF-1-OSPF的数据库交换(4)
  10. split出现得问题