批改状态:合格
老师批语:
import { createRouter, createWebHistory } from 'vue-router'import Ad from '../views/kedaishu/ad.vue'import Index from '../views/Index.vue'import Login from '../views/Login.vue'import Course from '../views/kedaishu/course.vue'import AdminUser from '../views/admin/user.vue'const routes = [{path: '/', // 路由地址配置,就是浏览器上的urlname: 'home', // 是页面的名称,自定义,但是不要重复component: Index, // 这个是页面文件的路径},{path: '/login',//创建登录页面的路由name: 'login',component: Login,},{path: '/admin_user', // 路由地址配置,就是浏览器上的urlname: 'AdminUser', // 是页面的名称,自定义,但是不要重复component: AdminUser, // 这个是页面文件的路径},{path: '/ad', // 路由地址配置,就是浏览器上的urlname: 'ad', // 是页面的名称,自定义,但是不要重复component: Ad, // 这个是页面文件的路径},{path: '/course', // 路由地址配置,就是浏览器上的urlname: 'course', // 是页面的名称,自定义,但是不要重复component: Course, // 这个是页面文件的路径}]const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes})export default router
<template><div class="container"><div style="text-align: center"><img src="@/assets/logo.png" alt="logo" /><h3>phpAdmin后台管理</h3></div><div class="main"><!-- label-width="auto" 导致ElementPlusError: [ElForm] unexpected width 0 --><el-form :model="state" size="large"><el-form-item prop="account"><el-input v-model="state.account" name="account" class="w-50 m-2" placeholder="请输入账号"><template #prefix><el-icon class="el-input__icon" style="color: #1890ff"><Avatar /></el-icon></template></el-input></el-form-item><el-form-item prop="password"><el-input v-model="state.password" name="password" type="password" class="w-50 m-2" placeholder="请输入密码" show-password><template #prefix><el-icon class="el-input__icon" style="color: #1890ff"><Lock /></el-icon></template></el-input></el-form-item><el-form-item prop="remember"><el-checkbox v-model="state.remember" label="1" size="large">自动登录</el-checkbox></el-form-item><el-form-item><el-button type="primary" style="width: 100%" @click="onSubmit()">登录</el-button></el-form-item></el-form></div></div></template><script setup>import {reactive} from 'vue';import { useRouter } from 'vue-router';import {Login} from '../network/index.js';import { ElMessage } from 'element-plus'//这是向服务器请求时所输入的数据,创建登录时的state,与本文11,18,25行相对应const state = reactive({account : "",password : "",remember : true});//定义路由器const router = useRouter();//从浏览器存储里获取用户登录时的数据;uid//const uid=window.localStorage.getItem("uid");const ticket=window.localStorage.getItem("ticket");//如果有票据就跳转到首页if(ticket){ElMessage({ //增加这一条就不会跳转到登录页面了message:'您已登录',type:'success'});router.push("/");}//提交,onSubmit与28行相对应const onSubmit=()=>{console.log(state);//先打印一下数据Login(state).then((e)=>{ //state是传值,e是返回值console.log(e);if(e.code==0){ //如果e的值为0时,则登录成功ElMessage({message:e.msg,type:'success'});//把登录时的数据保存到浏览器的存储中//window.localStorage.setItem('uid',e.data.uid);window.localStorage.setItem('ticket',e.data.ticket);window.localStorage.setItem('name',e.data.name);//路由器跳转到首页router.push("/");}else{ //反之登录不成功ElMessage({message:e.msg,type:'error'});}})}// const router = useRouter();// const ticket = window.localStorage.getItem("ticket");// if(ticket){// ElMessage({// message: '您已登录',// type: 'success'// });// router.push("/");// }// const onSubmit = ()=>{// Login(state).then( (e)=>{// console.log(e.data);// if(e.code == 0){// ElMessage({// message: e.msg,// type: 'success'// });// 登录完成以后// window.localStorage.setItem("ticket",e.data.ticket);// window.localStorage.setItem("name",e.data.name);// router.push("/");// }else{// ElMessage({// message: e.msg,// type: 'error'// });// }// } )// }</script><style>.container {position: relative;width: 100%;min-height: 100%;padding: 110px 0 144px;background-repeat: no-repeat;background-position: center 110px;background-size: 100%;}.main {width: 368px;min-width: 260px;margin: 50px auto;}.el-icon {color: #359eff;}</style>
<template><div style="margin:0 0 20px 0;"><!-- 当添加按钮点击时调用add方法并传一个为0的值 --><el-button type="success" size="large" @click="add(0)">添加</el-button></div><el-form label-width="120px" :inline="true"><el-form-item label="搜索项"><el-select placeholder="请选择您要搜索的项"><el-option label="姓名" value="" /><el-option label="手机" value="" /></el-select></el-form-item><el-form-item><el-button type="primary">搜索</el-button></el-form-item></el-form><el-table :data="tableData.lists" border style="width: 100%" size="large"><el-table-column prop="uid" label="ID" /><el-table-column prop="account" label="账号" /><el-table-column prop="name" label="姓名" /><el-table-column prop="phone" label="手机号" /><el-table-column prop="status" label="状态" /><el-table-column prop="add_time" label="入职时间" /><el-table-column prop="last_time" label="最后登录时间" /><el-table-column label="操作"><template #default="scope"><el-button size="small" type="primary" @click="add(scope.row)">修改</el-button><!-- <el-button size="small" type="danger">删除</el-button> --><el-popconfirm title="确认删除吗?" @confirm="del(scope.row)"><template #reference><el-button size="small" type="danger">删除</el-button></template></el-popconfirm></template></el-table-column></el-table><!-- 弹出的对话框(弹窗) --><el-dialog v-model="data.is_form" :title="data.title" width="30%"><!-- 弹窗中的表单 --><el-form :model="fromData" label-width="120px" size="small"><el-form-item label="账号"><el-input v-model="fromData.account"/></el-form-item><el-form-item label="密码"><el-input v-model="fromData.password" type="password" show-password :placeholder="data.plac"/></el-form-item><el-form-item label="姓名"><el-input v-model="fromData.name"/></el-form-item><el-form-item label="手机号"><el-input v-model="fromData.phone"/></el-form-item><el-form-item label="状态"><el-select v-model="fromData.status" placeholder="请选择状态"><el-option label="开启" :value="1" /><el-option label="关闭" :value="0" /></el-select></el-form-item><el-form-item label="入职时间"><el-date-pickerv-model="fromData.add_time"type="date"placeholder="选一日期":size="size"/></el-form-item><el-form-item label="最后登录时间"><el-date-pickerv-model="fromData.last_time"type="date"placeholder="选一日期":size="size"/></el-form-item><!-- '确定'按钮 --><el-button type="success" size="largr" @click="fun">确定</el-button></el-form></el-dialog></template><script setup>//从vue中引入响应式数据reactive(数据改变后视图也会自动更新,就叫响应式数据)import {reactive} from 'vue';import axios from "axios";//引入index.js文件中的UserLists,UserSave方法import {UserLists,UserSave,UserDel} from "../../network/index.js"// 引入element组件中的消息框import { ElMessage } from 'element-plus';// 引入element组件中的告示框import { alertProps } from 'element-plus';//运用票据(ticket),还要引入下面路由import { useRouter } from 'vue-router';//获取票据(ticket)const ticket=window.localStorage.getItem('ticket');const router=useRouter();//增加下面这一条就不能随便打开用户文件了,要先登录才行if(!ticket){ElMessage({message:'请先登录',type:'error'});router.push("/login");}// reactive表示data下有多个值,如data.is_form,data.titleconst data=reactive({is_form:false,title:"添加",plac:"请输入密码",});const fromData=reactive({uid : 0,account:'',password:'',name:'',phone:'',add_time:'',last_time:'',status:1,});const tableData=reactive({lists:[]});UserLists().then((e)=>{tableData.lists=e;})// 添加和修改弹框const add=(e)=>{ //e传一个0的值(看第4行)console.log(e);data.is_form=true;//if(e!=0){data.title="修改";data.plac = "密码如果不修改,可以不填写"fromData.account=e.account;fromData.name=e.name;fromData.phone=e.phone;fromData.password="";fromData.uid = e.uid;}else{data.title="添加";data.plac = "请输入密码";fromData.account="";fromData.name="";fromData.phone="";fromData.add_time="";fromData.last_time="";fromData.password="";fromData.uid = 0;}}//'确定'按钮点击时调用以下fun方法const fun=()=>{console.log(fromData);UserSave(fromData).then((e)=>{//console.log(e);// alert(e.msg);// console.log(fromData.add_time);// console.log(fromData.last_time);data.is_form=false;//弹窗关闭UserLists().then((e)=>{tableData.lists=e;})if(e.code==0){ElMessage({message: e.msg,type: 'success',})}else{ElMessage({message: e.msg,type: 'error',})}})// data.is_form=false;//弹窗关闭// UserLists().then((e)=>{// tableData.lists=e;// })}const del=(e)=>{console.log(e);UserDel({uid:e.uid}).then((e)=>{if(e.code==0){ElMessage({message:e.msg,type:'success'});}else{ElMessage({message:e.msg,type:'error'});}UserLists().then((e)=>{tableData.lists=e;})})}</script>
import { request } from "../network/request.js";// export function index(){// return request({// url:"Api2/index",// method:"get",// })// }//查询用户列表接口export function UserLists(){return request({url:"Api2/UserLists",method:"post",})}// 添加用户数据接口export function UserSave(data){//header("Access-Control-Allow-Origin:*");return request({url:"Api2/UserSave",method:"post",data:data})}// 删除用户数据接口export function UserDel(data){return request({url:"Api2/UserDel",method:"post",data:data})}//创建登录接口export function Login(data){return request({url:"Api2/Login",method:"post",data:data})}
<?phpnamespace app\controller;use app\BaseController;use ouyangke\Ticket;// *要使用Db类必须使用门面方式( think\facade\Db )调用use think\facade\Db;// *引用门面方式的请求类use think\facade\Request;class Api2 extends BaseController{//public function index(){//header("Access-Control-Allow-Origin:*");//------------------------------------// echo 333;//------------------------------------// json格式,叫json字符串,在php中,不方便创建,先创建数组,用数组转成json格式//------------------------------------// $json = '{// ouyangke => "欧阳克"// }';// echo $json;//------------------------------------// 数组格式// $arr = [// [// 'uid' => 1,// 'name' => '欧阳克'// ],// [// 'uid' => 2,// 'name' => '朱天蓬'// ]// ];// print_r($arr);//------------------------------------// 把数组转换成json格式// $arr = [// [// 'uid' => 1,// 'name' => '欧阳克'// ],// [// 'uid' => 2,// 'name' => '朱天蓬'// ]// ];// $json = json_encode($arr);// print_r($json);// [{"uid":1,"name":"\u6b27\u9633\u514b"},{"uid":2,"name":"\u6731\u5929\u84ec"}]//------------------------------------// 使用var_dump判断json是一个字符串////------------------------------------//------------------------------------ // 打印json数据的类型,是字符串// $arr = [// [// 'uid' => 1,// 'name' => '欧阳克'// ],// [// 'uid' => 2,// 'name' => '朱天蓬'// ]// ];// $json = json_encode($arr);// var_dump($json);// string(77) "[{"uid":1,"name":"\u6b27\u9633\u514b"},{"uid":2,"name":"\u6731\u5929\u84ec"}]"//------------------------------------// 把json转换为数组的形式// $json = '[{"uid":1,"name":"\u6b27\u9633\u514b"},{"uid":2,"name":"\u6731\u5929\u84ec"}]';// $array = json_decode($json,true);// print_r($array);//------------------------------------// 用户表转换为数组形式//$arr_user = Db::table('bew_user')->select()->toArray();//打印// print_r($arr_user);// if(!empty( $arr_user)){// foreach( $arr_user as &$user_v){// if($user_v['status'] == 1){// $user_v['status_s'] = '开启';// }else{// $user_v['status_s'] = '关闭';// }// //把时间的值由时间戳改为年月日// $user_v['add_time'] = date('Y-m-d',$user_v['add_time']);// $user_v['last_time'] = date('Y-m-d',$user_v['last_time']);// }// }// 用户表由数组形式转换为json形式//$json_user = json_encode( $arr_user);//输出// echo $json_user;//也可以打印的方法// print_r($json_user);//------------------------------------//}//从前台的查询用户列表接口转到后台这用户列表方法public function UserLists(){//header("Access-Control-Allow-Origin:*");// 用户表转换为数组形式$arr_user = Db::table('bew_user')->select()->toArray();if (!empty($arr_user)) {foreach ($arr_user as & $user_v) {if ($user_v['status'] == 1) {$user_v['status'] = '开启';} else {$user_v['status'] = '关闭';}//把时间的值由时间戳改为年月日$user_v['add_time'] = date('Y-m-d', $user_v['add_time']);$user_v['last_time'] = date('Y-m-d', $user_v['last_time']);}}// 用户表由数组形式转换为json形式$json_user = json_encode($arr_user);//输出// echo $json_user;//也可以打印的方法print_r($json_user);}//从前台的添加用户接口转到后台这添加用户方法public function UserSave(){//$post相当于前台的弹窗表单$post=input('post.');//print_r($post);if ($post['uid']==0) {$data=[ //以下$data就是要传的数据'account' => $post['account'],//如'account'是$post下的'account'传过来的'password'=>md5($post['password']),'name' => $post['name'],'phone' => $post['phone'],'status' => $post['status'],// 'add_time'=>time(),//time()表示当前日期//strtotime表示获取某个时间的时间戳'add_time'=>strtotime($post['add_time']),// 'last_time'=>strtotime($post['last_time'])//数据库中如果对该字段(add_time)设为不可null,则该项就要加上去(即不能注释)'last_time'=>strtotime($post['last_time']),];// print_r ($data);$insert = Db::table('bew_user')->insert($data);if (empty($insert)) {$arr=['code'=>1,//以上添加中的插入语句通常返回为code码,有0或1,0表示成功,1表示失败,这里用数组包括0及1'msg'=>'失败'];} else {$arr=['code'=>0,'msg'=>'成功'];}echo json_encode($arr);// 由数组形式转换为json形式}else{$data=[ //以下$data就是要传的数据//'uid'=>$post['uid'],'account' => $post['account'],//如'account'是$post下的'account'传过来的//密码不修改// 'password'=>md5($post['password']),'name' => $post['name'],'phone' => $post['phone'],'status' => $post['status'],'add_time'=>strtotime($post['add_time']),'last_time'=>strtotime($post['last_time']),];if(!empty($post['password'])){//当修改对象时不使其密码为空$data['password']=md5($post['password']);}$user=Db::table('bew_user')->where('uid',$post['uid'])->update($data);if (empty($user)) {$arr=['code'=>1,//以上添加中的插入语句通常返回为code码,有0或1,0表示成功,1表示失败,这里用数组包括0及1'msg'=>'修改失败'];} else {$arr=['code'=>0,'msg'=>'修改成功'];}echo json_encode($arr);// 由数组形式转换为json形式}}//从前台的删除用户接口转到后台这删除用户方法public function UserDel(){$uid=input('post.uid');if(empty($uid)){$arr=['code'=>1,'msg'=>'请选择用户'];echo json_encode($arr);exit;}$del=Db::table('bew_user')->where('uid',$uid)->delete();if(empty($del)){$arr=['code'=>1,'msg'=>'删除失败'];echo json_encode($arr);exit;}else{$arr=['code'=>0,'msg'=>'删除成功'];echo json_encode($arr);}}//从前台的登录接口转到后台这登录方法public function Login(){$post=input('post.');//接收这postif(empty($post['account'])){ //如果接收的post中的账号为空$arr=['code'=>1,'msg'=>'账户不能为空'];echo json_encode($arr);exit;}if(empty($post['password'])){ //如果接收的post中的密码为空$arr=['code'=>1,'msg'=>'密码不能为空'];echo json_encode($arr);exit;}//根据所接收的账号,查询bew_user表,并返回给变量$user$user=Db::table('bew_user')->where('account',$post['account'])->find();//print_r($user);//把它打印出来if(empty($user)){ //判断变量$user是否为空$arr=['code'=>1,'msg'=>'未找到账户'];echo json_encode($arr);exit;}if($user['password']!=md5($post['password'])){$arr=['code'=>1,'msg'=>'密码错误'];echo json_encode($arr);exit;}// unset($user['password']);//登录时数据中不显示密码(暂时打开)//票据调用创建(create())方法,把$user下面的uid传过来,关键词是phpcn,最后返回一个票据$ticket$ticket=Ticket::create($user['uid'],'phpcn');// print_r($ticket); //暂时打开//echo Ticket::get($ticket,'phpcn');//把32位加密传回去,然后再输出出来(暂时打开)$user['ticket'] = $ticket;unset($user['password'],$user['uid']);//登录时数据中不显示密码与用户的uid$arr = ['code' => 0,'msg' => '登录成功','data' => $user];echo json_encode($arr);}}
<?phpnamespace ouyangke;/*** ticket* @author ouyangke*/// Tickey(票据)其作用是考虑数据安全,这里是不直接显示uid,并对uid进行加密class Ticket {/*** 只允许静态调用*/// final private function __construct() {// throw new ThinkException('只允许静态调用');// }/*** 创建ticket(即门票的意思)** @param integer $uid 用户id* @param integer $bind 关键词* @param number $time 有效期* @param string $durable* @return multitype:number string*///静态的创建方法(由于是静态,故可用'::'进行访问及调用,其中7*24*60*60表示7天有效期,$durable为判断)// public static function create($uid, $bind="ouyangke",$time=7*24*60*60, $durable = false) {public static function create($uid, $bind="ouyangke",$time=1*1*1*60, $durable = false) {$expire = time() + $time;//调用_genKey方法(即加密成一个key,现返回给$key)$key = self::_genKey($uid, $bind, $expire);// 然后把上面的$bind, $uid, $key, $expire, $durable传到以下这个生成门票的方法中// 以下通过调用生成门票方法,然后就生成一个票据($ticket)$ticket = self::_buildTicket($bind, $uid, $key, $expire, $durable);return $ticket;}/*** 获取ticket信息** @param integer $ticket* @param boolean $checked* @return Ambigous <mixed, NULL, multitype:number >*/// 静态获取票据方法(把票据传过来)public static function get($ticket, $bind, $checked = false) {$checked || self::checkFormat($ticket);$uid = 0;$key = 0;$expire = 0;$durable = false;// 把以下这些数据进行解密$info = self::_parseTicket($ticket, $bind, $uid, $key, $expire, $durable);if (time() < $expire) {$info = array();$info['uid'] = $uid;$info['expire'] = $expire;return $uid; //最后返回uid}return false;}/*** 生成ticket* @param string $bind* @param integer $uid* @param integer $key* @param integer $expire* @param boolean $durable* @return string*///生成门票的方法protected static function _buildTicket($bind, $uid, $key, $expire, $durable = false) {$uBit = decbin($uid);$uLen = strlen($uBit);$eBit = sprintf('%032b', $expire);$kBit = sprintf('%032b', $key);$rBit = sprintf('%058s%05b%d', substr(base_convert(substr(md5(uniqid(mt_rand(), true)), mt_rand(0, 16), 16), 16, 2), 0, 58), $uLen % 32, $durable ? 1 : 0);$cBit = sprintf('%032b', crc32($uBit . $eBit . $kBit . $rBit . $bind));$uBit .= substr(sprintf('%032b', mt_rand()), $uLen - 32);$bin = '';for ($i = 0; $i < 32; $i++) {$bin .= $rBit[$i * 2];$bin .= $eBit[$i];$bin .= $kBit[$i];$bin .= $rBit[$i * 2 + 1];$bin .= $uBit[$i];$bin .= $cBit[$i];}// 然后再进行加密并返回return strtr(base64_encode(implode('', array_map(function($item){ return chr(bindec($item)); }, str_split($bin, 8)))), '+/', '-_');}/*** 解析Ticket** @param string $ticket* @param string $bind* @param integer $uid* @param integer $key* @param integer $expire* @param boolean $durable* @return boolean*/protected static function _parseTicket($ticket, $bind, &$uid = NULL, &$key = NULL, &$expire = NULL, &$durable = NULL) {$rBit = '';$eBit = '';$kBit = '';$uBit = '';$cBit = '';$bin = implode('', array_map(function($item){ return sprintf('%08b', ord($item)); }, str_split(base64_decode(strtr($ticket, '-_', '+/')), 1)));for ($i = 0; $i < 192; $i += 6) {$rBit .= $bin[$i];$eBit .= $bin[$i + 1];$kBit .= $bin[$i + 2];$rBit .= $bin[$i + 3];$uBit .= $bin[$i + 4];$cBit .= $bin[$i + 5];}$uLen = bindec(substr($rBit, 58, 5));if ($uLen < 32) {$uBit = substr($uBit, 0, $uLen);}if (sprintf('%u', crc32($uBit . $eBit . $kBit . $rBit . $bind)) == bindec($cBit)) {$uid = bindec($uBit);if ($uid > 0) {$expire = bindec($eBit);$key = bindec($kBit);$durable = ($rBit[63] === '1');return true;}}// throw new ThinkException('Ticket error');}/*** 生成key** @param integer $uid* @param string $bind* @param integer $expire* @return integer*///_genKey方法其作用是加密成一个key(键)// 先用'%d|%s|%d',替换掉$uid, $bind, $expire,然后用md5进行加密,最后使用32位数据进行处理并返回protected static function _genKey($uid, $bind, $expire) {return crc32(md5(sprintf('%d|%s|%d', $uid, $bind, $expire), true));}/*** 发送ticket http头** @param string $ticket* @param integer $uid* @param integer $ttl*/// protected static function _headerTicket($ticket, $uid, $ttl) {// header(sprintf('Set-Ticket: %s; uid=%d; expires=%s; Max-Age=%d', $ticket, $uid, Request::httpDate(time() + $ttl), $ttl));// }/*** 判断格式是否正确** @param string $ticket* @return boolean*/protected static function _isTicket($ticket) {return strlen($ticket) == 32 && strspn($ticket, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_') == 32;}/*** 检查格式是否正确** @param string $ticket*/public static function checkFormat($ticket) {if (!self::_isTicket($ticket)) {return false;}}}
1
2
3
4
1
2
3
4
1
2
3
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号