天天看點

利用thinkphp建立一個物流原型系統

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

通過這樣幾步就能完成一個物流系統核心代碼的編寫。