本文将完成一個物流原型系統核心代碼的編寫。該系統采用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密匙然後填入其中才可正确調用。
通過這樣幾步就能完成一個物流系統核心代碼的編寫。