【wiki知识库】06.文档管理页面的添加--前端Vue部分

  📝个人主页:哈__

期待您的关注 

目录

一、🔥今日目标

 二、🐻前端Vue模块的改造

BUG修改

1.wangeditor无法展示问题

2.弹窗无法正常关闭问题

2.1 添加admin-doc.vue

2.1.1 点击admin-ebook中的路由跳转到admin-doc

 2.2.2 进入到admin-doc中调用初始化查询方法

2.2.3 文档编辑中的一些细节

2.2.4 文档的删除

2.2.5 admin-doc.vue全部代码

2.2 添加DocView.vue

2.3 添加新的路由规则


一、🔥今日目标

上一次带大家把前端的分类管理模块做了出来,我们可以实现网站的分类功能,以及分类的树形结构展示功能。到此为止已经带大家做了电子书管理模块、分类模块,那么只要再把文档管理模块也做出来,我们就可以初步实现电子书这整个一套流程了。我们可以编辑添加电子书,实现分类,并且真正的往电子书的文档模块中添加内容。【wiki知识库】05.分类管理实现--前端Vue模块-CSDN博客

我们今天就要实现下方图片中箭头指向的功能

 除此之外,还有主页的展示功能。

 二、🐻前端Vue模块的改造

在此之前我要要说一件事情,我在做这个模块的时候出现了问题,一个是我们之后要使用的文本编辑器wangeditor无法正常展示,还有一个是弹窗无法关闭的问题。这里我把解决方法告诉大家。

BUG修改

1.wangeditor无法展示问题

出现这个问题可能是版本的问题,进入到我们的web目录中,打开终端窗口然后输入下方指令。重新安装wangeditor。

npm i wangeditor@4.6.3 --save

2.弹窗无法正常关闭问题

这个问题是wangeditor和vue版本兼容的问题。我们需要修改一下package.json。将vue版本改成下方图中所示,注意前边的符号。


2.1 添加admin-doc.vue

2.1.1 点击admin-ebook中的路由跳转到admin-doc

还记得我当初在admin-ebook.vue中写的一个router吗?在我们点击文档管理跳转到对应的组件的时候,我们是有传一个ebookId进来的,我们这里使用的是路由传参。


 2.2.2 进入到admin-doc中调用初始化查询方法

进入到这个页面呢调用了两个方法,一个是editor.create(),用于加载我们的文本编辑器,另外一个方法调用的是handleQuery()方法,向后端发送查询请求。

onMounted(() => {editor.create();handleQuery();});

 这个方法进入的时候,修改了一个变量loading,我们在进行信息查询的时候会给用户一个反馈,告诉用户稍等,我们修改为true之后就会有页面数据加载的效果。

level1变量我们之前也说过,用于保存树形结构的数据。之后呢就会发送一个ajax请求,等我们的数据返回来之后就要把loading改为false了。

至于下边的treeSelectData,在我们修改一个文档的父文档的时候,如果我们要把这个文档作为根文档,也就是一级文档,我们需要把这个文档的父文档设置为无,但是我们的level中存储的是数据库中查出来的数据,没有无这个选项,所以我们新加一个变量来存储level1的结果和无,这样不会影响我们查出来的数据。

