实战4 ele与tp:登录状态路由跳转,ticket加密登录

编辑: admin 分类: 电脑知识 发布时间: 2023-06-14 来源:互联网
一、涉及代码文件文件:
  • /shop/src/views/Login.vue(更新登录成功路由跳转验证)
  • /shop/src/views/Index.vue(更新登录成功路由跳转验证。更新查询所有组)
  • /tp6/extend/ouyangke/Ticket.php(新建ticket登录认证)
  • /tp6/app/admin/controller/Login.php(更新)
  • /shop/src/views/User.vue(更新部门列表,新增修改用户部门)
  • /tp6/app/admin/controller/Index.php(更新部门查询)

1、Login.vue文件代码
  1. <template>
  2. <div class="container">
  3. <div style="text-align: center">
  4. <!--<img src="@/assets/logo.jpg" alt="logo" />-->
  5. <h3>后台管理</h3>
  6. </div>
  7. <div class="main">
  8. <!-- label-width="auto" 导致ElementPlusError: [ElForm] unexpected width 0 -->
  9. <el-form :model="form" size="large">
  10. <el-form-item prop="account">
  11. <el-input v-model="form.account" name="account" class="w-50 m-2" placeholder="请输入账号">
  12. <template #prefix>
  13. <el-icon class="el-input__icon" style="color: #1890ff"><Avatar /></el-icon>
  14. </template>
  15. </el-input>
  16. </el-form-item>
  17. <el-form-item prop="password">
  18. <el-input v-model="form.password" name="password" type="password" class="w-50 m-2" placeholder="请输入密码" show-password>
  19. <template #prefix>
  20. <el-icon class="el-input__icon" style="color: #1890ff"><Lock /></el-icon>
  21. </template>
  22. </el-input>
  23. </el-form-item>
  24. <el-form-item prop="remember">
  25. <el-checkbox v-model="form.remember" label="1" size="large">保存账密</el-checkbox>
  26. </el-form-item>
  27. <el-form-item>
  28. <el-button type="primary" style="width: 100%" @click="onSubmit()">登录</el-button>
  29. </el-form-item>
  30. </el-form>
  31. </div>
  32. </div>
  33. </template>
  34. <style>
  35. .container {
  36. position: relative;
  37. width: 100%;
  38. min-height: 100%;
  39. padding: 110px 0 144px;
  40. background-repeat: no-repeat;
  41. background-position: center 110px;
  42. background-size: 100%;
  43. }
  44. .main {
  45. width: 368px;
  46. min-width: 260px;
  47. margin: 50px auto;
  48. }
  49. .el-icon {
  50. color: #359eff;
  51. }
  52. </style>
  53. <script>
  54. import { reactive } from "vue";
  55. //import { request } from "../network/request.js";
  56. import { login } from "../network/index.js";
  57. // 登录成功用路由进行跳转:
  58. import { useRouter } from "vue-router";
  59. export default {
  60. setup() {
  61. const form = reactive({
  62. account: "428188207@qq.com",
  63. password: "123456",
  64. remember: true,
  65. });
  66. const router = useRouter();
  67. // 读取保存在缓存中的用户uid信息
  68. let ticket = window.localStorage.getItem('ticket');
  69. // 如果有登录就跳转到home页面
  70. if(ticket){
  71. router.push({
  72. path: "/index/home"
  73. });
  74. }
  75. const onSubmit = ()=>{
  76. login({
  77. account : form.account,
  78. password : form.password,
  79. }).then(res =>{
  80. console.log(res.data);
  81. // html5有个保存到本地的缓存机制.
  82. // 把用户的唯一标识,用户UID.保存到缓存中.
  83. // 接入ticket
  84. window.localStorage.setItem("ticket", res.data.data.ticket);
  85. if(res.data.code == 0){
  86. // 跳转到新页面
  87. router.push("/Index");
  88. // 另外一种写法
  89. // router.push({
  90. // path: "/index"
  91. //});
  92. }
  93. })
  94. }
  95. return {
  96. form,
  97. onSubmit
  98. };
  99. }
  100. };
  101. </script>

