18-经过actions方法封装请求以及补充计算属性

news/2026/1/21 10:39:18/文章来源:https://www.cnblogs.com/gccbuaa/p/19510348

首页菜单添加补充计算属性

<template><div class="home-container"><div class="home-header">头部</div><div class="home-menu"><el-menuactive-text-color="#ffd04b"background-color="#545c64"class="el-menu-vertical-demo"default-active="2"text-color="#fff":unique-opened="true":router="true"><el-sub-menu v-for="menu in newMenus" :index="menu.id"><template #title><span>{{ menu.title }}</span></template><template v-for="submenu in menu.children"><el-menu-item v-if="submenu.hidden === 0" :index="submenu.id">{{ submenu.title }}</el-menu-item></template></el-sub-menu></el-menu></div>
<div class="home-content">右侧内容</div>
</div>
</template>
<script lang='ts' setup>
/**
{
id: {
title: "一级菜单",
children: [
{title: "二级菜单"},
{title: "二级菜单"},
{title: "二级菜单"},
{title: "二级菜单"},
]
}
}
* */
import { computed } from 'vue'
import { useStore } from 'vuex'
interface MenuObj {
id: string
title: string
parentId: string
hidden: 0 | 1
children?: MenuObj[]
}
interface NewMenus {
[key: string]: MenuObj
}
const store = useStore();
const newMenus = computed<NewMenus>(() => store.getters.getNewMenus);console.log('newMenus---------home-----------', newMenus)
</script><style lang='less' scoped>.home-container {position: relative;height: 100%;.home-header {height: 70px;background-color: goldenrod;}.home-menu {position: absolute;top: 70px;left: 0;bottom: 0;width: 250px;background-color: #a37676;}.home-content {position: absolute;top: 70px;right: 0;left: 250px;bottom: 0;background-color: skyblue;}}
</style>

通过actions方法封装用户信息请求

import { createStore } from 'vuex'
import { type App } from 'vue'
import { getAdminInfoApi } from '@/api/login'
interface MenuObj {
id: string
parentId: string
children?: MenuObj[]
}
interface State {
menus: MenuObj[]
}
interface NewMenus {
[key: string]: Partial<MenuObj>}const store = createStore<State>({state() {return {menus: []}},getters: {getNewMenus(state) {const newMenus: NewMenus = {}const menus = state.menusfor (let i = 0; i < menus.length; i++) {const menu = menus[i] as MenuObjif (menu.parentId === '0') {// 一级菜单:初始化 children 为空数组,方便后续 pushnewMenus[menu.id] = {...menus[i],children: newMenus[menu.id]?.children || []}} else {// 子级菜单:根据 parentId 找到对应的父级const parentId = menu.parentIdnewMenus[parentId] = newMenus[parentId] || {}newMenus[parentId].children = newMenus[parentId].children || []newMenus[parentId].children.push(menu)}}console.log('newMenus--------------------', newMenus)return newMenus;}},mutations: {updateMenus(state, menus) {console.log('updateMenus--->', state, menus)state.menus = menus}},actions: {getAdminInfoApi({ commit }) {return new Promise((resolve, reject) => {getAdminInfoApi().then((res) => {if(res.code === 200) {// 用户信息存储到vuexcommit('updateMenus', res.data.menus)resolve(res.data)}else {reject(res)}})})}},modules: {}})export const initStore = (app: App<Element>) => {app.use(store)}export default store

使用这个封装的方法改造路由

import {
createRouter,
createWebHashHistory,
type RouteRecordRaw
} from 'vue-router'
import { type App } from 'vue'
import store from '../store'
import Cookie from 'js-cookie'
const routes: RouteRecordRaw[] = [
{
path: '/',
redirect: '/login'
},
{
path: '/login',
name: 'login',
component: () => import('../views/login/login.vue')
},
{
path: '/home',
name: 'home',
component: () => import('../views/home/home.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes // 路由配置
})
// 前置导航守卫
router.beforeEach((to, from, next) => {
// 1、token && vuex里面的 menus 为空
const token = Cookie.get('token')
console.log(store)
if(token && store.state.menus.length === 0) {
console.log('menus为空')
// 获取用户信息
store.dispatch('getAdminInfoApi');
}
next()
})
export const initRouter = (app: App<Element>) => {app.use(router)}

使用这个封装的方法改造登录页面

<template><div class="login-rule-form"><div class="content"><div class="title">商品管理系统</div><el-form ref="ruleFormRef" :model="ruleForm" status-icon :rules="rules" label-width="60px"><el-form-item prop="username" label="账号"><el-input v-model="ruleForm.username" type="text" placeholder="请输入账号"/></el-form-item><el-form-item prop="pwd" label="密码"><el-input v-model="ruleForm.pwd" type="password" placeholder="请输入密码"/></el-form-item><el-form-item><el-button type="primary" @click="loginFn()">登录</el-button></el-form-item></el-form></div></div>
</template><script lang='ts' setup>import { onMounted, reactive, ref } from 'vue'import { adminLoginApi, getAdminInfoApi } from '@/api/login'import Cookie from 'js-cookie'import { ElMessage } from 'element-plus'import { useRouter } from 'vue-router'import { useStore } from 'vuex'let ruleForm = reactive({username: "",pwd: ""})// 自定义密码校验规则(_variable - 未使用的变量 ts不校验)const validatePwd = (_rule: unknown, value: string | undefined, callback: (msg?: string) => void) => {if(!value) {callback('密码不能为空')} else {callback()}}// 校验规则let rules = reactive({username: [{required: true,message: '用户名不能为空',trigger: 'blur'}],pwd: [{required: true,validator: validatePwd,trigger: 'blur'}]})// 获取el-form组件对象let ruleFormRef = ref()// 获取项目路由对象let router = useRouter()// 获取当前项目的vuex对象let store = useStore()onMounted(() => {// console.log('组件实例:', ruleFormRef.value)// console.log('DOM 元素:', ruleFormRef.value?.$el)})// 点击登录const loginFn = () => {ruleFormRef.value.validate().then(() => {adminLoginApi({username: ruleForm.username,password: ruleForm.pwd}).then((res) => {if(res.code === 200) {// 储存cookieCookie.set('token', res.data.token, { expires: 7 })ElMessage.success('登录成功')// 获取用户信息store.dispatch('getAdminInfoApi').then(res => {// 跳转home页面router.push('/home')})} else {ElMessage.error('登录报错')}})}).catch(() => {console.log('校验不通过')})}
</script><style lang='less' scoped>.login-rule-form {width: 100%;height: 100vh;display: flex;justify-content: center;align-items: center;background-color: #f5f5f5;overflow: hidden;box-sizing: border-box;margin: 0;padding: 0;.content {width: 420px;padding: 40px;background-color: #fff;border-radius: 8px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);box-sizing: border-box;.title {font-size: 28px;font-weight: bold;text-align: center;margin-bottom: 30px;}}:deep(.el-form) {.el-form-item {margin-bottom: 20px;&:last-child {margin-bottom: 0;}}.el-button {width: 100%;}}}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1194011.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1小时打造KB2533623漏洞检测原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 快速开发一个KB2533623检测工具原型&#xff0c;要求&#xff1a;1. 系统信息采集 2. 补丁状态检查 3. 风险等级评估 4. 简易修复建议 5. 结果导出功能。使用Python开发控制台应用…

2026年工程咨询公司排名,中恒通达项目管理公司值得推荐吗?

本榜单依托全维度工程行业调研与真实合作口碑,深度筛选出五家标杆工程咨询企业,为工程从业者及创业团队提供客观选型依据,助力精准匹配适配的资质合作与项目管理伙伴。 TOP1 推荐:中恒通达项目管理有限公司 推荐指…

亲测有效:用verl在Qwen模型上跑PPO全流程分享

亲测有效&#xff1a;用verl在Qwen模型上跑PPO全流程分享 最近在尝试使用强化学习&#xff08;RL&#xff09;对大语言模型进行后训练优化&#xff0c;目标是提升其在特定任务上的推理能力。经过一番调研和测试&#xff0c;我选择了字节跳动火山引擎团队开源的 verl 框架&…

2026年1月市面上乳化剂推荐榜:CO436/A501/COPS -1/SR10/LCN118等不同乳化剂厂家哪家好深入剖析!

2026年1月【乳化剂】优质之选:A501与CO43深入剖析 在化工领域,【乳化剂】作用关键,像 2A1阴离子乳化剂、CO436乳液聚合乳化剂、A501造纸用丁苯胶乳乳化剂、COPS - 1反应型乳化剂、SR10耐水乳化剂、LCN118环保非离子…

echart 格式化水平坐标 tooltip数据

在做图表的时候,总是会遇到提示的内容和水平的内容格式不统一。然后每次都要做两次处理,鼠标滑过的提示x坐标内容 和 水平x显示的刻度要不一样,或者把外部的数据传入到内部进行切割。 更好的做法,提示的显示全部,…

Hutool + AI:如何用智能工具提升Java开发效率

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个Java项目&#xff0c;使用Hutool工具库结合AI能力实现以下功能&#xff1a;1. 自动生成常用工具类代码模板 2. 智能识别并处理常见异常场景 3. 根据数据库表结构自动生成C…

AlexNet vs 传统CV算法:效率对比实验

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 构建一个对比测试平台&#xff0c;比较AlexNet与传统CV方法&#xff08;如SIFTSVM&#xff09;在图像分类任务中的表现。包括&#xff1a;1) 相同测试数据集&#xff1b;2) 准确率…

2026年无缝钢管供应商综合评估与推荐榜单研究报告

在工业制造与基础设施建设领域,无缝钢管作为关键的基础材料,其供应链的稳定性、产品的可靠性直接关系到下游项目的成本、进度与安全。当前,采购决策者普遍面临一个核心挑战:在众多供应商中,如何精准识别那些不仅能…

AI如何解决‘连接被阻止‘的常见开发问题

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个能够自动诊断连接被阻止错误的AI工具。该工具应能&#xff1a;1. 分析浏览器控制台错误日志&#xff1b;2. 识别CORS策略、混合内容安全策略等常见原因&#xff1b;3. 根据…

2026年细胞器取样系统/细胞器提取系统/细胞器细胞取样系统/细胞器提取分析系统品牌大盘点:从入门到精通

随着精准医学、单细胞组学、合成生物学和再生医学等前沿领域的迅猛发展,对细胞内部结构——尤其是细胞器(如线粒体、溶酶体、内质网、高尔基体、细胞核等)的精细操作与分析需求日益增长。传统基于群体细胞的批量处理…

QOJ #1823. Permutation CFG

现在网上找不到题解,QOJ上的论文看不了了,来贡献一篇。 题目链接 记 \(U(x, s)\) 表示从 \(x\) 一个单独的数开始,进行 \(s\) 次操作后得到的序列。 举个例子,若 \(p = \{1, 4, 3, 2\}\),那么 \(U(4, 0) = \{4\},…

AI配音降本增效:CosyVoice2-0.5B批量生成实战指南

AI配音降本增效&#xff1a;CosyVoice2-0.5B批量生成实战指南 1. 引言&#xff1a;为什么你需要关注AI语音合成&#xff1f; 你有没有遇到过这样的问题&#xff1a;做短视频需要配音&#xff0c;但请人录一次成本高、周期长&#xff1b;写好的文章想转成有声内容&#xff0c;…

Hunyuan-MT-7B连接超时?反向代理配置修复网页访问问题

Hunyuan-MT-7B连接超时&#xff1f;反向代理配置修复网页访问问题 1. 问题背景&#xff1a;Hunyuan-MT-7B-WEBUI 访问异常 你是不是也遇到过这种情况&#xff1a;刚部署完腾讯混元开源的 Hunyuan-MT-7B 翻译模型&#xff0c;满怀期待地点击“网页推理”按钮&#xff0c;结果浏…

AI搜索优化哪家技术强?2026年AI搜索优化推荐与排名,解决语义理解与适配效率痛点

随着生成式人工智能深度重塑用户获取信息与决策的路径,AI搜索优化已从营销领域的创新尝试,演变为决定品牌未来五年市场地位的关键战略。数据显示,2025年中国AI搜索优化相关市场规模增长迅猛,大量企业已将其纳入核心…

零基础学REQABLE:10分钟掌握抓包核心技巧

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个交互式REQABLE新手教程应用&#xff0c;通过步骤式引导教会用户完成基础抓包操作。包含模拟网络环境&#xff0c;让用户可以在安全环境中练习抓包。要求每个步骤有图文说明…

Paraformer-large法律行业应用:庭审录音精准转写实战案例

Paraformer-large法律行业应用&#xff1a;庭审录音精准转写实战案例 1. 庭审场景下的语音转写痛点 在司法实践中&#xff0c;庭审过程往往持续数小时&#xff0c;涉及大量口语化表达、专业术语和多人交替发言。传统的人工记录方式不仅耗时耗力&#xff0c;还容易遗漏关键信息…

Git作者信息总延迟/错位?VS Code插件兼容性避坑清单(基于127个真实项目验证)

第一章&#xff1a;Git作者信息总延迟/错位&#xff1f;VS Code插件兼容性避坑清单&#xff08;基于127个真实项目验证&#xff09;在参与开源协作与团队开发过程中&#xff0c;频繁出现 Git 提交记录中作者信息延迟或错位的问题&#xff0c;尤其在使用 VS Code 及其生态插件时…

YOLO11为何难部署?一文详解常见问题与避坑指南

YOLO11为何难部署&#xff1f;一文详解常见问题与避坑指南 YOLO11作为目标检测领域的新一代算法&#xff0c;凭借其在精度和速度上的双重提升&#xff0c;吸引了大量开发者关注。然而&#xff0c;许多人在尝试将其部署到实际项目中时却发现&#xff1a;理想很丰满&#xff0c;…

张三的声音+李四的情绪?IndexTTS 2.0神奇组合实验

张三的声音李四的情绪&#xff1f;IndexTTS 2.0神奇组合实验 你有没有遇到过这种情况&#xff1a;想给一段动画配音&#xff0c;却找不到声音和情绪都匹配的演员&#xff1f;或者&#xff0c;你想让虚拟主播“愤怒地喊出一句台词”&#xff0c;结果AI生成的语音语气平淡得像在…

【VSCode侧边栏消失怎么办】:5分钟快速找回的3种实用方法

第一章&#xff1a;VSCode侧边栏消失的常见原因分析 Visual Studio Code&#xff08;VSCode&#xff09;作为广受欢迎的代码编辑器&#xff0c;其界面布局的稳定性对开发效率至关重要。侧边栏是文件资源管理、搜索、源码控制等核心功能的入口&#xff0c;一旦意外消失&#xff…