const handleQuery = () => {loading.value = true;// 如果不清空现有数据,则编辑保存重新加载数据后,再点编辑,则列表显示的还是编辑前的数据level1.value = [];axios.get("/doc/all/" + route.query.ebookId).then((response) => {loading.value = false;const data = response.data;if (data.success) {docs.value = data.content;console.log("原始数组:", docs.value);level1.value = [];level1.value = Tool.array2Tree(docs.value, 0);console.log("树形结构:", level1);// 父文档下拉框初始化,相当于点击新增treeSelectData.value = Tool.copy(level1.value) || [];// 为选择树添加一个"无"treeSelectData.value.unshift({id: 0, name: '无'});} else {message.error(data.message);}});};

2.2.3 文档编辑中的一些细节

在我们进行文档编辑的时候,我们不可能把该文档的父文档改为自己,或者改为它的子文档,这是一个循环错误。所以我们在修改一个文档的时候要把这个文档的子文档和自己设置为不可选中。

 来看看这个方法,我们把树形结构的数据,还有我们要编辑的文档的id传进来,首先进行for循环去找到这个结点,然后我们把这个节点设置为不可见,然后我们去遍历这个节点的子节点,递归调用。

/*** 将某节点及其子孙节点全部置为disabled*/const setDisable = (treeSelectData: any, id: any) => {// console.log(treeSelectData, id);// 遍历数组,即遍历某一层节点for (let i = 0; i < treeSelectData.length; i++) {const node = treeSelectData[i];if (node.id === id) {// 如果当前节点就是目标节点console.log("disabled", node);// 将目标节点设置为disablednode.disabled = true;// 遍历所有子节点,将所有子节点全部都加上disabledconst children = node.children;if (Tool.isNotEmpty(children)) {for (let j = 0; j < children.length; j++) {setDisable(children, children[j].id)}}} else {// 如果当前节点不是目标节点,则到其子节点再找找看。const children = node.children;if (Tool.isNotEmpty(children)) {setDisable(children, id);}}}};

2.2.4 文档的删除

文档的删除并不只是该文档简单删除就完了,这个文档删掉之后,这个文档的所有子文档都要删除。我们之前分类管理模块也处理过这样的删除,但是我们是后端处理的删除逻辑,后端处理起来呢比较麻烦,这里我们可以使用前端处理一下。既然要删除子分支,我们就把这个要删除的文档的子文档的id都查出来一起传到后端。

/*** 查找整根树枝*/const getDeleteIds = (treeSelectData: any, id: any) => {// console.log(treeSelectData, id);// 遍历数组,即遍历某一层节点for (let i = 0; i < treeSelectData.length; i++) {const node = treeSelectData[i];if (node.id === id) {// 如果当前节点就是目标节点console.log("delete", node);// 将目标ID放入结果集ids// node.disabled = true;deleteIds.push(id);deleteNames.push(node.name);// 遍历所有子节点const children = node.children;if (Tool.isNotEmpty(children)) {for (let j = 0; j < children.length; j++) {getDeleteIds(children, children[j].id)}}} else {// 如果当前节点不是目标节点,则到其子节点再找找看。const children = node.children;if (Tool.isNotEmpty(children)) {getDeleteIds(children, id);}}}};

2.2.5 admin-doc.vue全部代码

<template><a-layout><a-layout-content:style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }"><a-row :gutter="24"><a-col :span="8"><p><a-form layout="inline" :model="param"><a-form-item><a-button type="primary" @click="handleQuery()">查询</a-button></a-form-item><a-form-item><a-button type="primary" @click="add()">新增</a-button></a-form-item></a-form></p><a-tablev-if="level1.length > 0":columns="columns":row-key="record => record.id":data-source="level1":loading="loading":pagination="false"size="small":defaultExpandAllRows="true"><template #name="{ text, record }">{{record.sort}} {{text}}</template><template v-slot:action="{ text, record }"><a-space size="small"><a-button type="primary" @click="edit(record)" size="small">编辑</a-button><a-popconfirmtitle="删除后不可恢复,确认删除?"ok-text="是"cancel-text="否"@confirm="handleDelete(record.id)"><a-button type="danger" size="small">删除</a-button></a-popconfirm></a-space></template></a-table></a-col><a-col :span="16"><p><a-form layout="inline" :model="param"><a-form-item><a-button type="primary" @click="handleSave()">保存</a-button></a-form-item></a-form></p><a-form :model="doc" layout="vertical"><a-form-item><a-input v-model:value="doc.name" placeholder="名称"/></a-form-item><a-form-item><a-tree-selectv-model:value="doc.parent"style="width: 100%":dropdown-style="{ maxHeight: '400px', overflow: 'auto' }":tree-data="treeSelectData"placeholder="请选择父文档"tree-default-expand-all:replaceFields="{title: 'name', key: 'id', value: 'id'}"></a-tree-select></a-form-item><a-form-item><a-input v-model:value="doc.sort" placeholder="顺序"/></a-form-item><a-form-item><a-button type="primary" @click="handlePreviewContent()"><EyeOutlined /> 内容预览</a-button></a-form-item><a-form-item><div id="content"></div></a-form-item></a-form></a-col></a-row><a-drawer width="900" placement="right" :closable="false" :visible="drawerVisible" @close="onDrawerClose"><div class="wangeditor" :innerHTML="previewHtml"></div></a-drawer></a-layout-content></a-layout></template><script lang="ts">import { defineComponent, onMounted, ref, createVNode } from 'vue';import axios from 'axios';import {message, Modal} from 'ant-design-vue';import {Tool} from "@/util/tool";import {useRoute} from "vue-router";import ExclamationCircleOutlined from "@ant-design/icons-vue/ExclamationCircleOutlined";import E from 'wangeditor'export default defineComponent({name: 'AdminDoc',setup() {const route = useRoute();console.log("路由:", route);console.log("route.path:", route.path);console.log("route.query:", route.query);console.log("route.param:", route.params);console.log("route.fullPath:", route.fullPath);console.log("route.name:", route.name);console.log("route.meta:", route.meta);const param = ref();param.value = {};const docs = ref();const loading = ref(false);// 因为树选择组件的属性状态,会随当前编辑的节点而变化,所以单独声明一个响应式变量const treeSelectData = ref();treeSelectData.value = [];const columns = [{title: '名称',dataIndex: 'name',slots: { customRender: 'name' }},{title: 'Action',key: 'action',slots: { customRender: 'action' }}];const level1 = ref(); // 一级文档树,children属性就是二级文档level1.value = [];/*** 数据查询**/const handleQuery = () => {loading.value = true;// 如果不清空现有数据,则编辑保存重新加载数据后,再点编辑,则列表显示的还是编辑前的数据level1.value = [];axios.get("/doc/all/" + route.query.ebookId).then((response) => {loading.value = false;const data = response.data;if (data.success) {docs.value = data.content;console.log("原始数组:", docs.value);level1.value = [];level1.value = Tool.array2Tree(docs.value, 0);console.log("树形结构:", level1);// 父文档下拉框初始化,相当于点击新增treeSelectData.value = Tool.copy(level1.value) || [];// 为选择树添加一个"无"treeSelectData.value.unshift({id: 0, name: '无'});} else {message.error(data.message);}});};// -------- 表单 ---------const doc = ref();doc.value = {ebookId: route.query.ebookId};const modalVisible = ref(false);const modalLoading = ref(false);const editor = new E('#content');editor.config.zIndex = 0;// 显示上传图片按钮,转成Base64存储,同时也支持拖拽图片editor.config.uploadImgShowBase64 = true;const handleSave = () => {modalLoading.value = true;doc.value.content = editor.txt.html();axios.post("/doc/save", doc.value).then((response) => {modalLoading.value = false;const data = response.data; // data = commonRespif (data.success) {// modalVisible.value = false;message.success("保存成功!");// 重新加载列表handleQuery();} else {message.error(data.message);}});};/*** 将某节点及其子孙节点全部置为disabled*/const setDisable = (treeSelectData: any, id: any) => {// console.log(treeSelectData, id);// 遍历数组,即遍历某一层节点for (let i = 0; i < treeSelectData.length; i++) {const node = treeSelectData[i];if (node.id === id) {// 如果当前节点就是目标节点console.log("disabled", node);// 将目标节点设置为disablednode.disabled = true;// 遍历所有子节点,将所有子节点全部都加上disabledconst children = node.children;if (Tool.isNotEmpty(children)) {for (let j = 0; j < children.length; j++) {setDisable(children, children[j].id)}}} else {// 如果当前节点不是目标节点,则到其子节点再找找看。const children = node.children;if (Tool.isNotEmpty(children)) {setDisable(children, id);}}}};const deleteIds: Array<string> = [];const deleteNames: Array<string> = [];/*** 查找整根树枝*/const getDeleteIds = (treeSelectData: any, id: any) => {// console.log(treeSelectData, id);// 遍历数组,即遍历某一层节点for (let i = 0; i < treeSelectData.length; i++) {const node = treeSelectData[i];if (node.id === id) {// 如果当前节点就是目标节点console.log("delete", node);// 将目标ID放入结果集ids// node.disabled = true;deleteIds.push(id);deleteNames.push(node.name);// 遍历所有子节点const children = node.children;if (Tool.isNotEmpty(children)) {for (let j = 0; j < children.length; j++) {getDeleteIds(children, children[j].id)}}} else {// 如果当前节点不是目标节点,则到其子节点再找找看。const children = node.children;if (Tool.isNotEmpty(children)) {getDeleteIds(children, id);}}}};/*** 内容查询**/const handleQueryContent = () => {axios.get("/doc/find-content/" + doc.value.id).then((response) => {const data = response.data;if (data.success) {editor.txt.html(data.content)} else {message.error(data.message);}});};/*** 编辑*/const edit = (record: any) => {// 清空富文本框editor.txt.html("");modalVisible.value = true;doc.value = Tool.copy(record);handleQueryContent();// 不能选择当前节点及其所有子孙节点,作为父节点,会使树断开treeSelectData.value = Tool.copy(level1.value);setDisable(treeSelectData.value, record.id);// 为选择树添加一个"无"treeSelectData.value.unshift({id: 0, name: '无'});};/*** 新增*/const add = () => {// 清空富文本框editor.txt.html("");modalVisible.value = true;doc.value = {ebookId: route.query.ebookId};treeSelectData.value = Tool.copy(level1.value) || [];// 为选择树添加一个"无"treeSelectData.value.unshift({id: 0, name: '无'});};const handleDelete = (id: number) => {// console.log(level1, level1.value, id)// 清空数组,否则多次删除时,数组会一直增加deleteIds.length = 0;deleteNames.length = 0;getDeleteIds(level1.value, id);Modal.confirm({title: '重要提醒',icon: createVNode(ExclamationCircleOutlined),content: '将删除:【' + deleteNames.join(",") + "】删除后不可恢复,确认删除?",onOk() {// console.log(ids)axios.delete("/doc/delete/" + deleteIds.join(",")).then((response) => {const data = response.data; // data = commonRespif (data.success) {// 重新加载列表handleQuery();} else {message.error(data.message);}});},});};// ----------------富文本预览--------------const drawerVisible = ref(false);const previewHtml = ref();const handlePreviewContent = () => {const html = editor.txt.html();previewHtml.value = html;drawerVisible.value = true;};const onDrawerClose = () => {drawerVisible.value = false;};onMounted(() => {editor.create();handleQuery();});return {param,// docs,level1,columns,loading,handleQuery,edit,add,doc,modalVisible,modalLoading,handleSave,handleDelete,treeSelectData,drawerVisible,previewHtml,handlePreviewContent,onDrawerClose,}}});
</script><style scoped>img {width: 50px;height: 50px;}
</style>

2.2 添加DocView.vue

这个组件呢就是为了在主页展示文档数据。但是其中的一些功能后端还未实现。

<template><a-layout><a-layout-content :style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }"><h3 v-if="level1.length === 0">对不起,找不到相关文档!</h3><a-row><a-col :span="6"><a-treev-if="level1.length > 0":tree-data="level1"@select="onSelect":replaceFields="{title: 'name', key: 'id', value: 'id'}":defaultExpandAll="true":defaultSelectedKeys="defaultSelectedKeys"></a-tree></a-col><a-col :span="18"><div><h2>{{doc.name}}</h2><div><span>阅读数:{{doc.viewCount}}</span> &nbsp; &nbsp;<span>点赞数:{{doc.voteCount}}</span></div><a-divider style="height: 2px; background-color: #9999cc"/></div><div class="wangeditor" :innerHTML="html"></div><div class="vote-div"><a-button type="primary" shape="round" :size="'large'" @click="vote"><template #icon><LikeOutlined /> &nbsp;点赞:{{doc.voteCount}} </template></a-button></div></a-col></a-row></a-layout-content></a-layout>
</template><script lang="ts">import { defineComponent, onMounted, ref, createVNode } from 'vue';import axios from 'axios';import {message} from 'ant-design-vue';import {Tool} from "@/util/tool";import {useRoute} from "vue-router";export default defineComponent({name: 'Doc',setup() {const route = useRoute();const docs = ref();const html = ref();const defaultSelectedKeys = ref();defaultSelectedKeys.value = [];// 当前选中的文档const doc = ref();doc.value = {};const level1 = ref(); // 一级文档树,children属性就是二级文档level1.value = [];/*** 内容查询**/const handleQueryContent = (id: number) => {axios.get("/doc/find-content/" + id).then((response) => {const data = response.data;if (data.success) {html.value = data.content;} else {message.error(data.message);}});};/*** 数据查询**/const handleQuery = () => {axios.get("/doc/all/" + route.query.ebookId).then((response) => {const data = response.data;if (data.success) {docs.value = data.content;level1.value = [];level1.value = Tool.array2Tree(docs.value, 0);if (Tool.isNotEmpty(level1)) {defaultSelectedKeys.value = [level1.value[0].id];handleQueryContent(level1.value[0].id);// 初始显示文档信息doc.value = level1.value[0];}} else {message.error(data.message);}});};const onSelect = (selectedKeys: any, info: any) => {console.log('selected', selectedKeys, info);if (Tool.isNotEmpty(selectedKeys)) {// 选中某一节点时,加载该节点的文档信息doc.value = info.selectedNodes[0].props;// 加载内容handleQueryContent(selectedKeys[0]);}};// 点赞const vote = () => {axios.get('/doc/vote/' + doc.value.id).then((response) => {const data = response.data;if (data.success) {doc.value.voteCount++;} else {message.error(data.message);}});};onMounted(() => {handleQuery();});return {level1,html,onSelect,defaultSelectedKeys,doc,vote}}});
</script><style>/* table 样式 */.wangeditor table {border-top: 1px solid #ccc;border-left: 1px solid #ccc;}.wangeditor table td,.wangeditor table th {border-bottom: 1px solid #ccc;border-right: 1px solid #ccc;padding: 3px 5px;}.wangeditor table th {border-bottom: 2px solid #ccc;text-align: center;}/* blockquote 样式 */.wangeditor blockquote {display: block;border-left: 8px solid #d0e5f2;padding: 5px 10px;margin: 10px 0;line-height: 1.4;font-size: 100%;background-color: #f1f1f1;}/* code 样式 */.wangeditor code {display: inline-block;*display: inline;*zoom: 1;background-color: #f1f1f1;border-radius: 3px;padding: 3px 5px;margin: 0 3px;}.wangeditor pre code {display: block;}/* ul ol 样式 */.wangeditor ul, ol {margin: 10px 0 10px 20px;}/* 和antdv p冲突,覆盖掉 */.wangeditor blockquote p {font-family:"YouYuan";margin: 20px 10px !important;font-size: 16px !important;font-weight:600;}/* 点赞 */.vote-div {padding: 15px;text-align: center;}/* 图片自适应 */.wangeditor img {max-width: 100%;height: auto;}/* 视频自适应 */.wangeditor iframe {width: 100%;height: 400px;}
</style>

2.3 添加新的路由规则

在router下的index.js中新增两个路由规则。

 {path: '/doc',name: 'doc',component:DocView},{path: '/admin/doc',name: 'AdminDoc',component: AdminDoc}

后续我会把后端的代码补上的。

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

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

相关文章

LoadBalance客户端负载均衡

1. 前言Ribbon Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。简单的说&#xff0c;Ribbon是Netflix发布的开源项目&#xff0c;主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时&#xff0…

数据结构——栈(Stack)详解

1. 栈&#xff08;Stack&#xff09; 1.1 概念 栈&#xff1a;一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中数据元素遵循后进先出LIFO(Last In First Out)的原则 压栈&am…

Java——LinkedList

1、链表 1.1 链表的概念及结构 链表在逻辑层面上是连续的&#xff0c;在物理层面上不一定是连续的 链表结构可分为&#xff0c;单向或双向、带头或不带头、循环或非循环&#xff0c;组合共计8种 重点&#xff1a;无头单向非循环链表、无头双向链表 1.2 模拟实现无头单向非…

梯度提升决策树(GBDT)

GBDT&#xff08;Gradient Boosting Decision Tree&#xff09;&#xff0c;全名叫梯度提升决策树&#xff0c;是一种迭代的决策树算法&#xff0c;又叫 MART&#xff08;Multiple Additive Regression Tree&#xff09;&#xff0c;它通过构造一组弱的学习器&#xff08;树&am…

OpenCV绘制直线

一 绘制图形 画线 画矩形 画圆 画椭圆 画多边形 绘制字体 二 画线 line(img,开始点&#xff0c;结束点&#xff0c;颜色…) 参数结束 img&#xff1a;在那个图像上画线 开始点,结束点&#xff1a;指定线的开始与结束位置&#xff1b; 颜色&#xff0c;线宽&#xff0c;线体…

图解 Twitter 架构图

写在前面 两年前&#xff0c;马老板收购了twitter&#xff0c;并且做了一系列的大动作。那么今天我们来看一下这个全球最火的软件之一的架构。 Twitter解析 开始之前&#xff0c;我先提前说明一下&#xff0c;我之前不是做搜推广的&#xff0c;所以对这些了解不是很深&…

力扣 SQL题目

185.部门工资前三高的所有员工 公司的主管们感兴趣的是公司每个部门中谁赚的钱最多。一个部门的 高收入者 是指一个员工的工资在该部门的 不同 工资中 排名前三 。 编写解决方案&#xff0c;找出每个部门中 收入高的员工 。 以 任意顺序 返回结果表。 返回结果格式如下所示。 …

CSS 字体颜色渐变

CSS 字体颜色渐变 css 代码: 注意&#xff1a;background: linear-gradient&#xff08;属性&#xff09;&#xff0c;属性可以调整方向 例如&#xff1a;to bottom 上下结构&#xff0c;to right 左右结构font-family: DIN, DIN;font-weight: normal;font-size: 22px;color:…

基于WPF技术的换热站智能监控系统09--封装水泵对象

1、添加用户控件 2、编写水泵UI 控件中用到了Viewbox控件&#xff0c;Viewbox控件是WPF中一个简单的缩放工具&#xff0c;它可以帮助你放大或缩小单个元素&#xff0c;同时保持其宽高比。通过样式和属性设置&#xff0c;你可以创建出既美观又功能丰富的用户界面。在实际开发中…

uniapp原生插件开发实战——集成Android端的Twitter登陆

Android集成Twitter登陆的官方教程:https://github.com/twitter-archive/twitter-kit-android/wiki 项目创建 首先可以先看下uniapp原生插件开发教程 uniapp原生插件类型分为两种: Module模式:能力扩展,无嵌入窗体的UI控件,类似于功能插件。Component模式:在窗体中内嵌…

【2024亲测无坑】Oracle--19C在Centos7上的静默安装(rpm版)

一、Oracle 19c Linux安装&#xff08;Centos 7&#xff09; 1.查看磁盘可用空间及配置ip地址 [rootlocalhost /]# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 1.4G 0 1.4G 0% /dev tmpfs 1.4G …

C#——值类型和引用类型的区别详情

值类型和引用类型的区别 值类型 值类型&#xff1a; 常用的基本数据类型都是值类型&#xff1a;bool 、char、int、 double、 float、long 、 byte 、ulong、uint、枚举类型、 结构体类型等特点: 在赋值的过程当中&#xff0c;把值的本身赋值给另一个变量&#xff0c;再修改…

【python】OpenCV—Histogram Matching(9.2)

学习来自OpenCV基础&#xff08;17&#xff09;基于OpenCV、scikit-image和Python的直方图匹配 文章目录 直方图匹配介绍scikit-image 中的直方图匹配小试牛刀风格迁移 直方图匹配介绍 直方图匹配&#xff08;Histogram Matching&#xff09;是一种图像处理技术&#xff0c;旨…

【图论应用】使用多路图(multigraph)对上海地铁站点图建模,并解决最短路径问题

文章目录 1 前言2 导包导入数据集3 创建多路图&#xff0c;导入节点和边信息3 绘制线路图4 计算最短路径 1 前言 最近正在学习图神经网络&#xff0c;先pick up了一些最基础的图论知识并学习了一些好玩的应用。 本文启发于B站视频&#xff08;BV1LY411R7HJ&#xff09;&#…

经验分享,如何去除文本中的空格

有时候我们需要去掉一窜文本中的空格&#xff0c;这里分享一个好用的免费网站&#xff0c;可实现在线去除 网址&#xff1a;http://www.txttool.com/t/?idMzM4 使用截图&#xff1a;

redis 笔记2之哨兵

文章目录 一、哨兵1.1 简介1.2 实操1.2.1 sentinel.conf1.2.2 问题1.2.3 哨兵执行流程和选举原理1.2.4 使用建议 一、哨兵 1.1 简介 上篇说了复制&#xff0c;有个缺点就是主机宕机之后&#xff0c;从机只会原地待命&#xff0c;并不能升级为主机&#xff0c;这就不能保证对外…

牛客网华为机试java版

目录 HJ1 字符串最后一个单词的长度HJ2 计算某字符出现次数HJ3 明明的随机数HJ4 字符串分隔HJ5 进制转换HJ6 质数因子HJ7 取近似值HJ8 合并表记录HJ9 提取不重复的整数HJ26 字符串排序HJ80 整型数组合并HJ101 输入整型数组和排序标识&#xff0c;对其元素按照升序或降序进行排序…

困惑度作为nlp指标的理解示例

为了更清晰地说明困惑度的计算过程以及如何通过困惑度判断模型的优劣&#xff0c;我们可以通过一个简单的例子来演示。假设我们有一个非常简单的文本语料库和两个基础的语言模型进行比较。 示例文本 假设我们的文本数据包括以下两个句子&#xff1a; “cat sits on the mat”…

贷款投资决策和常用财务函数

前段时间上了一门excel操作的课&#xff0c;本文结合其中介绍财务函数以及投资决策分析相关的部分&#xff0c;对贷款中的现金流计算进行深入的分析。 以等额本息产品为例进行实操计算&#xff0c;假设某产品本金12000元&#xff0c;期限12&#xff0c;IRR利率24%。每期还款113…

VScode中连接并使用docker容器

前提条件&#xff1a; 1.在windows下安装Docker Desktop(方法可见下面的教程) Docker Desktop 安装使用教程-CSDN博客 2.在vscode安装3个必备的插件 3.先在ubuntu中把docker构建然后运行 4.打开vscode&#xff0c;按下图顺序操作 调试好之后上传到git上&#xff0c;然后后面…