使用 Vue3 + Pinia + Ant Design Vue3 搭建后台管理系统
Vue3 & Ant Design Vue3基础
nodejs版本要求:node-v18.16.0-x64
nodejs基础配置
npm -v
node -vnpm config set prefix "D:\software\nodejs\node_global"
npm config set cache "D:\software\nodejs\node_cache"npm config get registry
npm config set registry https://registry.npm.taobao.org
安装Vue3
npm install @vue/cli -g
vue --version#npm install @vue/cli@5.0.8 -g 安装指定版本
#npm uninstall @vue/cli -g
使用Vue创建前端项目
npm create vue@latest
√ Project name: ...web
√ Add TypeScript? ... No
√ Add JSX Support? ... No
√ Add Vue Router for Single Page Application development? ... Yes
√ Add Pinia for state management? ... Yes
√ Add Vitest for Unit Testing? ... No
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... Yes
√ Add Prettier for code formatting? ... Yes
启动前端项目
cd web
npm install
npm run dev
浏览器访问:http://localhost:5173
修改端口号,修改配置 vite.config.js
export default defineConfig({server: {port: 9000},plugins: [vue(),],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}}
})
再次访问:http://localhost:9000/
https://antdv.com/components/overview-cn
Ant Design Vue官方文档
安装Ant Design Vue
npm install ant-design-vue --save
npm install --save @ant-design/icons-vue#自动按需引入组件
npm install unplugin-vue-components -D
修改配置文件vite.config.js
import {fileURLToPath, URL} from 'node:url'import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import {AntDesignVueResolver} from 'unplugin-vue-components/resolvers';// https://vitejs.dev/config/
export default defineConfig({server: {port: 9000},plugins: [vue(),Components({resolvers: [AntDesignVueResolver({importStyle: false, // css in js}),],}),],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}}
})
修改main.js
import './assets/main.css'import { createApp } from 'vue'
import { createPinia } from 'pinia'
import Antd from 'ant-design-vue';import App from './App.vue'
import router from './router'
import 'ant-design-vue/dist/reset.css';const app = createApp(App)app.use(createPinia())
app.use(router)
app.use(Antd)app.mount('#app')
添加一个测试页面
<script setup>
import {ZoomOutOutlined} from "@ant-design/icons-vue";
</script><template><div class="about"><h1>This is an about page</h1><a-button>测试</a-button><br><ZoomOutOutlined /></div>
</template><style>
</style>
Antd栅格把页面平均分成24份
<template><a-row><a-col :span="24">col</a-col></a-row><a-row><a-col :span="12">col-12</a-col><a-col :span="12">col-12</a-col></a-row><a-row><a-col :span="8">col-8</a-col><a-col :span="8">col-8</a-col><a-col :span="8">col-8</a-col></a-row><a-row><a-col :span="6">col-6</a-col><a-col :span="6">col-6</a-col><a-col :span="6">col-6</a-col><a-col :span="6">col-6</a-col></a-row>
</template>
使用Pinia管理用户状态
刷新页面,Pinia中的数据会丢失,使用Pinia插件做数据持久化
npm install --save zipson
npm install --save pinia-plugin-persistedstate
修改main.js
import './assets/main.css'import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import Antd from 'ant-design-vue';import App from './App.vue'
import router from './router'
import 'ant-design-vue/dist/reset.css';const app = createApp(App)
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate);//pinia数据持久化app.use(pinia)
app.use(router)
app.use(Antd)app.mount('#app')
使用Pinia保存用户状态,添加文件src/stores/user.js
import {reactive} from 'vue'
import {defineStore} from 'pinia'
import {stringify, parse} from 'zipson'const MEMBER = "MEMBER"
export const useUserStore = defineStore('user', () => {const userInfo = reactive({id: '',mobile: '',token: ''})function setUserInfo({id, mobile, token}) {userInfo.id = iduserInfo.mobile = mobileuserInfo.token = token}function clearUserInfo() {userInfo.id = ''userInfo.mobile = ''userInfo.token = ''}return {userInfo, setUserInfo, clearUserInfo}
}, {persist: {key: MEMBER,storage: sessionStorage,// paths: ['count'],serializer: {deserialize: parse,serialize: stringify},beforeRestore: (ctx) => {console.log(`about to restore '${ctx.store.$id}'`)},afterRestore: (ctx) => {console.log(`just restored '${ctx.store.$id}'`)},debug: true,}
})
ite多环境配置
https://vitejs.cn/vite3-cn/guide/env-and-mode.html#env-variables
官方配置文档
在根目录创建文件 .env.development
NODE_ENV=development
#自定义变量需要以VITE_开头
VITE_APP_BASE_URL=http://localhost:8000
生产环境 .env.production
NODE_ENV=production
VITE_APP_BASE_URL=http://train.intmall.com
使用环境变量
axios.defaults.baseURL = import.meta.env.VITE_APP_BASE_URL;
console.log(process.env.NODE_ENV)
console.log(import.meta.env.VITE_APP_BASE_URL)
封装网络请求工具类Axios
npm install axios --save
封装网络请求工具类 src/utils/request.js
import axios from 'axios'
import {notification} from 'ant-design-vue';
import {useUserStore} from '@/stores/user';
import router from '@/router'const {userInfo, clearUserInfo} = useUserStore()
export const serverUrl = import.meta.env.VITE_APP_BASE_URLconst service = axios.create({baseURL: serverUrl,timeout: 5000
})// Add a request interceptor 全局请求拦截
service.interceptors.request.use(function (config) {// Do something before request is sentconst token = userInfo.tokenif (token) {config.headers['token'] = token}// 此处还可以设置tokenreturn config},function (error) {// Do something with request errorreturn Promise.reject(error)}
)// Add a response interceptor 全局相应拦截
service.interceptors.response.use(function (response) {// Any status code that lie within the range of 2xx cause this function to trigger// Do something with response data// 如果是固定的数据返回模式,此处可以做继续完整的封装const resData = response.data || {}if (resData.success) {return resData}notification.error({description: resData.message});return Promise.reject(resData.message)},function (error) {// Any status codes that falls outside the range of 2xx cause this function to trigger// Do something with response error// 此处需要对返回的状态码或者异常信息作统一处理console.log('error', error)const response = error.response;const status = response.status;if (status === 401) {// 判断状态码是401 跳转到登录页console.log("未登录或登录超时,跳到登录页");clearUserInfo()notification.error({description: "未登录或登录超时"});router.push('/login')}return Promise.reject(error)}
)export const get = (url, params) => {return service.get(url, {params})
}export const post = (url, data) => service.post(url, data)export const put = (url, data) => service.put(url, data)export const del = (url, data) => service.delete(url)
遇到的问题:
useRouter失效,router无法跳转页面
https://blog.csdn.net/qq_57700056/article/details/133530562
后台接口调用示例: src/api/userApi.js
import { get, post, put, del } from "../utils/request";// 用户登录
export async function login(data) {return post('/member/member/login', data)
}export async function sendCode(data) {return post('/member/member/sendCode', data)
}export async function getUserCount() {return get('/member/member/count')
}export async function savePassenger(data) {return post('/member/passenger/save', data)
}export async function queryPassengerList(data) {return post('/member/passenger/queryList', data)
}export async function deletePassenger(id) {return del(`/member/passenger/delete/${id}`)
}// 导出 userApi 方法
export default {login,sendCode,getUserCount,savePassenger,deletePassenger,queryPassengerList
}
前端页面路由配置
增加路由防卫,判断要跳转的页面是否需要登录
src/router/index.js
由于router挂载比pinia要早,守卫在在使用pinia时,pinia还没有挂载,把pinia写在守卫里面即可解决问题
import {createRouter, createWebHistory} from 'vue-router'
import {notification} from 'ant-design-vue';
import {useUserStore} from '@/stores/user';const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'main',component: () => import('../views/MainView.vue'),children: [{path: '/welcome',name: 'welcome',component: () => import('../views/main/WelcomeView.vue')}, {path: '/passenger',name: 'passenger',component: () => import('../views/main/PassengerView.vue')}]},{path: '/login',name: 'login',component: () => import('../views/LoginView.vue'),meta: {noToken: true}}, {path: '',redirect: '/welcome'}]
})// 路由登录拦截
router.beforeEach((to, from, next) => {// 要不要对meta.noToken属性做监控拦截if (to.matched.some(function (item) {console.log(item, "是否不需要登录校验:", item.meta.noToken || false);return !item.meta.noToken})) {const {userInfo} = useUserStore()console.log("页面登录校验开始:", userInfo);if (!userInfo.token) {console.log("用户未登录或登录超时!");notification.error({description: "未登录或登录超时"});next('/login');} else {next();}} else {next();}
});export default router
登录页面
<script setup>
import {reactive} from 'vue';
import {useRouter} from 'vue-router'
import {CodepenCircleOutlined} from "@ant-design/icons-vue";
import {notification} from 'ant-design-vue';
import userApi from '../api/userApi';
import { useUserStore } from '@/stores/user';
const { setUserInfo } = useUserStore()const router = useRouter();const loginForm = reactive({mobile: '',code: '',
});
const onFinish = async (value) => {// 执行登录逻辑const respData = await userApi.login(value);const data = respData.datasetUserInfo(data)console.log('Success:', value, data);notification.success({ description: '登录成功!' });router.push("/welcome");
};
const onFinishFailed = errorInfo => {console.log('Failed:', errorInfo);
};const sendCode = async () => {await userApi.sendCode({mobile: loginForm.mobile})notification.success({ description: '发送验证码成功!' });loginForm.code = "8888";
}
</script><template><a-row class="login"><a-col :span="8" :offset="8" class="login-main"><h1 style="text-align: center"><CodepenCircleOutlined/> 模拟12306售票系统</h1><a-form:model="loginForm"name="basic"autocomplete="off"@finish="onFinish"@finishFailed="onFinishFailed"><a-form-itemlabel=""name="mobile":rules="[{ required: true, message: '请输入手机号!' }]"><a-input v-model:value="loginForm.mobile" placeholder="手机号"/></a-form-item><a-form-itemlabel=""name="code":rules="[{ required: true, message: '请输入验证码!' }]"><a-input v-model:value="loginForm.code"><template #addonAfter><a @click="sendCode">获取验证码</a></template></a-input></a-form-item><a-form-item :wrapper-col="{ offset: 8, span: 16 }"><a-button type="primary" html-type="submit">登录</a-button></a-form-item></a-form></a-col></a-row></template><style scoped>
.login-main h1 {font-size: 25px;font-weight: bold;
}.login-main {margin-top: 100px;padding: 30px 30px 20px;border: 2px solid grey;border-radius: 10px;background-color: #fcfcfc;
}
</style>
退出登录
<script setup>
import {ref} from "vue";
import {useUserStore} from '@/stores/user';const {userInfo, clearUserInfo} = useUserStore()const selectedKeys1 = ref(['2']);
</script><template><a-layout-header class="header"><div class="logo"/><div style="float: right; color: white;">您好:{{userInfo.mobile}} <router-link to="/login" @click.native="clearUserInfo()" style="color: white;">退出登录</router-link></div><a-menuv-model:selectedKeys="selectedKeys1"theme="dark"mode="horizontal":style="{ lineHeight: '64px' }"><a-menu-item key="1">nav 1</a-menu-item><a-menu-item key="2">nav 2</a-menu-item><a-menu-item key="3">nav 3abc</a-menu-item></a-menu></a-layout-header>
</template>
页面增删改查操作
<script setup>
import {ref, reactive} from 'vue';
import {notification} from "ant-design-vue";
import {cloneDeep} from 'lodash-es';
import userApi from '@/api/userApi';
import {PASSENGER_TYPE_ARRAY} from '@/assets/js/enums'const visible = ref(false);
const loading = ref(false);let passenger = ref({id: undefined,memberId: undefined,name: undefined,idCard: undefined,type: undefined,createTime: undefined,updateTime: undefined,
});const passengers = ref([]);
const pagination = reactive({total: 0,current: 1,pageSize: 2
})const columns = [{title: '姓名',dataIndex: 'name',key: 'name',},{title: '身份证',dataIndex: 'idCard',key: 'idCard',},{title: '旅客类型',dataIndex: 'type',key: 'type',},{title: '操作',dataIndex: 'operation'},
]
const handleQuery = (param) => {if (!param) {param = {"page": 1,"size": pagination.pageSize}}loading.value = true;userApi.queryPassengerList({"page": param.page,"limit": param.size}).then(res => {console.log('res', res)loading.value = false;passengers.value = res.data;pagination.total = res.count;pagination.current = res.page})
}const handleTableChange = (pagination) => {handleQuery({page: pagination.current,size: pagination.pageSize})
}handleQuery()const onAdd = () => {passenger.value = {};visible.value = true;
}const onEdit = (record) => {console.log("record", record)passenger.value = cloneDeep(record);visible.value = true;
}const onDelete = (record) => {console.log("delete record", record)userApi.deletePassenger(record.id).then(() => {notification.success({description: "删除成功!"});handleQuery({page: pagination.current,size: pagination.pageSize,});})
}const handleOk = () => {userApi.savePassenger(passenger.value).then(resp => {notification.success({description: "保存成功!"});visible.value = false;handleQuery({page: pagination.current,size: pagination.pageSize})})
}
</script><template><p><a-space><a-button type="primary" @click="handleQuery()">刷新</a-button><a-button type="primary" @click="onAdd">新增</a-button></a-space></p><a-table :dataSource="passengers" :columns="columns" :pagination="pagination" @change="handleTableChange":loading="loading"><template #bodyCell="{ column, text, record }"><template v-if="column.dataIndex === 'operation'"><a-space><a @click="onEdit(record)">编辑</a><a-popconfirmtitle="删除后不可恢复,确认删除?"ok-text="确认" cancel-text="取消"@confirm="onDelete(record)"><a style="color: red">删除</a></a-popconfirm></a-space></template><template v-else-if="column.dataIndex === 'type'"><span v-for="item in PASSENGER_TYPE_ARRAY" :key="item.code"><span v-if="item.code === record.type">{{item.desc}}</span></span></template></template></a-table><a-modal v-model:open="visible" title="乘车人" @ok="handleOk"ok-text="确认" cancel-text="取消"><a-form:model="passenger" :label-col="{span: 4}" :wrapper-col="{ span: 20 }"><a-form-item label="姓名"><a-input v-model:value="passenger.name"/></a-form-item><a-form-item label="身份证"><a-input v-model:value="passenger.idCard"/></a-form-item><a-form-item label="旅客类型"><a-select v-model:value="passenger.type"><a-select-option v-for="item in PASSENGER_TYPE_ARRAY" :key="item.code" :value="item.code">{{ item.desc }}</a-select-option></a-select></a-form-item></a-form></a-modal></template>
前端跨域问题
前后端分离项目,前端在请求后台接口时会出现跨域问题
这个后端项目使用到了gateway,在配置文件中加入:
# 允许请求来源(老版本叫allowedOrigin)
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedOriginPatterns=*
# 允许携带的头信息
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedHeaders=*
# 允许的请求方式
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedMethods=*
# 是否允许携带cookie
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowCredentials=true
# 跨域检测的有效期,会发起一个OPTION请求
spring.cloud.gateway.globalcors.cors-configurations.[/**].maxAge=3600
后端分页查询方法
#CommonPageParam.java
@Data
public class CommonPageParam {@NotNull(message = "页码不能为空")private Integer page;@NotNull(message = "每页数量不能为空")@Max(value = 100, message = "分页条数不能超过100")private Integer limit;
}#PassengerQueryReq.java
@Data
public class PassengerQueryReq extends CommonPageParam {private Long memberId;
}#CommonPageResp.java
@Data
@NoArgsConstructor
public class CommonPageResp<T> {/** 默认每页的条数 */public static final int PAGE_SIZE_DEFAULT = 10;/*** 业务上的成功或失败*/private boolean success = true;/*** 返回信息*/private String message;/*** 返回泛型数据,自定义类型*/private List<T> data;/*** 总数*/private Long count;/*** 页码*/private Integer page;/*** 每页数量*/private Integer limit;public Integer getPage() {if (page == null || page < 1) {return 1;}return page;}public Integer getLimit() {if (limit == null) {return PAGE_SIZE_DEFAULT;}return limit;}public static <T> CommonPageResp<T> SUCCESS(String message, List<T> data, PageInfo pageInfo) {return new CommonPageResp<>(true, message, data, pageInfo.getTotal(), pageInfo.getPageNum(), pageInfo.getPageSize());}public CommonPageResp(boolean success, String message, List<T> data, Long count, Integer page, Integer limit) {this.success = success;this.message = message;this.data = data;this.count = count;this.page = page;this.limit = limit;}
}#PassengerService.java
@Service
@Slf4j
public class PassengerService {@Resourceprivate PassengerMapper passengerMapper;public CommonPageResp<PassengerQueryResp> queryList(PassengerQueryReq req) {PassengerExample passengerExample = new PassengerExample();passengerExample.setOrderByClause("id desc");PassengerExample.Criteria criteria = passengerExample.createCriteria();if (ObjectUtil.isNotNull(req.getMemberId())) {criteria.andMemberIdEqualTo(req.getMemberId());}PageHelper.startPage(req.getPage(), req.getLimit());List<Passenger> passengerList = passengerMapper.selectByExample(passengerExample);PageInfo<Passenger> pageInfo = new PageInfo<>(passengerList);List<PassengerQueryResp> list = BeanUtil.copyToList(passengerList, PassengerQueryResp.class);return CommonPageResp.SUCCESS("", list, pageInfo);}
}
使用线程本地变量存储用户信息
拦截器从token中获取用户信息
@Slf4j
@Component
public class MemberInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("MemberInterceptor开始");//获取header的token参数String token = request.getHeader("token");if (StrUtil.isNotBlank(token)) {log.info("获取会员登录token:{}", token);JSONObject loginMember = JwtUtil.getJSONObject(token);log.info("当前登录会员:{}", loginMember);MemberLoginResp member = JSONUtil.toBean(loginMember, MemberLoginResp.class);LoginMemberContext.setMember(member);}log.info("MemberInterceptor结束");return true;}
}
配置开启拦截器
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {@Resourceprivate MemberInterceptor memberInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 路径不要包含context-pathregistry.addInterceptor(memberInterceptor).addPathPatterns("/**").excludePathPatterns("/hello","/member/sendCode","/member/login");}
}
设置用户到本地线程
import com.intmall.train.common.domain.resp.MemberLoginResp;
import lombok.extern.slf4j.Slf4j;@Slf4j
public class LoginMemberContext {private static ThreadLocal<MemberLoginResp> member = new ThreadLocal<>();public static MemberLoginResp getMember() {return member.get();}public static void setMember(MemberLoginResp member) {LoginMemberContext.member.set(member);}public static Long getId() {try {return member.get().getId();} catch (Exception e) {log.error("获取登录会员信息异常", e);throw e;}}
}
源码地址
完整代码参考:
https://gitee.com/galen.zhang/train
相关文章:
使用 Vue3 + Pinia + Ant Design Vue3 搭建后台管理系统
Vue3 & Ant Design Vue3基础 nodejs版本要求:node-v18.16.0-x64 nodejs基础配置 npm -v node -vnpm config set prefix "D:\software\nodejs\node_global" npm config set cache "D:\software\nodejs\node_cache"npm config get registry …...

SpringCloud核心组件
Eureka 注册中心,服务的注册与发现 Feign远程调用 Ribbon负载均衡,默认轮询 Hystrix 熔断 降级 Zuul微服务网关(这个组件负责网络路由,可以做统一的降级、限流、认证授权、安全) Eureka 微服务的功能主要有以下几…...
基于C++11实现将IP地址、端口号和连接状态写入文件
要基于C11实现将IP地址、端口号和连接状态写入文件,您可以使用std::ofstream类来打开文件并进行写入操作。以下是一个示例: #include <iostream> #include <fstream>void writeConnectionStatus(const std::string& ip, int port, bool…...
非空断言,
先看下TypeScript基础之非空断言操作符、可选链运算符、空值合并运算符-CSDN博客 我没有复现出来,但是我知道了它的作用 用 let str: string arg!; 代替 let str: string; if (arg) { str arg; } 非空断言(!)和不使用的区别在于对于…...
Spark---创建DataFrame的方式
1、读取json格式的文件创建DataFrame 注意: 1、可以两种方式读取json格式的文件。 2、df.show()默认显示前20行数据。 3、DataFrame原生API可以操作DataFrame。 4、注册成临时表时,表中的列默认按ascii顺序显示列。 df.createTempView("mytab…...

瑜伽学习零基础入门,各种瑜伽教学方法全集
一、教程描述 练习瑜伽的好处多多,能够保证平衡健康的身体基础,提升气质、塑造形体、陶冶情操,等等。本套教程是瑜伽的组合教程,共由33套视频教程组合而成,包含了塑身纤体,速效瘦身,四季养生&a…...

pycharm编译报错处理
1.c生成工具下载 https://visualstudio.microsoft.com/visual-cpp-build-tools/ 在这里插入图片描述 pip install pycocotools...
“华为杯”研究生数学建模竞赛2019年-【华为杯】E题:基于多变量的全球气候与极端天气模型的构建与应用(附python代码实现)
目录 摘 要: 一.问题重述 1.1 问题背景 1.2 问题提出 二.模型假设及符号设定...
冒泡排序(适合编程新手的体质)
冒泡排序:简单而高效的排序技巧 欢迎来到我们今天的博客,我们将一起探索计算机科学中最基本但同时也非常重要的概念之一:冒泡排序。无论你是编程新手还是有一些编程经验的读者,这篇博客都将帮助你更好地理解冒泡排序的原理和应用…...
pdfjs,pdf懒加载
PDF.js是一个使用JavaScript实现的PDF阅读器,它可以在Web浏览器中显示PDF文档。PDF.js支持懒加载,也就是说,它可以在用户滚动页面时才加载PDF文档的某些部分,从而减少初始加载时间和内存占用。 注意点:如果要运行在多留…...

K8s 多租户方案的挑战与价值
在当今企业环境中,随着业务的快速增长和多样化,服务器和云资源的管理会越来越让人头疼。K8s 虽然很强大,但在处理多个部门或团队的业务部署需求时,如果缺乏有效的多租户支持,在效率和资源管理方面都会不尽如人意。 本…...

单链表相关经典算法OJ题:移除链表元素
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 题目:移除链表元素 解法一: 解法一的代码实现: 解法二: 解法二代码的实现: 总结 前言 世上有两种耀眼的…...

【JUC】十九、volatile与内存屏障
文章目录 1、volatile的两大特性2、volatile的四大内存屏障3、分类4、happens-before之volatile变量重排规则5、读写屏障插入策略 1、volatile的两大特性 被volatile修饰的变量有两大特点: 可见性有序性 关于volatile的可见性,也即volatile的内存语义…...

下载MySQL JDBC驱动的方法
说明 java代码通过JDBC访问MySQL数据库,需要MySQL JDBC驱动。 例如,下面这段代码,因为找不到JDBC驱动,所以执行会报异常: package com.thb;public class JDBCDemo {public static void main(String[] args) throws …...

C/C++ 实现FTP文件上传下载
FTP(文件传输协议)是一种用于在网络上传输文件的标准协议。它属于因特网标准化的协议族之一,为文件的上传、下载和文件管理提供了一种标准化的方法,在Windows系统中操作FTP上传下载可以使用WinINet库,WinINetÿ…...
第十三章 python之爬虫
Python基础、函数、模块、面向对象、网络和并发编程、数据库和缓存、 前端、django、Flask、tornado、api、git、爬虫、算法和数据结构、Linux、设计题、客观题、其他 第十三章 爬虫 1. 写出在网络爬取过程中, 遇到防爬问题的解决办法。 在网络爬取过程中,可能会遇…...
scrum 敏捷开发
scrum 敏捷开发 Scrum 是一种敏捷软件开发方法,旨在通过迭代、增量和协作的方式提高团队的效率和产品质量。下面是关于 Scrum 的一些重要概念和实践: 1. Scrum 团队角色 Scrum 团队通常由以下角色组成: 产品负责人(Product Ow…...

亚信科技AntDB数据库完成中国信通院数据库迁移工具专项测试
近日,在中国信通院“可信数据库”数据库迁移工具专项测试中,湖南亚信安慧科技有限公司(简称:亚信安慧科技)数据库数据同步平台V2.1产品依据《数据库迁移工具能力要求》、结合亚信科技AntDB分布式关系型数据库产品&…...

深度学习(一):Pytorch之YOLOv8目标检测
1.YOLOv8 2.模型详解 2.1模型结构设计 和YOLOv5对比: 主要的模块: ConvSPPFBottleneckConcatUpsampleC2f Backbone ----->Neck------>head Backdone 1.第一个卷积层的 kernel 从 6x6 变成了 3x3 2. 所有的 C3 模块换成 C2f,可以发现…...

EasyExcel如何读取全部Sheet页数据方法
一、需求描述 Excel表格里面大约有20个sheet页,每个sheet页65535条数据,需要读取全部数据,并导入至数据库。 找了好多种方式,EasyExcel比较符合,下面看代码。 二、实现方式 采用EasyExcel框架的doReadAll()方法 1、…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...