2、Index.vue文件代码
  1. <!-- 1、新建 /src/views/Index/Index.vue 文件 -->
  2. <template>
  3. <el-container class="layout" style="height: 100%">
  4. <aside style="height: 100%">
  5. <el-menu default-active="-1" class="el-menu-vertical-demo" :collapse="isCollapse" active-text-color="#ffd04b" background-color="#545c64" text-color="#fff">
  6. <div class="logo">
  7. <router-link to="/index/home" class="router">
  8. <!--<img src="@/assets/logo.jpg" alt="logo" />-->
  9. <h1>phpAdmin</h1>
  10. </router-link>
  11. </div>
  12. <router-link to="/index/home">
  13. <el-menu-item index="-1">
  14. <template #title>首页</template>
  15. </el-menu-item>
  16. </router-link>
  17. <router-link to="/index/home">
  18. <el-menu-item index="-2">
  19. <template #title>个人中心</template>
  20. </el-menu-item>
  21. </router-link>
  22. <template v-for="(item,index,key) in menu">
  23. <el-sub-menu :index="item.mid" v-if="item.type == 0">
  24. <template #title>
  25. <span>{{ item.label }}</span>
  26. </template>
  27. <template v-for="(items,indexs,keys) in item.son">
  28. <router-link :to="items.src" v-if="items.type == 1">
  29. <el-menu-item :index="item.mid + items.mid">
  30. <span>{{ items.label }}</span>
  31. </el-menu-item>
  32. </router-link>
  33. <a :href="items.src" target="_blank" v-if="items.type == 2">
  34. <el-menu-item :index="item.mid + items.mid">
  35. <span>{{ items.label }}</span>
  36. </el-menu-item>
  37. </a>
  38. </template>
  39. </el-sub-menu>
  40. <router-link :to="item.src" v-if="item.type == 1">
  41. <el-menu-item :index="index + item.mid">
  42. <template #title>{{ item.label }}</template>
  43. </el-menu-item>
  44. </router-link>
  45. <router-link :to="item.src" v-if="item.type == 2">
  46. <el-menu-item :index="index + item.mid">
  47. <template #title>{{ item.label }}</template>
  48. </el-menu-item>
  49. </router-link>
  50. </template>
  51. </el-menu>
  52. <div class="flexible" @click="isCollapse = !isCollapse">
  53. <el-icon v-if="isCollapse" color="white" :size="40"><ArrowRight /></el-icon>
  54. <el-icon v-else color="white" :size="40"><ArrowLeft /></el-icon>
  55. </div>
  56. </aside>
  57. <el-container>
  58. <el-header style="text-align: right; font-size: 20px">
  59. <div class="toolbar">
  60. <el-dropdown size="large" type="primary">
  61. <span>{{name}}<el-icon style="margin-left: 8px; margin-top: 1px"><ArrowDown /></el-icon></span>
  62. <template #dropdown>
  63. <el-dropdown-menu>
  64. <el-dropdown-item>个人中心</el-dropdown-item>
  65. <el-dropdown-item @click="out()">退出</el-dropdown-item>
  66. </el-dropdown-menu>
  67. </template>
  68. </el-dropdown>
  69. </div>
  70. </el-header>
  71. <el-main>
  72. <router-view></router-view>
  73. </el-main>
  74. </el-container>
  75. </el-container>
  76. </template>
  77. <script>
  78. import { reactive, toRefs } from "vue";
  79. import { Index } from "../network/index";
  80. import { useRouter } from "vue-router";
  81. import { ElMessage } from 'element-plus';
  82. export default {
  83. name: "App",
  84. setup() {
  85. // 获取左侧菜单和用户信息
  86. const state = reactive({
  87. isCollapse: false,
  88. name : "",
  89. menu : []
  90. });
  91. // 读取保存在缓存中的用户uid信息
  92. let ticket = window.localStorage.getItem('ticket');
  93. // 如果没有获取到登录信息,就跳转
  94. const router = useRouter();
  95. if(!ticket){
  96. router.push({
  97. path: "/"
  98. });
  99. }
  100. // console.log(uid);
  101. Index({ticket:ticket}).then( (e) => {
  102. if(e.data.code == 1){
  103. alert(e.data.msg);
  104. router.push({
  105. path: "/"
  106. });
  107. } else if(e.data.code == 2){
  108. alert(e.data.msg);
  109. } else{
  110. state.menu = e.data.data.menu;
  111. }
  112. state.name = e.data.data.name;
  113. console.log(state);
  114. console.log(e.data);
  115. ElMessage('登录成功');
  116. })
  117. const out = ()=>{
  118. window.localStorage.setItem('ticket','');
  119. ElMessage('退出成功');
  120. setTimeout( ()=>{
  121. router.push({
  122. path : "/"
  123. });
  124. }, 500 )
  125. }
  126. return {
  127. ...toRefs(state),
  128. out,
  129. };
  130. }
  131. };
  132. </script>
  133. <style>
  134. body,
  135. html{
  136. margin : 0px 0px;
  137. height: 100%;
  138. }
  139. a {
  140. text-decoration: none;
  141. }
  142. .layout {
  143. background-color: #f0f2f5;
  144. }
  145. .layout .el-header {
  146. position: relative;
  147. background-color: white;
  148. color: var(--el-text-color-primary);
  149. }
  150. .layout aside {
  151. color: var(--el-text-color-primary);
  152. background: #001529;
  153. }
  154. .layout .el-menu {
  155. border-right: none;
  156. }
  157. .layout .el-main {
  158. margin: 30px 10px;
  159. background-color: white;
  160. }
  161. .layout .toolbar {
  162. display: inline-flex;
  163. align-items: center;
  164. justify-content: center;
  165. height: 100%;
  166. right: 20px;
  167. }
  168. aside {
  169. position: relative;
  170. }
  171. .flexible {
  172. background-color: #002140;
  173. text-align: center;
  174. position: absolute;
  175. bottom: 0px;
  176. left: 0px;
  177. right: 0px;
  178. }
  179. .el-menu-vertical-demo:not(.el-menu--collapse) {
  180. width: 200px;
  181. min-height: 100vh;
  182. }
  183. .layout aside .logo .router {
  184. display: flex;
  185. justify-content: space-evenly;
  186. align-items: center;
  187. animation-duration: 0.1s;
  188. overflow: hidden;
  189. text-decoration: none;
  190. padding-left: 1px;
  191. position: relative;
  192. left: 2px;
  193. }
  194. .layout aside .logo .router h1 {
  195. margin-left: 10px;
  196. color: aliceblue;
  197. overflow: hidden;
  198. }
  199. .layout aside .logo .router img {
  200. padding-left: 5px;
  201. width: 48px;
  202. height: 48px;
  203. }
  204. </style>

