本文将完成一个物流原型系统核心代码的编写。该系统采用thinkphp作为后端框架,bootstrap作为前端主框架,并使用百度地图api作为地图载体。
一、系统需求
系统需完成的功能包括:
- 订单提交
- 订单追踪(出发地、目的地、当前位置)
- 地图集成(百度地图api)
- 用户管理
二、技术基础
- 后端:php,框架:thinkphp
- 前端:bootstrap,jquery,百度api
关于thinkphp的核心学习可参考前一篇《利用thinkphp建立一个简单的站点》,其中介绍了该框架的基础入门教程。
三、系统设计
1、控制器及视图
由于是原型系统,所以在控制器上不分其他控制器,因此只需创建一个index的控制器,然后在该控制器的方法上做文章。视图文件也可就放在一个index文件夹中,方便调用。
2、数据库设计
user表:
- id:int 8(用户编号)
- name:varchar 20(用户名)
- password:varchar 20(密码)
- type:int 1(用户类型:用户、司机、管理员等)
order表:
- id:int 8(订单编号)
- start:varchar 50(订单起始地,位置信息用字符串描述)
- end:varchar 50(订单目的地,位置信息用字符串描述)
- time:varchar 50(订单上传时间)
- lal:varchar 50(订单目前所处位置)
四、核心代码
1、index控制器
控制器index的核心代码如下:
<?php
namespace app\index\controller;
//引入多个包
use think\Controller;
use think\View;
use think\Db;
use think\Request;
use think\Session;
class Index extends Controller
{
public function index()//首页
{
$DB=new Db;
$order=$DB::table("order")->select();
$this->assign('order',$order);
$this->assign('name',Session::get('name'));
$this->assign('type',Session::get('type')==0?"用户":"司机");
return $this->fetch();
}
public function query()//查询页
{
if(request()->isPost()){
$DB=new Db;
$map['id']=input('id');
$order=$DB::table("order")->where($map)->find();
$this->assign('order',$order);
return $this->fetch();
}
$this->error("错误");
}
public function view($id)//订单页
{
$DB=new Db;
$map['id']=$id;
$order=$DB::table("order")->where($map)->find();
$this->assign('order',$order);
return $this->fetch('query');
}
public function add()//添加订单
{
if(request()->isPost()){
$data=[
'start'=>input('start'),
'end'=>input('end'),
'time'=>time(),
];
$DB=new Db;
$DB::name('order')->insert($data);
}
$this->success("添加成功!");
}
public function del($id)//删除订单
{
$DB=new Db;
$info=$DB::table("order")->where('id',$id)->delete();
if($info){
$this->success("删除成功!");
}else{
$this->error($file->getError());
}
}
public function douser()//验证用户
{
$request = Request::instance();
if(request()->isPost()){
$m['name']=input('name');
$m['password']=input('password');
$DB=new Db;
$userdata=$DB::table("user")->where($m)->find();
if($userdata==null){
return $this->error('用户名或密码错误!');
}else{
Session::set('name',$userdata['name']);
Session::set('type',$userdata['type']);
return $this->success('登录成功!',url('index/index'));
}
}
}
public function loginout()//注销
{
Session::delete('name');
Session::delete('type');
return $this->success('注销成功!',url('index/index'));
}
}
在index控制器中,我们写了几个函数用于构建对应链接所导致的行为,如显示主页、查询页等页面,用户登录注销等操作以及添加订单等行为。
2、index.html主页
主页index.html的代码如下:
<html>
<head>
<title>物流信息原型系统</title>
<!-- 引入css文件 -->
<link rel="stylesheet" type="text/css" href="__HOME__/css/bootstrap.min.css" />
<!-- 引入js文件 -->
<script src="__HOME__/js/jquery-3.4.1.min.js"></script>
<script src="__HOME__/js/bootstrap.min.js"></script>
<script src="__HOME__/js/echarts.min.js"></script>
</head>
<body>
<nav class="navbar navbar-dark bg-dark navbar-expand-lg mb-3">
<a class="navbar-brand" href="{:url('index/index');}">物流信息原型系统</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
管理
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">上传单号</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">管理单号</a>
</div>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="单号" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">查询</button>
</form>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-4 col-sm-12">
{if condition="$Think.session.name == null"}
<div class="card" style="width: 100%;">
<div class="card-header">
登录
</div>
<div class="card-body">
<form method="post" action="{:url('index/douser');}">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">用户名</span>
</div>
<input name="name" type="text" class="form-control" placeholder="" aria-describedby="basic-addon1" value="">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">密码</span>
</div>
<input name="password" type="password" class="form-control" placeholder="" aria-describedby="basic-addon1" value="">
</div>
<button id="count" type="submit" class="btn btn-primary btn-block mb-3" data-dismiss="modal">登录</button>
</form>
</div>
</div>
{else /}
<div class="card" style="width: 100%;">
<div class="card-header">
个人信息
</div>
<div class="card-body">
<div class="input-group mb-3">
姓名:{$name}</br>
类型:{$type}
</div>
<button type="submit" class="btn btn-primary btn-block mb-3" data-dismiss="modal">进入个人中心</button>
<a href="{:url('index/loginout');}" class="btn btn-primary btn-block mb-3" data-dismiss="modal">退出</a>
</div>
</div>
{/if}
<br/>
<div class="card" style="width: 100%;">
<div class="card-header">
查询订单
</div>
<div class="card-body">
<form method="post" action="{:url('index/query');}">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">单号</span>
</div>
<input name="id" type="text" class="form-control" placeholder="" aria-describedby="basic-addon1" value="">
</div>
<button id="count" type="submit" class="btn btn-primary btn-block mb-3" data-dismiss="modal">查询</button>
</form>
</div>
</div>
<br/>
</div>
<div class="col-md-8 col-sm-12">
<div class="card" style="width: 100%;">
<div class="card-header">
最新订单
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th scope="col">单号</th>
<th scope="col">出发地</th>
<th scope="col">目的地</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
{foreach $order as $data}
<tr>
<th scope="row">{$data.id}</th>
<td>{$data.start}</td>
<td>{$data.end}</td>
<td><a href="{:url('index/view');}/id/{$data.id}">查看</a></td>
</tr>
{/foreach}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
主页中用到了thinkph视图的输出函数,在无用户登录时显示登录框,在登录后显示用户个人信息框。同时在该页面集成查询、最新订单的显示等页面。
3、query.html查询页
查询也query.html的代码如下:
<html>
<head>
<title>物流信息原型系统</title>
<!-- 引入css文件 -->
<link rel="stylesheet" type="text/css" href="__HOME__/css/bootstrap.min.css" />
<!-- 引入js文件 -->
<script src="__HOME__/js/jquery-3.4.1.min.js"></script>
<script src="__HOME__/js/bootstrap.min.js"></script>
<script src="__HOME__/js/echarts.min.js"></script>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=RODusGpnlcywQkMpTigghmhb5mfPu2Gf"></script>
</head>
<body>
<nav class="navbar navbar-dark bg-dark navbar-expand-lg mb-3">
<a class="navbar-brand" href="{:url('index/index');}">物流信息原型系统</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
管理
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">上传单号</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">管理单号</a>
</div>
</li>
</ul>
<form class="form-inline my-2 my-lg-0">
<input class="form-control mr-sm-2" type="search" placeholder="单号" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">查询</button>
</form>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-4 col-sm-12">
<div class="card" style="width: 100%;">
<div class="card-header">
查询订单
</div>
<div class="card-body">
<form method="post" action="{:url('index/query');}">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">单号</span>
</div>
<input name="id" type="text" class="form-control" placeholder="" aria-describedby="basic-addon1" value="{$order.id}">
</div>
<button id="count" type="submit" class="btn btn-primary btn-block mb-3" data-dismiss="modal">查询</button>
</form>
</div>
</div>
<br/>
<div class="card" style="width: 100%;">
<div class="card-header">
管理订单
</div>
<div class="card-body">
<form method="post" action="{:url('index/query');}">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">当前位置</span>
</div>
<input id="lal" name="lal" type="text" class="form-control" placeholder="" aria-describedby="basic-addon1" value="">
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">信息</span>
</div>
<input name="inf" type="text" class="form-control" placeholder="" aria-describedby="basic-addon1" value="">
</div>
<button id="count" type="submit" class="btn btn-primary btn-block mb-3" data-dismiss="modal">更新</button>
</form>
</div>
</div>
<br/>
</div>
<div class="col-md-8 col-sm-12">
<div class="card mb-3" style="width: 100%;">
<div class="card-header">
订单信息
</div>
<div class="card-body">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">单号</span>
</div>
<input type="text" class="form-control" placeholder="" aria-describedby="basic-addon1" value="{$order.id}">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">出发地</span>
</div>
<input type="text" class="form-control" placeholder="" aria-describedby="basic-addon1" value="{$order.start}">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">目的地</span>
</div>
<input type="text" class="form-control" placeholder="" aria-describedby="basic-addon1" value="{$order.end}">
</div>
<div class="input-group mb-3">
</div>
<div id="container" style="width:100%;height:500px"></div>
</div>
<script type="text/javascript">
var map = new BMap.Map("container"); // 创建地图实例
var curpoint = new BMap.Point({$order.lal}); // 创建点坐标
map.centerAndZoom(curpoint, 8); // 初始化地图,设置中心点坐标和地图级别
map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
var myIcon = new BMap.Icon("__HOME__/img/1.png", new BMap.Size(50,32));
var marker = new BMap.Marker(curpoint,{icon:myIcon}); // 创建标注
map.addOverlay(marker); // 将标注添加到地图中
// 创建地址解析器实例
var myGeo = new BMap.Geocoder();
// 将地址解析结果显示在地图上,并调整地图视野
myGeo.getPoint("{$order.start}", function(spoint){
if (spoint) {
map.addOverlay(new BMap.Marker(spoint));
myGeo.getPoint("{$order.end}", function(epoint){
if (epoint) {
map.addOverlay(new BMap.Marker(epoint));
var driving = new BMap.DrivingRoute(map, {
renderOptions: {
map: map,
autoViewport: true
}
});
driving.search(curpoint, epoint);
//调整视野
map.setViewport([spoint, curpoint, epoint]);
}else{
alert("您选择地址没有解析到结果!");
}
});
}else{
alert("您选择地址没有解析到结果!");
}
});
//获取位置
function getPosition() {
if(navigator.geolocation){
//navigator.geolocation.getCurrentPosition这个方法里面有三个参数
//这个会在界面拉出一个消息框,让用户确认是否允许获取位置,不过pc端我试了都是err,
//参1,成功后执行的函数
//参2,失败时执行的函数
//参3,选项配置,下面是在6000毫秒内结束请求
navigator.geolocation.getCurrentPosition(
function (position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
$('#lal').val(latitude+latitude);
},
/*function (error) {
//处理错误
switch (error.code) {
case 1:
alert("位置服务被拒绝。");
break;
case 2:
alert("暂时获取不到位置信息。");
break;
case 3:
alert("获取信息超时。");
break;
default:
alert("未知错误。");
break;
}
}*/
)
}
}
getPosition();
</script>
</div>
</div>
</div>
</div>
</body>
</html>
在该页面中最核心的代码是调用百度地图的api,该调用需要先申请ak密匙然后填入其中才可正确调用。
通过这样几步就能完成一个物流系统核心代码的编写。
|