遇到后立刻解决,遇不到这就是“废材”
其实工作中的一些需求还是挺不常见的,遇到了这些需求就会记录下来,防止下次出现这个需求,还需要去看巨量的博客文章,所以这里记录一下。
md编辑器
由于项目需要,需要在后台中集成docusaurus
文档编辑器。docusaurus 真的是一个非常好看的静态文档生成器。
但是由于docusaurus
有自己定义的语法,不完全是md。起初在网上想要找一个基于docusaurus
的编辑器,mdx
语法,还是不支持docusaurus
内置的组件。
然后使用公司其他项目都在使用的md编辑器mavon-editor
。他是基于vue2
的, 下面来看一下基础使用吧。
// main.js
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
Vue.use(mavonEditor)
使用组件
<mavon-editor
ref="mavonEditorRef"
v-model="mavonContent"
:toolbars="toolbars"
@change="changeContent"
class="editor-content"
@imgAdd="imgAdd"
:ishljs="true"
/>
工具栏配置
toolbars: {
bold: true, // 粗体
italic: true, // 斜体
header: true, // 标题
underline: true, // 下划线
strikethrough: true, // 中划线
mark: true, // 标记
superscript: true, // 上角标
subscript: true, // 下角标
quote: true, // 引用
ol: true, // 有序列表
ul: true, // 无序列表
link: true, // 链接
imagelink: true, // 图片链接
code: true, // code
table: true, // 表格
fullscreen: true, // 全屏编辑
readmodel: true, // 沉浸式阅读
htmlcode: true, // 展示html源码
help: true, // 帮助
/* 1.3.5 */
undo: true, // 上一步
redo: true, // 下一步
trash: true, // 清空
save: false, // 保存(触发events中的save事件)
/* 1.4.2 */
navigation: true, // 导航目录
/* 2.1.8 */
alignleft: true, // 左对齐
aligncenter: true, // 居中
alignright: true, // 右对齐
/* 2.2.1 */
subfield: true, // 单双栏模式
preview: true, // 预览
},
文件上传
// 处理图片上传
imgAdd(pos, file) {
const fd = new FormData()
fd.append('file', file)
axios({
url: process.env.VUE_APP_BASE_API + '/uploading',
method: 'post',
headers: { 'Content-Type': 'multipart/form-data' },
data: fd,
}).then((res) => {
if (res.resultCode === 1) {
this.$refs.mavonEditorRef.$img2Url(pos, res.datum)
this.$message.success(res.resultInfo)
}
})
},
xml在线预览编辑
这个需求的完成也是找了很多库去测试,普通的md编辑器预览并编辑,对于大文件的xml,会非常非常非常的卡。所以就是放弃了。
上网搜了一下在线xml编辑器,发现了一个简单优雅的编辑器,并且复制很大的内容粘贴并不会卡顿,于是就打开了sources,分析一下他加载的类库。
有了这个思路就上网搜了一下ace库。这个库叫做ace-builds
。并且结合vkbeautify
格式化xml内容。
下面来看一下它的使用
<div ref="ace" class="ace-editor"></div>
import ace from 'ace-builds'
import 'ace-builds/webpack-resolver'
import vkbeautify from 'vkbeautify'
props: {
value: {
type: String,
default: '',
},
themePath: {
type: String,
default: 'ace/theme/tomorrow_night',
},
modePath: {
type: String,
default: 'xml',
},
maxLines: {
type: Number,
default: 20,
},
minLines: {
type: Number,
default: 20,
},
},
data() {
return {
aceEditor: null,
currentValue: this.value,
}
},
watch: {
value: {
handler(newValue) {
if (newValue === '' || newValue) {
this.aceEditor.setValue(vkbeautify.xml(newValue))
}
},
},
modePath: {
handler(newValue) {
if (newValue) {
this.aceEditor.getSession().setMode('ace/mode/' + newValue)
}
},
},
},
mounted() {
this.aceEditor = ace.edit(this.$refs.ace, {
value: this.value,
// maxLines: this.maxLines,
// minLines: this.minLines,
fontSize: 12,
// 主题
theme: this.themePath,
// 语言模式
mode: 'ace/mode/' + this.modePath,
tabSize: 2,
})
},
methods: {
// 格式化xml内容
handleFormatter() {
const value = this.aceEditor.getSession().getValue()
this.aceEditor.setValue(vkbeautify.xml(value))
},
},
接口请求数据,然后直接调用vkbeautify来格式化代码,然后赋值
vkbeautify.xml(res.data)
下面提供一下当时的参考文章
- ajaxorg.github.io/ace-api-doc…
- blog.csdn.net/qq_27971677…
- 即使引入了
ace-builds/webpack-resolver
,他还是会报define is not defined
。blog.csdn.net/weixin_4461… 这种情况我只在测试的时候遇见过,在项目中使用的时候没有遇见过。
实现签到功能
这个需求是我们把签到单独做成一个页面,而不是页面里面的按钮。我们点击了这个页面就会触发签到接口,所以我们需要去控制一下。
如果是签到做成一个页面的按钮,这些操作就不需要去做了,因为当用户点击按钮,就会给出提示请勿重复签到
。
// 判断当前事件是否到达零点
const currentTime = new Date()
// 根据道当前时间和第二天0点时间比较
if(currentTime.getTime() > utils.getItem("isFirstSign").secDayStamp) {
this.isFirstSign = true
this.secDayStamp = new Date(currentTime.setHours(0, 0, 0, 0) + 24 * 60 * 60 * 1000).getTime()
utils.setItem("isFirstSign", {
state: this.isFirstSign,
secDayStamp: this.secDayStamp
})
}else {
if(utils.getItem("isFirstSign")) {
this.isFirstSign = utils.getItem("isFirstSign").state
}else {
this.isFirstSign = true
}
}
if(this.isFirstSign) {
// 调取签到接口
this.handleSign()
}
递归请求接口,并生成数据菜单
总体来说这个需求很麻烦的,我们主要的设计思路就是
- 实时预览文档编辑,
docusaurus
语法忽略,使用md代替。 - 当编辑完成文档时,我们就去将文件插入到
docusaurus
项目中,然后并提交到git仓库中,并且执行npm run dev
命令运行docusaurus
项目。 - 还设有就是一些创建目录什么的。于是就有了递归调用接口获取目录菜单。
async getCatalogList() {
this.docCatalogList = []
this.docCatalogMenu = []
// 这里是获取docs下的所有直接子级目录
const res = await this.$request.Admin.getChildFileByDir({
filePath: '',
fileType: '',
})
if (res.resultCode == 1) {
for (let index in res.data) {
this.docCatalogList.push({
...res.data[index],
children: [],
})
// 这个是为了让二级目录可以显示在外面,和根目录一起。
if (res.data[index].queryPath != 'docs') {
this.getRecursionToDir(
res.data[index],
this.docCatalogList[index].children
)
}
// // 再次请求内部的菜单
// if (res.data[index].queryPath != 'docs') {
// // const res2 = await this.$request.Admin.getChildFileByDir({
// // filePath: res.data[index].queryPath,
// // fileType: 2, // 2: 请求菜单
// // })
// const res2 = await this.getChildFileByDir(
// res.data[index].queryPath
// )
// if (res2.resultCode == 1) {
// this.docCatalogList[index].children = res2.data
// }
// }
}
// 过滤掉非菜单对象
for (let item of this.docCatalogList) {
if (
item.queryPath != 'docs' ||
(item.queryPath == 'docs' && item.name == 'README.md')
) {
if (item.queryPath == 'docs') {
item.title = '根目录'
}
this.docCatalogMenu.push(item)
}
}
}
},
// 递归函数 currentMenu当前菜单, menu菜单列表(当前菜单子菜单列表)
async getRecursionToDir(currentMenu, menu) {
// 这里便利一级目录的title。然后调用接口获取其他层级目录。
const res = await this.getChildFileByDir(currentMenu.queryPath) // 这里可能会返回空值
if (res.length) {
for (let index in res) {
// parentMenu.children
menu.push({
...res[index],
children: [],
})
}
}
if (menu.length) {
for (let item of menu) {
this.getRecursionToDir(item, item.children) // 这里我只需要传入一个数据,存放该item的值即可。
}
}
},
// 获取单个目录下的所有目录
async getChildFileByDir(queryPath) {
const res = await this.$request.Admin.getChildFileByDir({
filePath: queryPath,
fileType: 2, // 2: 请求目录
})
if (res.resultCode == 1) {
return res.data
} else {
return []
}
},
h5接入微信登录
上次了一篇文章主要是记录一下这个过程,防止小白无从下手。
amis自定义组件
这里需要你了解amis这个低代码平台。不了解的可以看这里
amis内的jsoneditor组件是非常难看的,使用起来也是非常不方便的,所以我们结合jsoneditor
库,实现一个通用的json编辑器。
(function() {
let React = amisRequire('react');
let amisLib = amisRequire("amis");
let amis = amisRequire('amis/embed');
/**
* @param {*} props
* @description label, width, height 在使用这个组件的时候,需要提前在form表单中定义好用到的属性
* @returns
*/
function CustomComponent(props) {
let dom = React.useRef(null);
React.useEffect(function () {
// console.log("props", props)
dom.current.setAttribute("class", "antd-Form-item antd-Form-item--horizontal")
// dom.current.style.width = props.width ? `${props.width}px` : "400px"
dom.current.style.height = props.height ? `${props.height}px` : "225px"
// dom.current.style.marginBottom = props.mb ? `${props.mb}px` : "24px"
dom.current.innerHTML = `
<label class="custom-jsoneditor-label antd-Form-label ${props?.labelColumn != 0 ? 'antd-Form-itemColumn--4' : ''}">
<span>
<span class="antd-TplField" data-debug-id="6040a585-c654-4000-aea5-c1aa1a2c5000">
<span>${props?.label}</span>
</span>
</span>
</label>
<div
id="custom-editor-wrapper-${props?.name}"
class="antd-Form-value ${props?.labelColumn == 0 ? 'antd-Form-itemColumn--12' : 'antd-Form-itemColumn--6'}"
></div>
`
// 这里不能用id,id全局唯一,这里使用class
const wrapper = document.getElementById(`custom-editor-wrapper-${props?.name}`)
const editor = new JSONEditor(wrapper, {
mode: 'code',
modes: ['code', 'text', 'tree', 'preview'],
// onValidationError: function(errors) {
// console.log('onValidationError', errors);
// },
// 只有输入的json格式正确才会赋值
onValidate: function (json) {
// console.log("json", json)
// props.data = {
// ...props.data,
// [props?.name]: json
// }
props.data[props?.name] = json
},
})
// set json
const initialJson = props.data && props.data[props?.name]
editor.set(initialJson)
});
return React.createElement('div', {
ref: dom
});
}
amisLib.Renderer({
test: /(^|\/)custom-jsoneditor/
})(CustomComponent);
})()
除此之外还定义了一下和业务强相关的组件,这里就不贴代码了。
source中修改代码并执行
这个需求其实也很常见,有时候状态值后端传递错误,我们可以在source中直接修改对应的代码(只修改代码的话,立刻刷新他还是会重新请求新的代码,然后执行),做一些相应的操作就刷新页面就可以执行修改后的代码了。
然后右键修改的文件,点击save for overrides
按照上面的操作修改内容后,然后点击刷新就行了。
设置git账号密码
刚来到一家公司,我们肯定会去做这个操作的。所以这里记录一下。
这个还是上次修改一下公司的工作网页的登录密码,这个就不能用了,所以需要重新设置。(公司的gitee和所有工作网页的密码都是绑定的)
控制面板–>用户账户–>管理Windows凭据
转载自:https://juejin.cn/post/7189087220970553402