3、Ticket.php
  1. <?php
  2. namespace ouyangke;
  3. /**
  4. * ticket
  5. * @author ouyangke
  6. */
  7. class Ticket {
  8. /**
  9. * 创建ticket
  10. *
  11. * @param integer $uid 用户id
  12. * @param integer $bind 关键词
  13. * @param number $time 有效期
  14. * @param string $durable
  15. * @return multitype:number string
  16. */
  17. public static function create($uid, $bind='ouyangke',$time=7*24*60*60, $durable = false) {
  18. $expire = time() + $time;
  19. // 获取key
  20. $key = self::_genKey($uid, $bind, $expire);
  21. // 生成票据 ticket
  22. $ticket = self::_buildTicket($bind, $uid, $key, $expire, $durable);
  23. return $ticket;
  24. // return array('ticket' => $ticket, 'expire_time' => $expire);
  25. }
  26. /**
  27. * 获取ticket信息
  28. *
  29. * @param integer $ticket
  30. * @param boolean $checked
  31. * @return Ambigous <mixed, NULL, multitype:number >
  32. */
  33. public static function get($ticket, $bind='ouyangke', $checked = false) {
  34. $checked || self::checkFormat($ticket);
  35. $uid = 0;
  36. $key = 0;
  37. $expire = 0;
  38. $durable = false;
  39. $info = self::_parseTicket($ticket, $bind, $uid, $key, $expire, $durable);
  40. if (time() < $expire) {
  41. $info = array();
  42. $info['uid'] = $uid;
  43. $info['expire'] = $expire;
  44. return $uid;
  45. return $info;
  46. }
  47. return false;
  48. }
  49. /**
  50. * 生成ticket
  51. * @param string $bind
  52. * @param integer $uid
  53. * @param integer $key
  54. * @param integer $expire
  55. * @param boolean $durable
  56. * @return string
  57. */
  58. protected static function _buildTicket($bind, $uid, $key, $expire, $durable = false) {
  59. // decbin 函数把十进制数转换为二进制数
  60. $uBit = decbin($uid);
  61. // strlen 函数返回字符串的长度
  62. $uLen = strlen($uBit);
  63. // sprintf 把百分号(%)符号替换成一个作为参数进行传递的变量
  64. $eBit = sprintf('%032b', $expire);
  65. $kBit = sprintf('%032b', $key);
  66. // mt_rand 生成随机数
  67. // uniqid 生成一个唯一的 ID
  68. // md5 函数计算字符串的 MD5 散列
  69. // substr 函数返回字符串的一部分
  70. // base_convert 把十六进制数转换为八进制数
  71. $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);
  72. $cBit = sprintf('%032b', crc32($uBit . $eBit . $kBit . $rBit . $bind));
  73. $uBit .= substr(sprintf('%032b', mt_rand()), $uLen - 32);
  74. $bin = '';
  75. for ($i = 0; $i < 32; $i++) {
  76. $bin .= $rBit[$i * 2];
  77. $bin .= $eBit[$i];
  78. $bin .= $kBit[$i];
  79. $bin .= $rBit[$i * 2 + 1];
  80. $bin .= $uBit[$i];
  81. $bin .= $cBit[$i];
  82. }
  83. // bindec 函数把二进制转换为十进制。
  84. // chr 函数从指定的 ASCII 值返回字符
  85. // str_split 函数把字符串分割到数组中
  86. // array_map 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新的值的数组。
  87. // implode 函数返回一个由数组元素组合成的字符串。
  88. // base64_encode 函数用base64加密
  89. return strtr(base64_encode(implode('', array_map(function($item){ return chr(bindec($item)); }, str_split($bin, 8)))), '+/', '-_');
  90. }
  91. /**
  92. * 解析Ticket
  93. *
  94. * @param string $ticket
  95. * @param string $bind
  96. * @param integer $uid
  97. * @param integer $key
  98. * @param integer $expire
  99. * @param boolean $durable
  100. * @return boolean
  101. */
  102. protected static function _parseTicket($ticket, $bind, &$uid = NULL, &$key = NULL, &$expire = NULL, &$durable = NULL) {
  103. $rBit = '';
  104. $eBit = '';
  105. $kBit = '';
  106. $uBit = '';
  107. $cBit = '';
  108. // strtr 函数转换字符串中特定的字符
  109. // base64_decode 函数用base64解密
  110. // str_split 函数把字符串分割到数组中
  111. // sprintf 把百分号(%)符号替换成一个作为参数进行传递的变量
  112. // array_map 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新的值的数组
  113. // implode 函数返回一个由数组元素组合成的字符串
  114. $bin = implode('', array_map(function($item){ return sprintf('%08b', ord($item)); }, str_split(base64_decode(strtr($ticket, '-_', '+/')), 1)));
  115. for ($i = 0; $i < 192; $i += 6) {
  116. $rBit .= $bin[$i];
  117. $eBit .= $bin[$i + 1];
  118. $kBit .= $bin[$i + 2];
  119. $rBit .= $bin[$i + 3];
  120. $uBit .= $bin[$i + 4];
  121. $cBit .= $bin[$i + 5];
  122. }
  123. // substr 函数返回字符串的一部分
  124. // bindec 函数把二进制转换为十进制
  125. $uLen = bindec(substr($rBit, 58, 5));
  126. if ($uLen < 32) {
  127. $uBit = substr($uBit, 0, $uLen);
  128. }
  129. // crc32 函数计算字符串的 32 位 CRC(循环冗余校验)
  130. //32位系统会产生整型溢出,必需输出格式化
  131. // bindec 函数把二进制转换为十进制
  132. // sprintf 把百分号(%)符号替换成一个作为参数进行传递的变量
  133. if (sprintf('%u', crc32($uBit . $eBit . $kBit . $rBit . $bind)) == bindec($cBit)) {
  134. $uid = bindec($uBit);
  135. if ($uid > 0) {
  136. $expire = bindec($eBit);
  137. $key = bindec($kBit);
  138. $durable = ($rBit[63] === '1');
  139. return true;
  140. }
  141. }
  142. return false;
  143. }
  144. /**
  145. * 生成key
  146. *
  147. * @param integer $uid
  148. * @param string $bind
  149. * @param integer $expire
  150. * @return integer
  151. */
  152. protected static function _genKey($uid, $bind, $expire) {
  153. // sprintf 把百分号(%)符号替换成一个作为参数进行传递的变量
  154. // md5 函数计算字符串的 MD5 散列
  155. // crc32 函数计算字符串的 32 位 CRC(循环冗余校验)
  156. return crc32(md5(sprintf('%d|%s|%d', $uid, $bind, $expire), true));
  157. }
  158. /**
  159. * 发送ticket http头
  160. *
  161. * @param string $ticket
  162. * @param integer $uid
  163. * @param integer $ttl
  164. */
  165. protected static function _headerTicket($ticket, $uid, $ttl) {
  166. header(sprintf('Set-Ticket: %s; uid=%d; expires=%s; Max-Age=%d', $ticket, $uid, Request::httpDate(time() + $ttl), $ttl));
  167. }
  168. /**
  169. * 判断格式是否正确
  170. *
  171. * @param string $ticket
  172. * @return boolean
  173. */
  174. protected static function _isTicket($ticket) {
  175. return strlen($ticket) == 32 && strspn($ticket, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_') == 32;
  176. }
  177. /**
  178. * 检查格式是否正确
  179. *
  180. * @param string $ticket
  181. */
  182. public static function checkFormat($ticket) {
  183. if (!self::_isTicket($ticket)) {
  184. return false;
  185. }
  186. }
  187. }

