小系统bug修复与功能增强--系统篇

先看看系统界面,就2个主要界面

第一个是登录界面

第二个是登录后主体界面

前端用TypeScript+Vue3+ElementPlus写,后端用php8+thinkphp8

第一点,功能增强点,原来的维持组件间的登录状态提升为用pinia来改写

main.js文件变动如下

// main.js

import { createApp } from 'vue'

import { createPinia } from 'pinia'

import piniaPersist from 'pinia-plugin-persist'

import ElementPlus from 'element-plus'

import 'element-plus/dist/index.css'

import { router } from './router'

import App from './App.vue'

const pinia = createPinia()

pinia.use(piniaPersist)

const app = createApp(App)

app.use(pinia)

app.use(ElementPlus)

app.use(router)

app.mount('#app')

新建tokener.js文件

// stores/tokener.js

import { defineStore } from 'pinia'

export const useTokenerStore = defineStore('tokener', {

state: () => {

return { token: 0 }

},

actions: {

setToken(value) {

this.token = value

},

},

persist: {

enabled: true,

strategies: [

{ storage: localStorage, paths: ['token'] },

],

}

})

pinia默认使用sessionStorage来存储,这里使用了localStorage,也可以为不同的变量混用存储方式

然后看看在新写的展示图片列表的地方是怎么使用存储好的token令牌的,这也是第二个新增点,其他地方用法同理

<script lang="ts" setup>

import { onMounted, ref } from 'vue'

import axios from 'axios';

import { useTokenerStore } from '../../stores/tokener'

const tokener = useTokenerStore()

onMounted(() => {

console.log(`the component is now mounted.`)

axios.get('http://admin.am8.com/index/getList', {

params: {

token: tokener.token,

}

})

.then(function (response) {

console.log(response);

if (response.data.code === 1) {

tableData.value = response.data.data

} else {

if (response.data.sub_code === 0) {

tokener.$reset()

}

}

})

.catch(function (error) {

console.log(error);

});

})

const tableData = ref([])

</script>

首先需要引入tokener.js文件

import { useTokenerStore } from '../../stores/tokener'

然后是获取存储的对象

const tokener = useTokenerStore()

最后是直接通过对象引用存储好的token值即可

params: {

token: tokener.token,

}

另外还有一个地方重置了token对象,这时候整个对象的值都会恢复成初始值

if (response.data.sub_code === 0) {

tokener.$reset()

}

我们继续看看展示图片列表的视图部分,这个展示图片的模块是新增的

<template>

<el-table :data="tableData" style="width: 100%">

<el-table-column type="index" width="50" />

<el-table-column label="Name" width="180">

<template #default="scope">

<el-image

style="width: 100px; height: 100px"

:src="scope.row.name"

fit="fill"></el-image>

</template>

</el-table-column>

</el-table>

</template>

以表格的方式展示了序列数和图片列表,结合上面逻辑处理部分,就能看到tableData是在哪里来的

if (response.data.code === 1) {

tableData.value = response.data.data

}

后端返回成功时,初始化了tableData的值

后端接口如下

public function getList()

{

$list = Head2::select();

$list2 = [];

foreach ($list as $key => $value) {

$search = '\\';

$replace = '/';

replacedString = str_replace(search, $replace, $value->name);

list\[key]['name'] = Config::get('app.server_url').'storage/'.$replacedString;

}

return mySuccessResponse($list);

}

第三个新增点是将前端代码打包进后端展示

打包就在项目中执行npm run build,生成dist文件夹,复制dist文件夹放到thinkphp8的public文件夹里面,这里我在public文件夹下新增一个admin文件夹,然后再把dist文件夹放到admin文件夹中,想法是项目应该是可以支持多个单文件组件的模式。比如后面计划前台又用另一个单文件组件来写。然后把dist文件夹中的index.html文件剪切到thinkphp8的视图中,想法是前端页面应该可以既用vue3项目写也可以用thinkphp8模板来写,混写。兼容各种技术来实现前端

编写视图接口

use think\facade\View;

class Anonym {

public function index()

{

return View::fetch();

}

...

}

视图结构如下

后端是自动多应用模式,这是一个admin应用的视图结构,那么在浏览器就可以访问http://admin.am8.com/Anonym/index进入到登录页面,admin.am8.com是我配置的映射到admin应用下的域名,大家各自配各自的

然后index.html页面需要稍微调整一下路径

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<link rel="icon" href="/admin/dist/favicon.ico" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<title>Vite App</title>

<script type="module" crossorigin src="/admin/dist/assets/index-BBtu1Sxt.js"></script>

<link rel="stylesheet" crossorigin href="/admin/dist/assets/index-DbFK1zW7.css">

</head>

<body>

<div id="app"></div>

</body>

</html>

前面就说了在public文件夹下新建admin文件夹然后再放入dist文件夹,这里的修改就是为了引用对前端的资源文件

第四个改动点是将BaseController里面的登录检查移到应用中间件中实现,原因是因为继承的基础控制器在未登录情况下不能直接返回json对象到前端,需要用die等方法处理成json字符串。如果处理成json字符串,前端又需要解码json字符串成json对象。而且thinkphp8也不推荐使用die等中断程序的方法。

新增admin应用中间件,并且修改代码如下

public function handle($request, \Closure $next)

{

$array = ['anonym/login', 'anonym/index', 'Anonym/index'];

$value = $request->pathinfo();

$sign = true;

foreach ($array as $k => $v) {

if ($v === $value) {

$sign = false;

break;

}

}

if ($sign) {

$exist = AdminToken::where([

'token' => request()->param('token'),

])->find();

if ($exist !== null) {

// 获取当前时间的时间戳

$now = time();

timestamp = intval(exist->update_time);

// 设定1小时的秒数

$oneHourInSeconds = 3600;

if (($now - $timestamp) > $oneHourInSeconds) {

return myFailResponse(0, '登录状态已过期');

}

} else {

return myFailResponse(0, '未登录');

}

}

return next(request);

}

这里没用inArray来实现,因为那个方法判断有时不准确,改成如下写法

$array = ['anonym/login', 'anonym/index', 'Anonym/index'];

$value = $request->pathinfo();

$sign = true;

foreach ($array as $k => $v) {

if ($v === $value) {

$sign = false;

break;

}

}

if ($sign) {

...

}

这样写是为了判断路径,如果路径属于以上几种路径就不用检查登录状态,分别是登录请求、登录界面显示、还有里面主体界面显示。

第五个改动点,将菜单默认的选中项改为动态路由,这是为了页面刷新时能相应地在菜单项选中项也能对应上

<el-menu

router

:default-active="$route.fullPath"

class="el-menu-vertical-demo"

@open="handleOpen"

@close="handleClose"

>

...

</el-menu>

注意看:default-active="$route.fullPath",就是这个改动

第六个改动点,将前端路由由H5模式改为Hash模式

import { createRouter, createWebHashHistory } from 'vue-router'

history: createWebHashHistory(),

这是因为index.html放在thinkphp视图里面,访问时肯定会经过后端路由,为了不影响到前端路由,故前端改用hash模式

相关推荐
ggdpzhk9 分钟前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
活宝小娜5 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点5 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow5 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
刚刚好ā6 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
黑客Ash6 小时前
【D01】网络安全概论
网络·安全·web安全·php
->yjy6 小时前
计算机网络(第一章)
网络·计算机网络·php
会发光的猪。8 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
阳光帅气男孩8 小时前
PhpSpreadsheet导出图片
php
天下代码客8 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js