个人博客后台管理开发日志
技术栈:Vue3 + Ts + node.js + mySQL+ pinia + axios
3月14日
一、数据表梳理
ID | 名字 | 邮箱 | 密码 | 头像 地址 | 创建 时间 |
总览有本地文件、博客文章、摄影图库、随笔随记,这些板块也有对应的分类,我们要把这些分类都做成对应的表
ID | 分类名称 | 所属类型 (0文章、1摄影、2资源) | 创建时间 | 备注 |
ID | 文件地址 | 文件名称 | 文件格式 | 所属分类 | 创建时间 | 是否like |
后期可以自行修改文件名称 | 后期可以按照文件格式进行分类 |
可以再优化:比如记录文件时候是否删除了,就是说你要存档与否,以此来实现逻辑删除
但上面我们仅仅只是物理删除
我们的文章和图库所包含的内容都差不多,索性就把它们放在一个表里面了。只需要用一个所属类型字段做区分即可
ID | 标题 | 所属分类 | 所属类型 | 标签 | 简介 | 内容 | 封面 | 查看次数 | 文章状态 | 创建时间 |
0文章 1摄影 | 0未发布 1已发布 |
由于我们希望记录点赞和评论详细一点,例如获取点赞的人的ID或者ip,以及不能重复点赞,或者是点赞的总人数之类的。评论也是如此,所以我们为此单独建一个表
ID | 所属文章ID | 点赞者ID | 用户类型 | 创建时间 |
0登录用户 1游客 |
这里记录点赞者有两种,一种是游客模式,有一个我们分发的ip。另一种是注册过的用户,是其真实的id。我们需要很快速的去找到用户的信息,于是通过用户类型字段去快速判断是那种用户
ID | 所属文章ID | 评论者ID | 用户类型 | 创建时间 | 评论内容 | 举报数 | 是否已读 | 用户名称 |
0登录用户 1游客 | 0未读 1已读 |
ID | 标签名称 | 创建时间 |
ID | 标题 | 内容 | 图片 | 天气 | 心情 | 创建时间 |
ID | 天气名称 | 天气图标地址 |
ID | 用户ID | 用户类型 | 用户名称 | 创建时间 | 内容 | 是否已读 |
0登录用户 1游客 | 0未读 1已读 |
我们在首页有一个访问量的记录,还有一些监听数据。这些数据就来自于埋点
我们需要知道你什么时候来访问了,或者是访问了哪个页面/接口/模块
于是我们还要创建一个埋点的表
ID | 用户ID | 用户类型 | 创建时间 | 访问位置 | 访问设备 |
0登录用户 1游客 | 0移动端 1PC端 |
二、创建数据表
自动化建表
为什么不在可视化界面手动创建数据表?
自动创建的好处:
不管是将应用程序运到哪台服务器,我们都不需要在服务器里面重新手动录入一些表的字段,再把数据库弄好才能运行我们的程序
用户(user)
let users = `create table if not exists users(id INT NOT NULL AUTO_INCREMENT,name VARCHAR(100) NOT NULL COMMENT '用户名',mail VARCHAR(100) NOT NULL COMMENT '邮箱',password VARCHAR(100) NOT NULL COMMENT '密码',moment VARCHAR(100) NOT NULL COMMENT '时间',imgurl VARCHAR(100) COMMENT '头像地址',PRIMARY KEY ( id ));`
分类(subset)
let subset = `create table if not exists subset(id INT NOT NULL AUTO_INCREMENT,subset_name VARCHAR(100) NOT NULL COMMENT '分类名称',classify INT NOT NULL COMMENT '类型0文章,1图片,2资源',moment VARCHAR(100) NOT NULL COMMENT '时间',PRIMARY KEY ( id ));`
本地文件(file)
let file =
`create table if not exists file(id INT NOT NULL AUTO_INCREMENT,url VARCHAR(100) NOT NULL COMMENT '地址',file_name VARCHAR(100) NOT NULL COMMENT '名称',format VARCHAR(32) NOT NULL COMMENT '格式',subset_id INT COMMENT '所属分类',moment TIMESTAMP NOT NULL COMMENT '时间',PRIMARY KEY (id)
);`;//所属分类不是必填的
文章/图库(article)
let article =
`create table if not exists article(id INT NOT NULL AUTO_INCREMENT,title VARCHAR(200) NOT NULL COMMENT '标题',subset_id INT COMMENT '所属分类',classify INT NOT NULL COMMENT '类型0文章,1图片',label VARCHAR(200) COMMENT '标签',introduce VARCHAR(1000) COMMENT '简介',content VARCHAR(5000) COMMENT '内容',cover VARCHAR(100) COMMENT '封面地址',views INT DEFAULT 0 COMMENT '查看次数',state INT DEFAULT 0 COMMENT '文章状态',moment TIMESTAMP NOT NULL COMMENT '时间',PRIMARY KEY (id)
);`;
文章点赞(like)
let praise = `create table if not exists praise(id INT NOT NULL AUTO_INCREMENT,user_id VARCHAR(100) NOT NULL COMMENT '用户',user_type INT NOT NULL COMMENT '用户类型',article_id INT NOT NULL COMMENT '所属文章',moment VARCHAR(100) NOT NULL COMMENT '时间',PRIMARY KEY ( id )};`
文章评论(comment)
let comment =
`create table if not exists comment(id INT NOT NULL AUTO_INCREMENT,user_id VARCHAR(100) NOT NULL COMMENT '用户',user_type INT NOT NULL COMMENT '用户类型',article_id INT NOT NULL COMMENT '所属文章',moment TIMESTAMP NOT NULL COMMENT '时间',content VARCHAR(1000) NOT NULL COMMENT '内容',complaint INT DEFAULT 0 COMMENT '举报次数',isread INT DEFAULT 0 COMMENT '是否已读',PRIMARY KEY (id)
);`;
标签(label)
let label = `create table if not exists label(id INT NOT NULL AUTO_INCREMENT,label_name VARCHAR(100) NOT NULL COMMENT '名称',moment VARCHAR(100) NOT NULL COMMENT '时间',PRIMARY KEY ( id )};`
日记(diary)
let diary =
`create table if not exists diary(id INT NOT NULL AUTO_INCREMENT,title VARCHAR(200) NOT NULL COMMENT '标题',content VARCHAR(5000) NOT NULL COMMENT '内容',picture VARCHAR(500) COMMENT '图片地址',weather_id INT COMMENT '天气',mood INT DEFAULT 0 COMMENT '心情',moment TIMESTAMP NOT NULL COMMENT '时间',PRIMARY KEY (id)
);`;
天气(weather)
let weather =`create table if not exists weather(id NOT NULL AUTO_INCREMENT,weather_name VARCHAR(32) NOT NULL COMMENT '名称',icon VARCHAR(100) COMMENT '图标',PRIMARY KEY ( id ));`
私信(message)
let message = `create table if not exists message(id INT NOT NULL AUTO_INCREMENT,user_id VARCHAR(100) NOT NULL COMMENT '用户',user_type INT NOT NULL COMMENT '用户类型',user_name VARCHAR(100) NOT NULL COMMENT '用户名称',moment VARCHAR(100) NOT NULL COMMENT '时间',content VARCHAR(1000) NOT NULL COMMENT '内容',isread INT DEFAULT 0 COMMENT '是否已读',PRIMARY KEY ( id ));`
埋点(record)
let record =`create table if not exists record(id INT NOT NULL AUTO_INCREMENT,user_id VARCHAR(100) NOT NULL COMMENT '用户',user_type INT NOT NULL COMMENT '用户类型',position VARCHAR(100) COMMENT '位置',device INT DEFAULT 0 COMMENT '设备',moment VARCHAR(100) NOT NULL COMMENT '时间',PRIMARY KEY ( id ));`
三、数据接口梳理
我们需要展示的数据跟后端有交互的就需要把接口记录下来
【用户】
是否有注册
地址:isRegister
//请求
export type isRegister = {
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝//200表示注册过了,401表示没有注册过
}
用户注册
地址:/register
//请求
export type register = {name: string;password: string;moment: Date;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
用户登录
地址:/login
//请求
export type login = {name: string,psw: string
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{id: number; //因为id是自增的name: string;//imgurl: string;//psw: string; //把密码拿回来可以做数据加密token: string;}
}
这里的data是不一定有的,因为有可能返回错误状态码
【总览信息】
地址:/overview
//请求
export type overview = {token: string;userId: number;
}//如果是多用户,还需要获取userId
//因为要根据不同的用户去取不同的数据
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{file: string;article: number;gallery: number;diary: number;}
}
访问量
地址:/visits
//请求
export type visits = {token: string;length: number; //时间长度 近一周还是近一个月
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{date: string;count: number;}
}
数据监测
地址:/survey
//请求
export type survey = {token: string;length: number; //时间长度 近一周还是近一个月
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{device: { //不同设备key: 'mobile' | 'pc';value: number;}[];website: {key: 'file'|'article'|'gallery'|'diary';value: number;}[];}
}
评论
地址:/comment
我们要获取评论的总条数,但只用在第一次的时候获取就行了,所以加一个判断是否要获取总评论数
//请求
export type comment = {token: string;pageSize: number; //单页条数nowPage: number: //当前页count?: boolean;
}
返回数据为栈
除了获取id,我们还要获取该条评论来自于哪篇文章。但是这篇文章不一定取得回来,因为有可能被删除了
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{count?: number;list:{id: number;article?:{id: number;title: string;};user:{id: string|number; //有游客和登录用户name: string;imgurl: string;};comment: string;moment: string;complaint: number;}[];}
}
已读评论
地址:/commentIsread
//请求
export type commentIsread = {token: string;id: number; //评论的id
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
删除评论
地址:/deleteComment
//请求
export type deleteComment = {token: string;id: number; //评论的id
}
3月15日
私信
地址:/message
//请求
export type message = {token: string;pageSize: number; //单页条数nowPage: number: //当前页count?: boolean;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{count?: number;list:{id: number;user:{id: string|number; //有游客和登录用户name: string;};comment: string;moment: string;}[];}
}
获取未读私信数
地址:/noreadMessage
//请求
export type noreadMessage = {token: string;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?: count: number;
}
删除私信
地址:/deleteMessage
//请求
export type deleteMessage = {token: string;id: number; //私信的id
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
【博客文章】
文章/文章搜索
地址:/article
state不一定会取,因为除了已发布和未发布的分类,还有一个全部的分类囊括所有
为了保持搜索和渲染的一致,我们添加一个搜索词
//请求
export type article = {token: string;pageSize: number; //单页条数nowPage: number: //当前页state?: number; //状态 已发布or未发布subsetId?: number; //分组serchTerm?: string; //搜索词条count?: boolean; //是否获取总文章数
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{count?: number;result:{id: number;title: string;subset_id: number;moment: string;label?: string[]; //标签可以有多个introduce?: string; //简介cover?: string; //封面地址views: number; //查看次数state: number; //状态 0未发布 1已发布comment: number;praise: number; //点赞次数}[];}
}
文章发布/撤回
地址:/changeArticleState
//请求
export type changeArticleState = {token: string;articleId: number;state: number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
文章删除
地址:/deleteArticle
//请求
export type deleteArticle = {token: string;articleId: number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
文章状态
已发布/未发布
地址:/articleStateCount
//请求
export type articleState = {token: string;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{id: number; //0 or 1name: string;value: number;}[];
}
分组
地址:/subset
//请求
export type subset = {token: string;classify: number; //所属什么类型//0文章、1图片、2资源
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{count?: number; //全部分组的数量list:{id: number; name: string; //分组名称value: number; //多少条moment: string; //时间}[];}
}
新建分组
地址:/addSubset
//请求
export type addSubset = {token: string;value: {moment: Date;classify: number; //所属什么类型subset_name: string|number;}}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data: number; //分组id
}
修改分组名称
地址:/updateSubset
//请求
export type updateSubset = {token: string;subsetId: number;subsetName: string|number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
删除分组名称
地址:/deleteSubset
//请求
export type deleteSubset = {token: string;subsetId: number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
标签
地址:/label
//请求
export type label = {token: string;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{id: number;label_name: string|number;moment: Date;}[];
}
新增标签
地址:/addLabel
//请求
export type addLabel = {token: string;value: {label_name: string|number;moment: Date;}
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝id: number; //标签的id
}
删除标签
地址:/deleteLabel
//请求
export type deleteLabel = {token: string;labelId: number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
【本地文件】
文件
地址:/file
//请求
export type file = {token: string;pageSize: number; //单页条数nowPage: number; //当前页subsetId?: number; //分组count?: boolean;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{count?: number; //返回多少条数据,用来做翻页器list:{id: number;url: stirng; //地址fileName: string; //文件名format: string; //格式subsetId?: number; //所属类型isLike: boolean; //是否收藏}[];}
}
文件上传
地址:/uploadFile
//请求
export type uploadFile = {token: string;formData: new FormData();//这样写在node里面使用方法就可以获取到文件信息,就可以进行文件上传subsetId?: number; //所属类型
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{id: number;url: stirng; //地址fileName: string; //文件名format: string; //格式subsetId?: number; //所属类型}
}
文件删除
地址:/deleteFile
//请求
export type deleteFile = {token: string;files: number|number[]; //id//单张删除和批量删除
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
移动文件
地址:/removeFile
//请求
export type removeFile = {token: string;fileId: number; //id 单张删除和批量删除subsetId: number; //所属分组,要移动到哪个地方去
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
【摄影图库】
图库 / 图库搜索
地址:/gallery
//请求
export type gallery = {token: string;pageSize: number; //单页条数nowPage: number; //当前页subsetId?: number; //分组count?: boolean;serchTerm?: stirng|number; //搜索词条
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{count?: number;list:{id: number;title: string;subsetId?: number;moment: string; //时间introduce?: string; //简介cover?: string; //封面地址content: string[]; //图片内容views: number; //查看次数comment: number;praise: number; //点赞次数}[];}
}
图库删除
地址:/deleteGallery
//请求
export type deleteGallery = {token: string;galleryId: number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
【随笔随记】
日记 / 日记搜索
地址:/diary
//请求
export type diary = {token: string;pageSize: number; //单页条数nowPage: number; //当前页count?: boolean;serchTerm?: stirng|number; //搜索词条
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{count?: number;list:{id: number;title: string;moment: string; //时间weatherId: number; //天气content: string;picture?: string[];}[];}
}
日记删除
地址:/deleteDiary
//请求
export type deleteDiary = {token: string;diaryId: number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
日记新建
地址:/createDiary
//请求
export type createDiary = {token: string;title: string;content: stirng;picture?: string[];weatherId: number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
获取天气
地址:/weather
//请求
export type weather = {token: string;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{id: number;name: string;icon: string; //是图标的地址}
}
【文章与图库】
文章/图库新建
地址:/createArticle
//请求
export type createArticle = {token: string;title: string;subsetId: number; //分组classify: number; //0文章,1图片label?: string[];introduce?: string; //简介content?: string; //内容cover?: string; //封面地址state?: number; //状态moment: string; //时间
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝
}
获取文章/图库
地址:/gainArticle
//请求
export type gainArticle = {token: string;articleId: number;
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data?:{id: number;title: string;subsetId?: number;label?: string[];introduce?: string;content?: string;cover?: string;}
}
文章/图库修改
地址:/updateArticle
//请求
export type updateArticle = {token: string;id: number; //文章/图库修改value: {title?: string;subset_id?: number;label?: string[];introduce?: string;content?: string;cover?: string;state?: number;}
}
//返回数据
res = {code: number; //200正常,300未通过token验证,500错误,400功能拒绝data: number; //文章/图库id
}
四、开发环境搭建
vite + vue + Ts + pinia
- 安装 less
- 安装组件库,安装了之后还要按需引入,在此之前还要安装按需引入的插件
- 配置文件的书写
3月16日
在main.ts中引入组件库的样式
在vite.config.ts中写入css预编译器
之后想要修改全局色/警告色之类的就可以在第二十行代码的文件中修改
配置路由环境
使用懒加载
五、前端
HeadBar组件
菜单栏组件
静态数组把这些导航项都封装起来,调用时可以遍历一次性渲染。
但是如果想要动态的渲染图标,要先自己去引入一下图标库
3月17日
总览卡片
我们用mock拿到数据再放到overLink里面去,记得把导出的overLink拿ref包一下
数据统计卡片
遗留的问题
:数据监测的卡片没有实现绑定周月切换,并且数据的稳定性有问题,排版也稍微有点问题
3月20日
评论
删除评论按钮的实现
我们在单条中实现删除按钮,但是数据并不是在单条中删除的。是告诉父级,让父级删除相关的那个数组
翻页的触发事件是造好的轮子
遗留的问题
点击翻页的时候我希望评论可以自动滚动到第一条
私信
我大概看了一下,只有使用消息提示组件的时候使用了proxy,如下
遗留的问题
已读所有信息清除徽标点的效果实现
输入页面点击回车可直接跳转
删除私信成功后抽屉不要缩回(已解决)
在information.vue组件中第19行代码中的点击后面加上.stop
3月21日
分组组件
新建FileView.vue文件,添加路由
考虑到分组名称以及数量或者是文章状态(已发布/未发布情况)在后面很多地方都会用到,我们考虑将这些数据放入storage,于是引入pinia!!!
我们要将在mock生成的数据拿到useSubsetStore里面去然后再进行渲染
未分类的个数可以在store里面用getters进行计算
这是我写的一个博客后台管理项目,其中我用mock模拟生成了数据,存在mock文件夹下的data.ts文件中,我还使用了pinia状态管理库,数据存在stoore文件夹下的subset.ts文件中,且在该文件中,我写了一个名为exclude的getters函数,旨在获取没有分类的总数量(具体计算方法在函数中体现了,就是用总数减去有id的标签数量),但是最后我渲染出来的"未分类"标签总是负数,我不知道是哪里出了问题,你能帮我看看吗,并告诉我如何修改
遗留的问题
分组名称和相关联的文章数样式区别一下不然就会出现 “青岛1”+“23” =》“青岛123”
3月22日
文件组件
考虑到这里切换分组的气泡确认框非常鸡肋,因为明明可以通过上方subset来进行切换,没必要多此一举。我打算将切换功能换成收藏功能,喜欢的图片可以点小红心标记,支持单张收藏,也支持批量收藏。于是乎前面编写的一些数据和结构需要修改,比如图片需要加上是否被标记的字段,mock模拟数据处也需要修改,subset多新添一个分组【收藏】
【用mock模拟数据】
我们需要的文件数据是一个静态图集,所以我们干脆自己写一个图片合集,里面都是图片的名称。
因为我们的路径是固定好的,路径自己去拼接即可,在数据库存的话就存一个图片名称就可以了
【图片布局】
选中的勾怎么去写?
把黑色框变成背景,勾变成图标,这样的话啊我们直接控制图标的显示和不显示就行了
同样也是用动态绑定类名去实现
3月23日
【切换分组】
在气泡确认框中使用插槽,放在一个可滚动的容器内,需要用到滚动条去封装它
【全选按钮的显示】
对于多个文件是选择还是没选择,这关乎到全选按钮的显示与否。我们选择用一个数组来存储那些被选择了的文件的id,如果该数组为空,全选按钮不必亮起,反之则亮
遗留的问题
把名字换成动态的,可编辑的。鼠标悬浮时显示画笔编辑按钮,点击即可编辑文件名字
以及fileItem展示也有问题:我希望删除了一些文件之后后面的可以自己补上来,且如果删除数量足够大页数也能跟着改变,而不是让页面空着
3月24日
遗留的问题
在批量修改分组时我希望在点击完确认按钮之后取消所有选择,但目前我不知道把这个cancelSelected函数放在哪里触发比较好,现在我实现的效果是在点击完分组名称之后就取消了所有的选择,都还没等到我点确认按钮
感悟:以后每完成一个组件都自己优化一回
标签组件
watch
函数用于监听一个或多个响应式数据源的变化,当被监听的数据发生改变时,会执行相应的回调函数。在这段代码中,它监听props.label
的变化,一旦props.label
发生变化,就会将新的值展开并赋值给labelData.value
。
遗留的问题
管理标签还没有实现双向
3月25日
文章组件
【创建模拟数据】
【渲染文章所属分组】
因为我们的分组数据是放在pinia的storage里面的,我们可以在里面写一个方法"action",判断当前的subsetId是哪一个并返回出来
3月26日
摄影图库
遗留的问题
不知道为什么同样的宽高,我的页面一行只能显示四个图库,yike能显示五个。
感觉四个有点太大了,看一下后面能不能修改一下
3月27日
随笔随记
遗留的问题
日记并未设置修改功能,但我想新添加隐藏功能,加上眼睛图标点击切换日记是否可查看
后续更牛逼的可以搞仅自己可见 / 仅朋友(互关)可见 / 仅粉丝可见...
DiaryItem里面的深拷贝问题
3月28日
新建图库
新建表单
因为我们最后要把表单的数据一起打包提交,所以我们在设置数据的时候就弄成一个对象
我们写的这个表单编辑,需要根据是文章()还是随笔随记适配不同的内容,所以我们需要父级告诉它当前在哪个板块好呈现相应的内容
3月29日
富文本编辑器
难绷
遗留的问题
想删的几个功能没删脱,内容编辑处的hello还没删掉,editor.vue文件还留有一处飘红问题
注册与登录
遗留的问题
yike的注册登录页面太捞了,之后去b站找个牛逼的改一下
由于我们当时开发的时候是将header放在根组件App.vue里面的,这样路由跳转到哪个界面都能保证他的结构。但是我们的注册登录页面不需要header,这里只是通过样式进行掩盖了,之后1有时间可以优化一下
3月30日
后端
页面配置
使用cors处理跨域问题
创建数据库
链接数据库
//这是专门创建数据表、链接数据库的文件
const mysql = require('mysql');
const config = require('../config/default');
const { resolve } = require('path');//数据库链接
const connection = mysql.createConnection({host: config.database.HOST,user: config.database.USER,password: config.database.PASSWORD,
})//直接链接
let query = (sql, values) => {return new Promise((resolve, reject) => {connection.query(sql, values, (err, result) => {if (err) {reject(err)} else {resolve(result)}})})
}//链接指定数据库
const pool = mysql.createPool({connectionLimit: 10, //链接数量host: config.database.HOST,user: config.database.USER,password: config.database.PASSWORD,database: config.database.DB,
})//通过pool.getConnection 获得链接
let query2 = (sql, values) => {return new Promise((resolve, reject) => {pool.getConnection((err, connection) => {if (err) {reject(err)} else {connection.query(sql, values, (err, rows) => {if (err) {reject(err)} else {resolve(rows)}connection.release();})}})})
}
芜湖狗狗够
数据处理 1 2
大概思路:先有请求,再有方法,再有去调数据库的事件。
so,先在routes里面写请求,请求完之后在controller里面去处理,处理的时候如果要用到数据库的交互我们就要到数据库交互去写我们数据库的方法
【用户登录】要用到数据的查找,因为登录需要匹配信息
我们利用name将用户找出来,然后再来匹配密码,因为密码需要解密
并且这个板块我们要进行两次验证,第一次是用户名不存在说明是没有注册或者输入错误,第二种是密码错误
写登录接口返回给前端数据时我们还要创建token,之后每一次访问接口我们都要通过token来进行验证
const jwt = require('jsonwebtoken');
const secret = 'dsbicuashsdkjf euashdsuhasdvoishdbi ah hue';// 生成token
exports.generateToken = function (id) {let payload = { id, time: new Date() };let token = jwt.sign(payload, secret, { expiresIn: 60 * 60 * 24 * 30 });return token;
};// 解码token
exports.verifyToken = function (token) {return new Promise((resolve, reject) => {jwt.verify(token, secret, (err, result) => {if (err) {reject(err);} else {resolve(result);}});});
};
拿到token之后将数据拼接一下交给前端即可,前端拿到数据之后可以将数据存在localStorage里面
遗留的问题
【密码的加密与解密】
npm install bcrypt失败
目前看来原因是电脑系统python环境不够
【验证拦截】
需要通过那个拦截再去执行下面步骤的事情,拦截的时候需要token的对比
3月31日 4 5 6 7 8
数据处理
我们在进行文件移动的时候并不是真正物理意义上的让文件移动了,只是更换了它的分组修改了数据表罢了
4月1日
数据梳理 9 10 11 12
(这天的记录忘记保存了我晕厥,大概就是图库、日记的增删查改 以及文件真实的上传及删除
难点就是文件真实的上传和删除,用到了node的fs)
4月3日
联调篇
axios环境配置
hooks使用及返回code处理
hooks可以把多个组件中共享的逻辑代码抽取出来,封装到一个自定义 Hook 中。比如多个组件都有获取用户信息、处理数据加载状态的需求,就可以把这些逻辑封装到一个 useUserInfo
Hook 中,然后在不同组件中引入使用,避免重复编写代码,提高开发效率和代码的可维护性。
【用户输错地址的处理】
这段代码是在 Vue Router 中使用 beforeEach
导航守卫来处理路由请求
beforeEach
是一个全局前置守卫,在每次路由切换前都会被调用。这段代码的主要目的是在路由跳转前,检查目标路由是否匹配,如果不匹配(即路由地址错误 ),则进行相应的跳转处理;如果匹配,则继续进行正常的路由跳转。
可优化的问题
我们实际实现并没有使用ErrorInfo这个界面,而是如果用户输错地址则直接返回到总览页面。后续自己可以实现错误404页面3秒后自动跳转到主页提高交互的感觉
4月4日
【重新规划注册登录接口】
邮箱,手机号验证
遗留的问题
手机号验证还是没做,但是注册登录界面换了个自己喜欢的更高级的页面,目前已经调整好了,但是之后还是得研究一下源码?
明天接着联调
4月5日
用户注册及登录
遗留的问题
注册登录页面的弹窗提示都被覆盖掉了(如注册成功、用户名或密码错误等),之后需要研究注册登录源码看看是什么问题
目前我们登录成功之后刷新一次信息就掉了,因为我们还要前端去处理一些token的验证,且后端会返回用户信息,我们应该把这些信息都保存起来
用户数据本地存储
这一节主要做登录返回来的数据的存储,以及前端的是否登录的验证
因为博客后台管理还是比较私密的东西,我们尽量保证每一次访问都要登录。所以我们这里不采用浏览器的localStorage来进行长久保存,而是使用pinia
但是用pinia保存东西是不支持刷新的,因此我们需要处理
让其能够至少在我本次打开这个浏览器无论怎么去刷新都可以拿到数据——引入插件
—— Pinia Plugin Persistedstate
我们登录进来了之后还要验证一下是否真的已经登录了,因为要防止有人直接从网址进入
总览数据获取
4月6日
评论接口测试
评论联调补充
将评论变成已读,删除评论,评论头像显示
4月7日
私信接口联调
因为要处理私信右上角的小红点、我们还要写一个判断私信是否还有未读的接口。修改查询私信总数的sql语句,增加isread参数
遗留的问题
这个私信太垃了,之后考虑重新构思 。删除了私信之后不会自动补充,而且页数也不会根据私信数量来变化,第3页一个私信都没了但是这一页还在
新建分组
Headbar中退出按钮的功能实现:点击清空本地数据并跳转到登录页面
文件、文章、图库、日记
文件(全部、未分类、收藏、自定义)
文章(全部、未/已发布、未分类、收藏、、自定义)
图库(全部、未分类、收藏、自定义)
日记(全部、未分类、喜欢、自定义)
搞错了,日记并没有弄分组,但是喜欢功能后期可以自己去实现思考:收藏应该怎么存?
单独开个数据表来存?X
无论是文件文章还是图库日记,收藏的打个标识,也就是说以上提到的数据表都要添加一个字段isLiked
利用传props我们完成了只有博客文章显示已发布未发布的功能
我们在前端切换页面的时候,我们要告诉组件说我们已经切换到其他的模块去了,需要把当前的分组重新更新一下。所以我们在subset页面需要监听一下classify的变化,记住一定得是深度监视
(后续证明这个监听没有什么用,已废弃)
4月8日
获取和删除分组
标签管理联调
遗留的问题 (已解决)
新建标签之后标签管理页面不能及时的变化更新,在标签管理页面删除标签之后标签显示板块也没有及时更新
分组组件hooks写法改进
在hooks中使用默认的东西是需要引用的,比如defineEmits
4月9日
标签hooks的改造
在编辑博客文章是新建的标签也要存到数据库里面去
遗留的问题
新建标签时间有问题
文件上传
封面的上传以及添加到数据库中,使用的是单张文件上传的接口,且后端会返回给前端id,方便日后删除
目前我们上传的图片不是地址型的,浏览器只是生成了一个临时地址,此时我们一刷新就会掉。
那么我们需要自己给他生成一个地址并赋给它
我们看到yike文件上传的API如下
当前文件列表有一个固定的类型,所以我们要按照它那样来写
遗留的问题
文件上传没有完全解决,封面依旧存在一刷新就掉的问题
4月10日
新建文章
label是一个数组,我们要对它进行处理,将它转换成字符串才好存到数据库中去
这里遇到了一个小问题
我用yike的这种将数组转换成字符串的方法根本不行,最终我使用闭包解决了该问题
发布的时候后端出现了一点问题,之前遇到过的,传给后端的moment格式类型不对,无法插入到数据库。
我一开始将之前写的formatLocalDate方法拿到前端,想着把moment处理好了再传入后端。但是这样不仅没有效果,还会让编辑器一直报Network Error。
最终将moment处理放到后端就没啥事了,哦对了moment在前端哪怕是new Date()的,传入后端时都是一个字符串,但是formatLocalDate要求的参数得是一个Date类型,所以得加一个判断,如果传入的Date是个字符串的话,必须先进行转换,如下图
【发布成功之后并没有跳转】
在hooks中 const router = useRouter( );必须要放在export function里面,否则不奏效
修改更新文章
处理编辑博客文章页面插入图片的实现
后面写到中途去完善之前WangEditor的菜单配置问题了
4月11日
遗留的问题
出于私心,我想要编辑器有回退功能 (已实现)
我很贪心,我还想要字体切换功能。缩进和对齐图标有问题
这里有个贼怪的问题,就是我为了消除报红把InsertFnType给导入了之后富文本编辑器不能正常显示了,新建博客文章点都点不开。把导入删除了就没事,于是我就保留了这个报红,就这样吧
问题:保存与发布
我们希望保存是覆盖当前这篇文章,而不是在数据库存一篇新的。
但我们当前修改更新文章还没处理好,现在点击保存就是生成了一篇新的文章
按照我做的攻略,我们先找到了小飞奔的树。那棵树是在居民巷子楼道里,巷道拐来拐去错落有致,沿边还有卖贝壳珍珠的小摊以及精致的咖啡店,都散发着温暖的光亮。我觉得走那截路很好玩,我现在还记得那种感觉,就是,很舒服、温暖、安稳、期待、兴奋,心里痒痒的。
不过我们并没有在小飞奔的树那里停留,很多人在那里打卡拍照,我们三个选择继续往下走。我记得在下去之前我们在一个小摊贩那里买了一个烤海星吃,我们一边拿着吃一边走路,一副别人一看就知道是外地人来玩的模样。但那个烤海星实在不算好吃,那时我们下到琴屿路的时候钻进了一个咖啡店,本想点点吃喝满足味蕾惬意的坐着。最后碍于价格灰溜溜的出来了,把不想吃的烤海星留在了店里哈哈哈
后来我们就一直沿着琴屿路闲逛,看到什么谈什么,想到什么说什么。碰到小红书很火的红帽子拍立得,我们就这样随便又庄重的留下了我们三个的第一张拍立得。记得拍之前我们一直担心天气不好拍出来不好看,最后相片出来的时候我们都小心翼翼的捏着,轻轻的捂着。呈像时是三张美丽又开心的脸,爽了。
一路向左沿着海岸线,钻过一个石拱门,惊喜的发现不知怎的就走到了鲁迅公园,我一惊一乍的跟大张小张说太好了,本来还担心没时间辗转这么多景点,需要舍弃几个。没想到鲁迅公园就挨着琴屿路,哦耶。
我们一路说说笑笑,张文婷录了我们一起说韩国人来农的视频,我的表情把大张小张笑得捧腹,她们一笑我也想笑,于是我们三个笑得像蛆一样扭来扭去。
之后在一个我找的绝佳机位(摄影眼爆发)我提出大家来合影吧,本来大家没抱太大期待,结果却出乎意料的好看!!!,于是我们单人、双人、三人轮流拍了好多张哈哈哈,然后在这里的照片后来都成为了我们给对方的聊天背景,就是有这么好看😎
逛完公园又原路返回琴屿路,回去时天色渐暗,大家好像都不太舍得走。于是又逛了一遍琴屿路,在温暖的路灯下,海岸旁,我心里想,就在琴屿路一直闲逛下去吧
4月12日
获取文章条件整理
这里更正一个之前的错误
在hooks中用emits时应该把定义写在使用hooks的组件内,然后将emits作为参数传进来,如上图
遗留的问题
这里其实是子级subset传递给父级页面ArticleView,然后父级页面又传递给另一个子级articleView
但我们目前的处理方式不太好,之后可以找更好的更换一下
4月13日
获取文章内容
淦
4月14日
淦
4月15日
- 确保
formData
的更新是响应式的:在subsetSelect
、addLabel
、selectLabel
和handleSuccess
方法中,使用展开运算符...
来更新formData
,确保 Vue 能正确监听到变化。 - 深度监听
formData
:在watch
中添加{ deep: true }
选项,确保能监听到formData
内部属性的变化。
通过这些修改,watch
应该能够正确监听到 formData
的变化并发送信号。
但是现在仍然存在问题,watch监听没问题了说明肯定可以发送信号了,但是该信号对应的getFormData函数却没有执行
4月22日
超超超,你大爷的你大爷的你大爷的你大爷的你大爷的
大爷我终于解决了我好想哭,摆烂停工七天,终于!
最后我是用的事件总线来做的,也不算解决了我之前的问题吧,因为我现在还不知道我之前是哪里写的有问题导致爷孙之间无法正常通信,不过总算把这个坑跳过去了。
遗留的问题
现在又有一个问题,就是【我的数据库存不了表情】
4月23日
【分页】
4月24日
【点击不同的subset切换不同的文章】
在article组件中进行监视
【修改文章发布状态】
使用findIndex + 直接修改
遗留的问题
之前遇到过的,删除文章之后没有及时补齐。这个问题在每次删除之后都重新获取一下数据可以解决
编辑文章涉及到数据的回显,他会跳转到编辑文章的页面并且把数据带回来
相关文章:
个人博客后台管理开发日志
技术栈:Vue3 Ts node.js mySQL pinia axios 3月14日 一、数据表梳理 用户(user) ID名字邮箱密码 头像 地址 创建 时间 总览有本地文件、博客文章、摄影图库、随笔随记,这些板块也有对应的分类,我们要把这些分类…...
[论文阅读]REPLUG: Retrieval-Augmented Black-Box Language Models
REPLUG: Retrieval-Augmented Black-Box Language Models REPLUG: Retrieval-Augmented Black-Box Language Models - ACL Anthology NAACL-HLT 2024 在这项工作中,我们介绍了RePlug(Retrieve and Plug),这是一个新的检索增强型…...
Matlab 基于共面螺旋管或共面亥姆霍兹谐振器的超薄低频吸声板
经典吸声材料的吸声性能严格依赖于材料的厚度,要达到完全吸声,至少需要四分之一波长。在本文中,我们报道了一种厚度约为波长百分之一的超薄吸声板,可以完全吸收声能。其策略是将四分之一波长的减声管弯曲并缠绕成二维共面减声管&a…...
济南国网数字化培训班学习笔记-第二组-4节-输电线路工程安全管理
输电线路工程安全管理 安全标识 颜色 禁止红、警示黄、指令蓝、提示绿 安全器具 定义 安全工器具通常专指“电力安全工器具”,是防止触电、灼伤、坠落、摔跌、腐蚀、窒息等事故,保障工作人员人身安全的各种专用工具和器具 分类 个体防护设备 防…...
【C语言】数据在内存中的存储:从整数到浮点数的奥秘
前言 在计算机的世界里,数据的存储和表示是编程的基础。今天,我们就来深入探讨一下数据在内存中的存储方式,包括整数和浮点数的存储细节,以及大小端字节序的奥秘。这些内容不仅对理解计算机系统至关重要,还能帮助我们…...
白鲸开源WhaleStudio与崖山数据库管理系统YashanDB完成产品兼容互认证
近日,北京白鲸开源科技有限公司与深圳计算科学研究院联合宣布,双方已完成产品兼容互认证。此次认证涉及深圳计算科学研究院自主研发的崖山数据库管理系统YashanDB V23和北京白鲸开源科技有限公司的核心产品WhaleStudio V2.6。经过严格的测试与验证&#…...
图论---朴素Prim(稠密图)
O( n ^2 ) 题目通常会提示数据范围: 若 V ≤ 500,两种方法均可(朴素Prim更稳)。 若 V ≤ 1e5,必须用优先队列Prim vector 存图。 // 最小生成树 —朴素Prim #include<cstring> #include<iostream> #i…...
借助deepseek和vba编程实现一张表格数据转移到多张工作簿的表格中
核心目标 将工作表中的内容按村社名称分类放入对应位置的目标工作簿的第一个工作表的对应位置 deepseek提问方式 你是一个擅长vba编程的专家,核心目标是奖工作表中的部分内容按下列要求写入对应工作簿的第一个工作表中。第一,在工作表A列中筛选出相…...
springboot整合redis实现缓存
一、redis 二、spring boot 整合redis 三、基于注解的Redis缓存实现 使用Cacheable、CachePut、CacheEvict注解定制缓存管理 对CommentService类中的方法进行修改使用Cacheable、CachePut、CacheEvict三个注解定制缓存管理,修改后的方法如下 Cacheable(cacheNam…...
git tag使用场景和实践
背景 每次上线一个迭代,为了区分本次代码的分支是哪个迭代,可以给分支打上tag,这样利于追踪分支所属迭代,如果devops没有自动给分支打tag,需要自己来打 操作 1.查看当前tag git tag2.给分支打tag git tag <tag…...
十分钟恢复服务器攻击——群联AI云防护系统实战
场景描述 服务器遭遇大规模DDoS攻击,导致服务不可用。通过群联AI云防护系统的分布式节点和智能调度功能,快速切换流量至安全节点,清洗恶意流量,10分钟内恢复业务。 技术实现步骤 1. 启用智能调度API触发节点切换 群联系统提供RE…...
国产紫光同创FPGA视频采集转SDI编码输出,基于HSSTHP高速接口,提供2套工程源码和技术支持
目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目紫光同创FPGA相关方案推荐本博已有的 SDI 编解码方案本方案在Xilinx--Artix7系列FPGA上的应用本方案在Xilinx--Kintex系列FPGA上的应用本方案在Xilinx--Zynq系列FPGA上…...
最小生成树-prim、kruskal算法
目录 prim算法 kruskal算法 题目练习 (1)AcWing 858. Prim算法求最小生成树 - AcWing (2)859. Kruskal算法求最小生成树 - AcWing题库编辑 学习之前建议温习一下迪杰斯特拉算法和并查集~ 先简单认识下最小生成树:…...
【硬核干货】JetBrains AI Assistant 干货笔记
快进来抄作业,小编呕心沥血整理的 JetBrains AI Assistant 超干货笔记! 原文链接:【硬核干货】JetBrains AI Assistant 干货笔记 关于晓数神州 晓数神州坚持以“客户为中心”的宗旨,为客户提供专业的解决方案和技术服务ÿ…...
强化学习核心原理及数学框架
1. 定义与核心思想 强化学习(Reinforcement Learning, RL)是一种通过智能体(Agent)与环境(Environment)的持续交互来学习最优决策策略的机器学习范式。其核心特征为: 试错学习&#x…...
C# 综合示例 库存管理系统4 classMod类
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 在《库存管理系统》中使用classMod类来保存全局变量。 变量定义和含义,请详见下面的源代码: public class classMod { //数据库路径...
[C] 第6章 C51函数
文章目录 C51函数函数概述从函数定义角度分类从函数有无返回值分类从函数有无参数 函数定义的一般形式C51无参函数的一般形式C51有参函数的一般形式 函数的形式参数和实际参数形式参数实际参数函数的返回值一般形式为: 函数的形参和实参的特点 函数的调用函数的调用…...
docker 配置代理
docker 配置代理有 2 中方法 1.Daemon configuration 直接在 /etc/docker/daemon.json 文件中配置 {"proxies": {"http-proxy": "http://proxy.example.com:3128","https-proxy": "https://proxy.example.com:3129",&quo…...
Redis 深度解析:从核心原理到生产实践
Redis 深度解析:从核心原理到生产实践 一、Redis 核心定位与数据结构 1. 核心能力矩阵深度解析 Redis 作为高性能内存数据库,核心能力覆盖缓存、数据存储、消息中间件等场景,其设计哲学围绕速度优先、内存高效、功能丰富展开: …...
从零搭建高可用分布式限流组件:设计模式与Redis令牌桶实践
一、需求背景与设计目标 在分布式系统中,面对突发流量时需要一种精准可控的流量控制手段。我们的组件需要具备: 多维度限流(用户/IP/服务节点/自定义表达式)分布式环境下精准控制开箱即用的Spring Boot Starter集成高扩展性的架…...
基于霍尔效应传感器的 BLDC 电机梯形控制方案详解
基于霍尔效应传感器的 BLDC 电机梯形控制方案解读 使用霍尔效应传感器的无刷直流(BLDC)电机梯形控制 一、系统核心架构与技术优势 (一)BLDC 电机与霍尔传感器控制原理 BLDC 电机作为永磁同步电机的一种,其核心特征是转子反电动势为梯形波,定子电流为 120 电角度宽度的矩…...
Pikachu靶场-File Inclusion
文件包含漏洞(File Inclusion Vulnerability)是Web应用程序中的一种常见安全漏洞,通常由于开发者未对用户输入进行严格过滤,导致攻击者能够包含并执行恶意文件。这种漏洞主要分为两种类型: 1. 漏洞类型 本地文件包含&a…...
如何模拟黑客攻击(Red Teaming)以测试服务器安全性
模拟黑客攻击(Red Teaming)是评估服务器安全性的有效方法,但需严格遵循**合法授权**和**道德准则**。以下是专业且安全的操作流程: --- ### **1. 前期准备** - **法律授权** - 获得目标系统的**书面授权**,明确测…...
分页查询优惠券
文章目录 概要整体架构流程技术细节小结 概要 接口分析 一个典型的带过滤条件的分页查询,非常简单。按照Restful风格设计即可,我们关注的点有两个: 请求参数 返回值格式 请求参数包含两部分,一个是分页参数,另一…...
QTcpSocket 和 QUdpSocket 来实现基于 TCP 和 UDP 的网络通信
在 Qt 中,您可以通过 QTcpSocket 和 QUdpSocket 来实现基于 TCP 和 UDP 的网络通信。以下是如何使用 Qt 实现这两种通信方式的简要示例。 1. TCP 网络通信 TCP 是面向连接的协议,确保数据的可靠传输。下面是一个简单的 TCP 客户端和服务器示例。 TCP …...
从岗位依附到能力生态:AI革命下“什么叫就业”的重构与价值
在人工智能(AI)技术深刻重塑社会生产关系的当下,“就业”这一概念正经历着从“职业绑定”到“能力变现”的范式转移。本文将从传统就业观的解构、AI赋能艺术教育的价值逻辑、以及未来就业形态的进化方向三个维度,探讨技术驱动下就业的本质变革,并揭示AI技术如何通过教育创…...
2025上海车展 | 移远通信全栈车载智能解决方案重磅亮相,重构“全域智能”出行新范式
2025年4月23日至5月2日,第二十一届上海国际汽车工业展览会在国家会展中心(上海)盛大启幕。作为车载智能解决方案领域的领军企业,移远通信以“全域智能 驭见未来”为主题,携丰富的车载解决方案及客户终端惊艳亮相8.2馆8…...
LVGL在VScode的WSL2中仿真
目录 一、前言 二、开始部署 1.拉取github的库 2.在WSL安装一些必要的库或者包 3.开始编译 三、注意事项 一、前言 相信有不少兄弟因为苦于没有外设而无法学习LVGL,这里我提供一种WSL中仿真LVGL工程的方法。结果图如下: 二、开始部署 1.拉取github…...
React-组件和props
1、类组件 import React from react; class ClassApp extends React.Component {constructor(props) {super(props);this.state{};}render() {return (<div><h1>这是一个类组件</h1><p>接收父组件传过来的值:{this.props.name}</p>&…...
驱动开发系列53 - 一个OpenGL应用程序是如何调用到驱动厂商GL库的
一:概述 一个 OpenGL 应用程序调用 GPU 驱动的过程,主要是通过动态链接库(libGL.so)来完成的。本文从上到下梳理一下整个调用链,包含 GLVND、Mesa 或厂商驱动之间的关系。 二:调用关系 1. 首先一个 OpenGL 应用程序(比如游戏或图形渲染软件)在运行时会调用 OpenGL 提供…...
【python】一文掌握 markitdown 库的操作(用于将文件和办公文档转换为Markdown的Python工具)
更多内容请见: python3案例和总结-专栏介绍和目录 文章目录 一、markitdown概述1.1 markitdown介绍1.2 MarkItDown支持的文件1.3 为什么是Markdown?二、markitdown安装2.1 pip方式安装2.2 源码安装2.3 docker方式安装三、基本使用3.1 命令行方式3.2 可选依赖项配置3.3 插件方…...
【网络入侵检测】基于Suricata源码分析NFQ IPS模式实现
【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。 1. 概要 👋 本文聚焦于 Suricata 7.0.10 版本源码,深入剖析其 NFQ(Netfilter Queue)模式的实现原理。通过系统性拆解初始化阶段的配置流程、数据包监听机制的构建逻辑,以…...
驱动开发硬核特训 · Day 19:从字符设备出发,掌握 Linux 驱动的实战路径(含 gpio-leds 控制示例)
视频教程请关注 B 站:“嵌入式 Jerry” 一、背景说明:字符设备驱动的角色定位 在 Linux 内核驱动体系中,**字符设备驱动(Character Device Driver)**扮演着关键的桥梁作用,它直接向用户空间程序提供 read/…...
项目——高并发内存池
目录 项目介绍 做的是什么 要求 内存池介绍 池化技术 内存池 解决的问题 设计定长内存池 高并发内存池整体框架设计 ThreadCache ThreadCache整体设计 哈希桶映射对齐规则 ThreadCache TLS无锁访问 CentralCache CentralCache整体设计 CentralCache结构设计 C…...
几种查看PyTorch、cuda 和 Python 版本方法
在检查 PyTorch、cuda 和 Python 版本时,除了直接使用 torch.__version__ 和 sys.version,我们还可以通过其他方式实现相同的功能 方法 1:直接访问属性(原始代码) import torch import sysprint("PyTorch Versi…...
如何实现跟踪+分割的高效协同?SiamMask中的多任务损失设计
如何实现跟踪分割的高效协同?SiamMask中的多任务损失设计 一、引言二、三大分支损失函数详解2.1 分类分支损失2.2 回归分支损失2.3 Mask分支损失 三、损失加权策略与系数选择3.1 常见超参数设定3.2 动态权重(可选) 四、训练实践:平…...
MODBUS转EtherNetIP边缘计算网关配置优化:Logix5000与ATV340高效数据同步与抗干扰方案
一、行业背景 智能制造是当前工业发展的趋势,智能工厂通过集成各种自动化设备和信息技术,实现生产过程的智能化、自动化和高效化。在某智能工厂中,存在大量采用ModbusTCP协议的设备,如智能传感器、变频器等,而工厂的主…...
从代码学习深度学习 - 图像增广 PyTorch 版
文章目录 前言一、图像增广的基本概念二、PyTorch中的图像增广实现三、数据加载与处理四、模型训练与评估五、实验设置与执行六、实验结果与分析七、讨论总结前言 在深度学习中,数据是关键。尤其是在计算机视觉任务中,高质量且丰富多样的数据对模型性能有着决定性的影响。然…...
从机械应答到智能对话:大模型为呼叫注入智慧新动能
引言 在当今竞争激烈的商业环境中,高效和有效的客户沟通对于企业的成功至关重要。智能外呼系统已成为企业与潜在客户和现有客户互动的重要工具。最近,大模型(如大型语言模型或 LLMs)的出现为这些系统带来了显著的提升,…...
深入浅出 Python 协程:从异步基础到开发测试工具的实践指南
Python 的异步编程近年来越来越受欢迎,尤其在需要同时处理大量 I/O 请求的场景中,它展现了出色的性能。而协程是异步编程的核心,也是开发高效异步测试工具的关键技术。 这篇文章将用通俗的语言带你快速入门 Python 协程,结合实际…...
算法之分支定界
分支定界 分支定界概述核心思想与步骤常见变体复杂度分析案例分析1. 0-1背包问题2. 最短路径问题(分支定界法)3. 旅行商问题(TSP) 分支定界 概述 分支定界(Branch and Bound)是一种用于解决组合优化问题的…...
Hugging Face上面找开源的embedding模型
问题 想找一个支持中文的embedding模型(把一段文本转化成多维度的向量)。Hugging Face平台上面共享了很多开源模型,算是这年头(2025年),大家都把自己开源模式都往上放的地方了吧。现在去这个平台上面找一个…...
docker部署Jenkins工具
环境准备 1.当前安装在Windows系统下的Docker-Desktop 下载地址:Docker Desktop: The #1 Containerization Tool for Developers | Docker 2.下载后进行安装并进行配置启动docker 3.创建一个空的文件夹,用于后面的启动时做文件路径映射 下载镜像 d…...
Pgvector+R2R搭建RAG知识库
背景 R2R是一个采用Python编写的开源AI RAG框架项目,与PostgreSQL技术栈集成度高,运行需求资源少(主要是本人的Macbook air m1内存只有8G)的特点,对部署本地私有化化AI RAG应用友好。 Resource Recommendations Whe…...
Qt本地化 - installTranslator不生效
bool QCoreApplication::installTranslator(QTranslator *translationFile)注意这里输入的是QTranslator对象指针,如果QTranslator是局部变量,一旦离开其作用域就会导致翻译失效 错误代码示范: void ApplyTranslator(const QString& qmf…...
精益数据分析(19/126):走出数据误区,拥抱创业愿景
精益数据分析(19/126):走出数据误区,拥抱创业愿景 在创业与数据分析的探索之旅中,我们都渴望获取更多知识,少走弯路。今天,我依然带着和大家共同进步的想法,深入解读《精益数据分析…...
六、初始化与清理(Initialization cleanup)
六、初始化与清理(Initialization & cleanup) 本章内容主要介绍C中的 构造函数 和 析构函数 的作用与用法,以及默认构造、聚合初始化等相关特性 封装 和 *访问控制 *在提升库使用的便捷性方面迈出了重要的一步。在安全性方面࿰…...
Python - 爬虫-网页解析数据-库lxml(支持XPath)
lxml是 Python 的第三方解析库,完全使用 Python 语言编写,它对 Xpath 表达式提供了良好的支持,支持HTML和XML的解析,支持XPath解析方式,而且解析效率非常高 XPath,全称XML Path Language,即XML…...
单片机 + 图像处理芯片 + TFT彩屏 触摸滑动条控件
触摸滑动条控件使用说明 一、项目概述 本项目基于单片机和RA8889/RA6809图形处理芯片的TFT触摸屏滑动条控件。该控件支持水平和垂直滑动条,可自定义外观和行为,并支持回调函数进行值变化通知。 硬件平台:51/ARM均可(测试时使用STC8H8K64U单…...
LeetCode每日一题4.24
2799. 统计完全子数组的数目 题目 问题分析 完全子数组 的定义:子数组中不同元素的数目等于整个数组不同元素的数目。 子数组 是数组中的一个连续非空序列。 思路 统计整个数组的不同元素数目: 使用 set 来获取整个数组的不同元素数目。 遍历所有子数…...