4、Login.php文件代码
  1. <?php
  2. namespace app\admin\controller;
  3. use think\facade\Db;
  4. use ouyangke\Ticket;
  5. class Login
  6. {
  7. public function index()
  8. {
  9. // 跨域请求
  10. header("Access-Control-Allow-Origin:*");
  11. // 一个接口有3段
  12. // 1、获取传值的数据,并且检查这些信息(非必须)
  13. // 2、通过传值进行数据查询,并处理这些数据(非必须),可以自己组装数据
  14. // 3、返回查询的数据结果(必须)
  15. $account = input('post.account');
  16. $password = input('post.password');
  17. $password = md5($password);
  18. $user = Db::table('bew_admin_user')->where('account', $account)->find();
  19. //print_r($user);
  20. if(empty($user)){
  21. echo json_encode(['code'=>1, 'msg'=>'账号不存在']);
  22. exit;
  23. }
  24. if($user['password'] != $password){
  25. echo json_encode(['code'=>1, 'msg'=>'密码错误']);
  26. exit;
  27. }
  28. $user['ticket'] = Ticket::create($user['uid']);
  29. echo json_encode(['code'=>0,'msg'=>'成功','data'=>$user]);
  30. }
  31. }

4、User.vue
  1. <template>
  2. <div>
  3. <el-space wrap style="margin-bottom:20px;">
  4. <el-input v-model="data.search" size="small" placeholder="Type to search" />
  5. <el-button type="" @click="search()">搜索</el-button>
  6. </el-space>
  7. <el-space wrap>
  8. <el-button type="" @click="add()">添加</el-button>
  9. </el-space>
  10. <el-table
  11. :data="data.table"
  12. border
  13. style="width: 100%"
  14. @select="select"
  15. >
  16. <!--
  17. <el-table-column align="right">
  18. </el-table-column>
  19. <el-table-column label="选择" type="selection" />-->
  20. <el-table-column prop="uid" label="ID" min-width="50" />
  21. <el-table-column prop="name" label="Name" />
  22. <el-table-column prop="account" label="账号" />
  23. <el-table-column prop="group" label="部门" />
  24. <el-table-column prop="phone" label="手机号" />
  25. <el-table-column prop="qq" label="QQ">
  26. </el-table-column>
  27. <el-table-column prop="sex" label="性别">
  28. <!--插槽-->
  29. <!-- scope 相当于循环里的一次数据
  30. foreach ( $data['table] as $v)
  31. scope.row 就是相当于是 $v
  32. -->
  33. <template #default="scope">
  34. <span v-if="scope.row.sex == 'mimi'">
  35. 保密
  36. </span>
  37. <span v-else-if="scope.row.sex == 'nan'">
  38. </span>
  39. <span v-else-if="scope.row.sex == 'nv'">
  40. </span>
  41. </template>
  42. </el-table-column>
  43. <el-table-column prop="uid" label="修改" width="160px;">
  44. <template #default="scope">
  45. <el-space wrap>
  46. <!--传点击这条数据的( scope.row )-->
  47. <el-button type="warning" @click="add(scope.row)">修改</el-button>
  48. </el-space>
  49. <el-space wrap>
  50. <el-button type="danger" @click="del(scope.row)">删除</el-button>
  51. </el-space>
  52. </template>
  53. </el-table-column>
  54. </el-table>
  55. <el-pagination
  56. layout="prev, pager, next"
  57. :total="data.total"
  58. :page-size="5"
  59. :default-current-page="1"
  60. @current-change="fun"
  61. />
  62. <!--
  63. total:总条数
  64. page-size:一页显示多少条
  65. -->
  66. <!--添加/修改 弹窗-->
  67. <el-dialog v-model="data.add_form" :title="data.title">
  68. <el-form :model="form" label-width="120px">
  69. <el-form-item label="账号">
  70. <el-input v-model="form.account" />
  71. </el-form-item>
  72. <el-form-item label="密码">
  73. <el-input v-model="form.password" />
  74. </el-form-item>
  75. <el-form-item label="姓名">
  76. <el-input v-model="form.name" />
  77. </el-form-item>
  78. <el-form-item label="部门">
  79. <el-select v-model="form.group_id" class="m-2" placeholder="Select" size="large">
  80. <el-option :label="item.group_name" :value="item.group_id" v-for="(item,index,key) in data.group" />
  81. </el-select>
  82. </el-form-item>
  83. <el-form-item label="手机号">
  84. <el-input v-model="form.phone" />
  85. </el-form-item>
  86. <el-form-item label="QQ号">
  87. <el-input v-model="form.qq" />
  88. </el-form-item>
  89. <el-form-item label="性别">
  90. <el-select v-model="form.sex" class="m-2" placeholder="Select" size="large">
  91. <el-option label="男" value="nan" />
  92. <el-option label="女" value="nv" />
  93. <el-option label="保密" value="mimi" />
  94. </el-select>
  95. </el-form-item>
  96. </el-form>
  97. <template #footer>
  98. <span class="dialog-footer">
  99. <el-button @click="data.add_form = false">取消</el-button>
  100. <el-button type="primary" @click="add_form_json()">
  101. {{ data.title }}
  102. </el-button>
  103. </span>
  104. </template>
  105. </el-dialog>
  106. </div>
  107. </template>
  108. <script>
  109. import { reactive } from "vue"; // 引入动态创建
  110. import { UserLists , UserAdd ,UserDel } from "../network/index";
  111. export default{
  112. setup () {
  113. // 展示数据
  114. const data = reactive({
  115. table : [],
  116. total : 0,
  117. group : [],
  118. search : '',
  119. add_form : false,
  120. title : '添加',
  121. });
  122. // 展示的请求接口
  123. UserLists().then( (e)=>{
  124. data.table = e.data.data.user;
  125. data.total = e.data.data.count;
  126. data.group = e.data.data.group;
  127. console.log(data.table);
  128. })
  129. // 选择事件
  130. const select = (selection,row)=>{
  131. console.log(selection);
  132. console.log(row);
  133. }
  134. // 翻页方法
  135. const fun = (p) => {
  136. UserLists({p:p}).then( (e)=>{
  137. data.table = e.data.data.user;
  138. data.total = e.data.data.count;
  139. })
  140. // Index.php接收传值
  141. }
  142. // 搜索方法
  143. const search = () => {
  144. UserLists({search:data.search}).then( (e)=>{
  145. data.table = e.data.data.user;
  146. data.total = e.data.data.count;
  147. })
  148. }
  149. // 添加 修改
  150. // 展开form表单
  151. const form = reactive({
  152. uid : 0,
  153. account: '',
  154. password: '',
  155. name : '',
  156. group_id: '',
  157. phone : '',
  158. qq: '',
  159. sex: 'nan',
  160. })
  161. // 添加方法,如果为真,打开表单
  162. // 点击接收传uid数据,若有
  163. const add = (e) => {
  164. console.log(e);
  165. data.add_form = true;
  166. if(e){
  167. form.uid = e.uid;
  168. form.account = e.account;
  169. form.password = '';
  170. form.name = e.name;
  171. form.group_id = e.group_id;
  172. form.phone = e.phone;
  173. form.qq = e.qq;
  174. form.sex = e.sex;
  175. data.title = '修改';
  176. }else{
  177. form.uid = 0;
  178. form.account = '';
  179. form.password = '';
  180. form.name = '';
  181. form.group_id = '';
  182. form.phone = '';
  183. form.qq = '';
  184. form.sex = 'nan';
  185. data.title = '添加';
  186. }
  187. }
  188. // 确定提交添加的数据
  189. const add_form_json = () => {
  190. // 需要把数据提交给php接口
  191. // console.log(form);
  192. UserAdd(form).then((e) =>{
  193. // console.log(e);
  194. alert(e.data.msg);
  195. if(e.data.code == 0){
  196. UserLists().then( (e)=>{
  197. // 添加成功后自动刷新数据
  198. data.table = e.data.data.user;
  199. data.total = e.data.data.count;
  200. data.group = e.data.data.group;
  201. console.log(data.table);
  202. // 关闭添加表单
  203. data.add_form = false;
  204. })
  205. }
  206. })
  207. }
  208. // 删除
  209. const del = (e) => {
  210. UserDel({uid:e.uid}).then( (res) => {
  211. alert(res.data.msg);
  212. if( res.data.code == 0 ){
  213. UserLists().then( (e)=>{
  214. // 添加成功后自动刷新数据
  215. data.table = e.data.data.user;
  216. data.total = e.data.data.count;
  217. data.add_form = false;
  218. })
  219. }
  220. })
  221. }
  222. // 数据暴露出去
  223. return {
  224. data,
  225. select,
  226. fun,
  227. search,
  228. add,
  229. form,
  230. add_form_json,
  231. del,
  232. }
  233. }
  234. }
  235. </script>

5、Index.php
  1. <?php
  2. namespace app\admin\controller;
  3. use app\BaseController;
  4. use think\facade\Db;
  5. use ouyangke\Ticket;
  6. class Index extends BaseController
  7. {
  8. public function __construct(){
  9. // 跨域请求
  10. header("Access-Control-Allow-Origin:*");
  11. }
  12. // 首页左侧菜单
  13. public function index(){
  14. $ticket = input('post.ticket');
  15. $uid = Ticket::get($ticket);
  16. if(empty($uid)){
  17. echo json_encode([
  18. 'code' => 1,
  19. 'msg' => '用户已过期'
  20. ]);
  21. exit;
  22. }
  23. $user = Db::table('bew_admin_user')->where('uid',$uid)->find();
  24. if(empty($user)){
  25. echo json_encode([
  26. 'code' => 1,
  27. 'msg' => '请重新登录',
  28. 'data' => [
  29. 'name' => $user['name']
  30. ]
  31. ]);
  32. exit;
  33. }
  34. $group = Db::table('bew_admin_user_group')->where('group_id',$user['group_id'])->find();
  35. if(empty($group)){
  36. echo json_encode([
  37. 'code' => 2,
  38. 'msg' => '用户还没添加组,请联系管理员',
  39. 'data' => [
  40. 'name' => $user['name']
  41. ]
  42. ]);
  43. exit;
  44. }
  45. // 状态为1的全部展示出来,但是1级和2级的都在一起
  46. $tmp = Db::table('bew_admin_sys_menu')->where('status',1)->where('mid','in',json_decode($group['rights'],true))->order('parent_id')->select()->toArray();
  47. //print_r($tmp);
  48. $menu = [];
  49. foreach ($tmp as $v){
  50. if($v['parent_id'] == 0){
  51. // 将 menu为1000或者100的下标 保存到 这个菜单
  52. $menu[ $v['mid'] ] = $v;
  53. } else {
  54. // 现在时二级菜单,它的上一级,就是parent_id,找到它自己的parent_id
  55. // $v['mid'] 一级菜单的下标 $v['parent_id'] 二级菜单的上级下标
  56. $menu[ $v['parent_id'] ] ['son'] [] = $v;
  57. }
  58. }
  59. echo json_encode([
  60. 'code' => 0,
  61. 'msg' => '成功',
  62. 'data' => [
  63. 'menu' => $menu,
  64. 'name' => $user['name'],
  65. ]
  66. ]);
  67. }
  68. /*
  69. public function index()
  70. {
  71. return '<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }</style><div style="padding: 24px 48px;"> <h1>:) </h1><p> ThinkPHP V' . \think\facade\App::version() . '<br/><span style="font-size:30px;">16载初心不改 - 你值得信赖的PHP框架</span></p><span style="font-size:25px;">[ V6.0 版本由 <a href="https://www.yisu.com/" target="yisu">亿速云</a> 独家赞助发布 ]</span></div><script type="text/javascript" src="https://e.topthink.com/Public/static/client.js"></script><think id="ee9b1aa918103c4fc"></think>';
  72. }
  73. */
  74. // =======================管理员方法===============================
  75. // 管理员列表
  76. public function UserLists(){
  77. $p = input('post.p',1);
  78. $search = input('post.search','');
  79. // 在查询数出来的时候,
  80. // $user = Db::table('xpcms_admin')->select()->toArray();
  81. // limit方法、pgae方法
  82. // count方法统计数据库有多少条数据
  83. $where = [];
  84. if(!empty($search)){
  85. $where1 = [['account','like','%'.$search.'%']];
  86. $where2 = [['name','like','%'.$search.'%']];
  87. $where3 = [['phone','like','%'.$search.'%']];
  88. $where = [$where1,$where2,$where3];
  89. }
  90. $count = Db::table('bew_admin_user')->whereOr($where)->where('status','<>','2')->count();
  91. $user = Db::table('bew_admin_user')->whereOr($where)->where('status','<>','2')->page($p,5)->select()->toArray();
  92. // toArray 数组形式,显示时间戳
  93. // 查询所有组
  94. $tmp = Db::table('bew_admin_user_group')->where('status',1)->select()->toArray();
  95. $group = [];
  96. foreach($tmp as $v){
  97. $group[$v['group_id']] = $v;
  98. }
  99. foreach($user as &$u){
  100. $u['time_add_s'] = date('Y-m-d H:i:s',$u['time_add']);
  101. if($u['group_id'] != 0 ){
  102. $u['group'] = $group [ $u['group_id'] ] ['group_name'];
  103. }
  104. }
  105. $arr = [
  106. 'count' => $count,
  107. 'user' => $user,
  108. 'group' => $group
  109. ];
  110. // php接口、只能有一次输出结果值
  111. echo json_encode([
  112. 'code' => 0,
  113. 'msg' => '成功',
  114. 'data' => $arr
  115. ]);
  116. }
  117. // 添加&修改管理员,接收数据
  118. public function UserAdd(){
  119. $post = input('post.');
  120. $data = [
  121. 'account' => $post['account'],
  122. 'name' => $post['name'],
  123. 'group_id' => $post['group_id'],
  124. 'phone' => $post['phone'],
  125. 'qq' => $post['qq'],
  126. 'sex' => $post['sex'],
  127. 'time_last' => time(),
  128. ];
  129. // 查询单条数据
  130. $user = Db::table('bew_admin_user')->where('account',$post['account'])->find();
  131. if ( $post['uid'] == 0 ){
  132. // 判断查询出来的用户是否存在,若存在就退出,否则新建
  133. if(!empty($user)){
  134. echo json_encode([
  135. 'code' => 1,
  136. 'msg' => '账号已存在'
  137. ]);
  138. exit;
  139. }
  140. // 如果为0.就添加
  141. $data['password'] = md5($post['password']);
  142. $data['time_add'] = time();
  143. $ret = Db::table('bew_admin_user')->insert($data);
  144. } else {
  145. // 判断查询出来的用户名是否存在,且是不等于查询出来的uid,则修改
  146. if(!empty($user) && $post['uid'] != $user['uid']){
  147. echo json_encode([
  148. 'code' => 1,
  149. 'msg' => '账号已存在'
  150. ]);
  151. exit;
  152. }
  153. // 如果不为0 就修改
  154. if(!empty($post['password'])){
  155. $data['password'] = md5($post['password']);
  156. }
  157. $ret = Db::table('bew_admin_user')->where('uid', $post['uid'])->update($data);
  158. }
  159. // 添加&修改 后输出结果
  160. if( $post['uid'] == 0 ){
  161. if(empty($ret)){
  162. echo json_encode([
  163. 'code' => 1,
  164. 'msg' => '添加失败,请重试'
  165. ]);
  166. exit;
  167. };
  168. echo json_encode([
  169. 'code' => 0,
  170. 'msg' => '添加成功'
  171. ]);
  172. } else {
  173. if(empty($ret)){
  174. echo json_encode([
  175. 'code' => 1,
  176. 'msg' => '修改失败,请重试'
  177. ]);
  178. exit;
  179. };
  180. echo json_encode([
  181. 'code' => 0,
  182. 'msg' => '修改成功'
  183. ]);
  184. }
  185. }
  186. // 删除方法
  187. public function UserDel(){
  188. $uid = input('post.uid',0);
  189. if($uid ==0){
  190. echo json_encode([
  191. 'code' => 1,
  192. 'msg' => '请选择要删除的账号'
  193. ]);
  194. exit;
  195. }
  196. $del = Db::table('bew_admin_user')->where('uid', $uid)->update([
  197. 'status'=>2,
  198. 'time_last' => time(),
  199. ]);
  200. if(empty($del)){
  201. echo json_encode([
  202. 'code' => 1,
  203. 'msg' => '删除失败,请重试'
  204. ]);
  205. exit;
  206. }
  207. echo json_encode([
  208. 'code' => 0,
  209. 'msg' => '删除成功'
  210. ]);
  211. exit;
  212. }
  213. // =======================管理组方法===============================
  214. // 管理组列表接口
  215. public function GroupLists(){
  216. $p = input('post.p',1);
  217. $search = input('post.search','');
  218. $where = [];
  219. if(!empty($search)){
  220. $where[] = ['group_name','like','%'.$search.'%'];
  221. }
  222. $count = Db::table('bew_admin_user_group')->where($where)->count();
  223. $group = Db::table('bew_admin_user_group')->where($where)->page($p,8)->select()->toArray();
  224. foreach($group as &$u){
  225. $u['time_add_s'] = date('Y-m-d H:i:s',$u['time_add']);
  226. }
  227. // =================================================================================================
  228. // 新增权限管理
  229. // 状态为1的全部展示出来,但是1级和2级的都在一起
  230. $tmp = Db::table('bew_admin_sys_menu')->where('status',1)->order('parent_id')->select()->toArray();
  231. $menu = [];
  232. foreach ($tmp as $v){
  233. if($v['parent_id'] == 0){
  234. // 将 menu为1000或者100的下标 保存到 这个菜单
  235. $menu[ $v['mid'] ] = $v;
  236. } else {
  237. // 现在时二级菜单,它的上一级,就是parent_id,找到它自己的parent_id
  238. // $v['mid'] 一级菜单的下标 $v['parent_id'] 二级菜单的上级下标
  239. $menu[ $v['parent_id'] ] ['son'] [] = $v;
  240. }
  241. }
  242. // =================================================================================================
  243. $arr = [
  244. 'count' => $count,
  245. 'group' => $group,
  246. 'menu' => $menu,
  247. ];
  248. // php接口、只能有一次输出结果值
  249. echo json_encode([
  250. 'code' => 0,
  251. 'msg' => '成功',
  252. 'data' => $arr
  253. ]);
  254. }
  255. // 添加管理组
  256. public function GroupAdd(){
  257. $post = input('post.');
  258. $group = Db::table('bew_admin_user_group')->where('group_name', $post['group_name'])->find();
  259. if($post['group_id'] == 0){
  260. if(!empty($group)){
  261. echo json_encode([
  262. 'code' => 1,
  263. 'msg' => '添加失败,部门已存在'
  264. ]);
  265. exit;
  266. }
  267. $ret = Db::table('bew_admin_user_group')->insert([
  268. 'group_name' => $post['group_name'],
  269. 'status' => $post['status'],
  270. 'rights' => json_encode($post['checkList']),
  271. 'time_add' => time()
  272. ]);
  273. } else {
  274. if(!empty($group) && $group['group_id'] != $post['group_id']){
  275. echo json_encode([
  276. 'code' => 1,
  277. 'msg' => '修改失败,部门已存在'
  278. ]);
  279. exit;
  280. }
  281. $ret = Db::table('bew_admin_user_group')->where('group_id',$post['group_id'])->update([
  282. 'group_name' => $post['group_name'],
  283. 'status' => $post['status'],
  284. 'rights' => json_encode($post['checkList']),
  285. 'time_add' => time(),
  286. 'time_last' => time()
  287. ]);
  288. }
  289. if($post['group_id'] == 0 ){
  290. if(empty($ret)){
  291. echo json_encode([
  292. 'code' => 1,
  293. 'msg' => '添加失败,请重试'
  294. ]);
  295. exit;
  296. }
  297. echo json_encode([
  298. 'code' => 0,
  299. 'msg' => '添加成功'
  300. ]);
  301. } else {
  302. if(empty($ret)){
  303. echo json_encode([
  304. 'code' => 1,
  305. 'msg' => '修改失败,请重试'
  306. ]);
  307. exit;
  308. }
  309. echo json_encode([
  310. 'code' => 0,
  311. 'msg' => '修改成功'
  312. ]);
  313. }
  314. }
  315. // 删除管理组
  316. public function GroupDel(){
  317. $group_id = input('post.group_id',0);
  318. if($group_id == 0){
  319. echo json_encode([
  320. 'code' => 1,
  321. 'msg' => '请选择要删除的管理组'
  322. ]);
  323. exit;
  324. }
  325. $ret = Db::table('bew_admin_user_group')->where('group_id',$group_id)->update([
  326. 'status' => 0,
  327. 'time_last' => time()
  328. ]);
  329. if(empty($ret)){
  330. echo json_encode([
  331. 'code' => 1,
  332. 'msg' => '删除失败,请重试'
  333. ]);
  334. exit;
  335. }
  336. echo json_encode([
  337. 'code' => 0,
  338. 'msg' => '删除成功'
  339. ]);
  340. }
  341. // =======================菜单方法===============================
  342. /**
  343. * 一般分php文件,是根据功能来分
  344. * 用户相关放一个文件,并且统一处理
  345. * 用户个人中心、订单列表、订单详情、充值功能、登录日志等
  346. * 登录、注册放在一个文件,用户的未登录文件,统一处理的
  347. *
  348. * @return void
  349. */
  350. public function MenuLists(){
  351. $p = input('post.p',1);
  352. // 接收数据 mid
  353. $mid = input('post.mid',0);
  354. $count = Db::table('bew_admin_sys_menu')->where('parent_id',$mid)->count();
  355. $menu = Db::table('bew_admin_sys_menu')->where('parent_id',$mid)->order('sort DESC')->page($p,5)->select()->toArray();
  356. //需要把一级菜单获取出来,作为添加时选择项
  357. $ss = Db::table('bew_admin_sys_menu')->where('parent_id',0)->where('type',0)->order('sort DESC')->select()->toArray();
  358. $arr = [
  359. 'menu' => $menu,
  360. 'count' => $count,
  361. 'ss' => $ss,
  362. ];
  363. echo json_encode([
  364. 'code' => 0,
  365. 'msg' => '成功',
  366. 'data' => $arr
  367. ]);
  368. }
  369. // 添加 修改 菜单方法
  370. public function MenuAdd(){
  371. $post = input('post.');
  372. $data = [
  373. 'label' => $post['label'],
  374. 'parent_id' => $post['parent_id'],
  375. 'type' => $post['type'],
  376. 'src' => $post['src'],
  377. 'sort' => $post['sort'],
  378. 'status' => $post['status'],
  379. 'time_last' => time(),
  380. ];
  381. if($post['mid'] == 0){
  382. $ret = Db::table('bew_admin_sys_menu')->insert($data);
  383. } else {
  384. $ret = Db::table('bew_admin_sys_menu')->where('mid',$post['mid'])->update($data);
  385. }
  386. if($post['mid'] == 0 ){
  387. if(empty($ret)){
  388. echo json_encode([
  389. 'code' => 1,
  390. 'msg' => '添加失败,请重试'
  391. ]);
  392. exit;
  393. }
  394. echo json_encode([
  395. 'code' => 0,
  396. 'msg' => '添加成功'
  397. ]);
  398. } else {
  399. if(empty($ret)){
  400. echo json_encode([
  401. 'code' => 1,
  402. 'msg' => '修改失败,请重试'
  403. ]);
  404. exit;
  405. }
  406. echo json_encode([
  407. 'code' => 0,
  408. 'msg' => '修改成功'
  409. ]);
  410. }
  411. }
  412. // 删除菜单方法
  413. public function MenuDel(){
  414. $mid = input('post.mid',0);
  415. if($mid == 0){
  416. echo json_encode([
  417. 'code' => 1,
  418. 'msg' => '请选择要删除的菜单'
  419. ]);
  420. exit;
  421. }
  422. $del = Db::table('bew_admin_sys_menu')->where('mid',$mid)->update([
  423. 'status' => 2,
  424. 'time_last' => time(),
  425. ]);
  426. if(empty($del)){
  427. echo json_encode([
  428. 'code' => 1,
  429. 'msg' => '删除失败,请重试'
  430. ]);
  431. exit;
  432. }
  433. echo json_encode([
  434. 'code' => 0,
  435. 'msg' => '删除菜单成功'
  436. ]);
  437. }
  438. public function hello($name = 'ThinkPHP6')
  439. {
  440. return 'hello,' . $name;
  441. }
  442. }

6、运行截图6.1、登录退出


6.2、用户部门


【转自:美国cn2服务器 http://www.558idc.com/mg.html欢迎留下您的宝贵建议】