feat: 新增7个工具

工具:帮你选择(#)
工具:摩斯电码(#)
工具:生成随机数(#)
工具:数字转金额大写(#)
工具:文本对比(#)
工具:markdown编辑器(#)
工具:文字转图片(#)
This commit is contained in:
osiris
2023-12-18 11:50:00 +08:00
parent 1986fb8281
commit 04537038c5
15 changed files with 4199 additions and 11 deletions
+94
View File
@@ -0,0 +1,94 @@
<script setup lang="ts">
import { reactive, onMounted,ref } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
// import { copy } from '@/utils/string'
const info = reactive({
title: "帮我决定",
scope: '', //多个用`,`隔开
randomVal: '',
checked: '0',
food: '沙县,烧腊,小炒肉,兰州拉面,汤饭,黄焖鸡,卤肉饭,蛋炒饭,羊肉粉,螺蛳粉,猪脚饭,白切鸡,肯德基,火锅,烧烤,泡面,西北风,煎饼果子',
subject: '电影,听音乐,游戏,逛街,看电视,睡觉,吃饭,清洁,锻炼,学习,发呆,散步,购物,回家,唱歌',
})
const chooseStatus = ref(false)
const changeCheckBox = (val: any) => {
switch(val) {
case '0':
info.scope = info.food
break;
case '1':
info.scope = info.subject
break;
default:
info.scope = ''
break;
}
}
const init = () => {
changeCheckBox(info.checked)
}
//选择
const choose = () => {
chooseStatus.value = true
let count = 0
let scopeList = info.scope.split(',')
const chooseInterval = setInterval(() => {
const randomNum = Math.floor(Math.random() * scopeList.length);
info.randomVal = scopeList[randomNum]
count++
if (count > 10) {
clearTimeout(chooseInterval)
chooseStatus.value = false
}
}, 50)
}
//clear
const clear = () => {
info.scope = ''
info.checked = ''
info.randomVal = ''
}
onMounted(() => {
init()
})
</script>
<template>
<div class="flex flex-col mt-3 ml-4 flex-1 mr-10">
<DetailHeader :title="info.title"></DetailHeader>
<div class="">
<div>
<el-radio-group v-model="info.checked" @change="changeCheckBox">
<el-radio label="0" size="large">吃什么</el-radio>
<el-radio label="1" size="large">干什么</el-radio>
</el-radio-group>
</div>
<div>
<el-input type="textarea" v-model="info.scope" :rows="5"></el-input>
</div>
<div class="text-5xl h-24 leading-[6rem]" v-if="info.randomVal != ''">
{{ info.randomVal }}
<!-- <el-text class=""></el-text> -->
</div>
<div class="mt-3">
<el-button @click="choose" v-if="!chooseStatus" type="primary">帮我决定</el-button>
<el-button @click="choose" type="primary" disabled v-else>决定中...</el-button>
<el-button @click="clear">清空</el-button>
</div>
</div>
</div>
</template>
<style scoped>
</style>
+39
View File
@@ -0,0 +1,39 @@
<script setup lang="ts">
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { CodeDiff } from "v-code-diff";
// import { copy } from '@/utils/string'
const info = reactive({
title: "文本对比",
leftTxt: '旧文本',
rightTxt: '新文本'
})
//copy
// const copyRes = async (resStr: string) => {
// copy(resStr)
// }
</script>
<template>
<div class="flex flex-col mt-3 ml-4 flex-1 mr-10">
<DetailHeader :title="info.title"></DetailHeader>
<div class="">
<div class="flex justify-between">
<el-input type="textarea" :rows="16" v-model="info.leftTxt"></el-input>
<el-input type="textarea" :rows="16" v-model="info.rightTxt" class="ml-3"></el-input>
</div>
<code-diff
:old-string="info.leftTxt"
:new-string="info.rightTxt"
output-format="side-by-side"
theme="dark"
/>
</div>
</div>
</template>
<style scoped>
</style>
+29
View File
@@ -0,0 +1,29 @@
<script setup lang="ts">
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
const info = reactive({
title: "在线markdown编辑器",
content: '',
})
//copy
// const copyRes = async (resStr: string) => {
// copy(resStr)
// }
</script>
<template>
<div class="flex flex-col mt-3 ml-4 flex-1 mr-10">
<DetailHeader :title="info.title"></DetailHeader>
<div class="">
<v-md-editor v-model="info.content" height="500px"></v-md-editor>
</div>
</div>
</template>
<style scoped>
</style>
+57
View File
@@ -0,0 +1,57 @@
<script setup lang="ts">
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { copy } from '@/utils/string'
import { toMorse, toText } from '@/utils/morse'
const info = reactive({
title: "摩斯电码",
content: '支持中文的摩斯电码编码(Encode)解码(Decode)',
tranRes: '',
})
const toEncode = () => {
info.tranRes = toMorse(info.content)
}
const toDecode = () => {
info. tranRes = toText(info.content)
}
const clear = () => {
info.content = ''
info.tranRes = ''
}
//copy
const copyRes = async (resStr: string) => {
copy(resStr)
}
</script>
<template>
<div class="flex flex-col mt-3 ml-4 flex-1 mr-10">
<DetailHeader :title="info.title"></DetailHeader>
<div class="">
<div>
<el-input type="textarea" :rows="8" v-model="info.content"></el-input>
</div>
<div class="mt-4">
<el-button type="primary" @click="toEncode">摩斯编码</el-button>
<el-button type="primary" @click="toDecode">摩斯解码</el-button>
<el-button type="primary" @click="copyRes(info.tranRes)">复制结果</el-button>
<el-button type="danger" @click="clear">清空内容</el-button>
</div>
<div class="mt-3 min-h-md bg-gray-100 p-3 mb-3">
<el-input type="textarea" :rows="8" v-model="info.tranRes"></el-input>
</div>
</div>
</div>
</template>
<style scoped>
</style>
@@ -0,0 +1,50 @@
<script setup lang="ts">
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { copy, numberToChinese } from '@/utils/string'
const info = reactive({
title: "数字转金额大写",
content: '',
tranRes: '',
})
const tran = (type: number) => {
//数字转中文
info.tranRes = numberToChinese(info.content)
}
const clear = () => {
info.content = ''
info.tranRes = ''
}
const copyRes = async (resStr: string) => {
copy(resStr)
}
</script>
<template>
<div class="flex flex-col mt-3 ml-4 flex-1 mr-10">
<DetailHeader :title="info.title"></DetailHeader>
<div class="">
<div>
<el-input type="number" v-model="info.content" placeholder="请输入数字,最高13位数字"></el-input>
</div>
<div class="mt-4">
<el-button type="primary" @click="tran">数字转中文大写</el-button>
<el-button type="primary" @click="copyRes(info.tranRes)">复制结果</el-button>
<el-button type="danger" @click="clear">清空内容</el-button>
</div>
<div class="mt-3 min-h-md bg-gray-100 p-3 mb-3">
<el-input type="textarea" :rows="8" v-model="info.tranRes"></el-input>
</div>
</div>
</div>
</template>
<style scoped>
</style>
+56
View File
@@ -0,0 +1,56 @@
<script setup lang="ts">
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
// import { copy } from '@/utils/string'
const info = reactive({
title: "生成随机数",
startNum: 1,
endNum: 100,
resNum: 0,
genStatus: false,
})
const random = () => {
info.genStatus = true
let count = 0
const genInterval = setInterval(() => {
info.resNum = Math.floor(Math.random() * (info.endNum - info.startNum + 1)) + info.startNum;
count++
if (count > 10) {
clearTimeout(genInterval)
info.genStatus = false
}
}, 50)
}
//copy
// const copyRes = async (resStr: string) => {
// copy(resStr)
// }
</script>
<template>
<div class="flex flex-col mt-3 ml-4 flex-1 mr-10">
<DetailHeader :title="info.title"></DetailHeader>
<div class="flex flex-col items-center">
<div>
<el-input-number v-model="info.startNum" :min="0" size="large"/>
<el-input-number v-model="info.endNum" :min="0" size="large" class="ml-5"/>
</div>
<div class="h-60 text-8xl leading-[15rem]">
{{ info.resNum }}
</div>
<div>
<el-button @click="random" type="primary" size="large" v-if="!info.genStatus">生成</el-button>
<el-button @click="random" type="primary" size="large" disabled v-else>生成...</el-button>
</div>
</div>
</div>
</template>
<style scoped>
</style>
+142
View File
@@ -0,0 +1,142 @@
<script setup lang="ts">
import { reactive, ref, shallowRef, onBeforeUnmount } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import html2canvas from "html2canvas";
import '@wangeditor/editor/dist/css/style.css' // 引入富文本 css
import { Editor, Toolbar } from '@wangeditor/editor-for-vue' //富文本组件
// import { copy } from '@/utils/string'
const info = reactive({
title: "文本转图片",
mode: 'default',
convasWidth: 860,
convasBackgroundColor: '#fff',
downExt: '.png',
downExts: [
{
value: '.png',
label: '.png'
},
{
value: '.jpg',
label: '.jpg'
},
]
})
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef()
// 内容 HTML
const valueHtml = ref(`文字转图片演示😀
拥有丰富的样式选择
可自由调整宽度背景色
支持一键导出为长图
`)
// 绑定 需要把那个内容生成图片
const poster = ref();
// 工具栏配置
const toolbarConfig = {
excludeKeys: [
"uploadImage",
"group-video",
"insertLink",
]
}
//编辑器配置
const editorConfig = { placeholder: '请输入内容...' }
const handleCreated = (editor) => {
editorRef.value = editor // 记录 editor 实例,重要!
}
const goDown =() => {
html2canvas(poster.value, {
backgroundColor: info.convasBackgroundColor,//海报的背景颜色
useCORS: true, // 允许跨域
width: info.convasWidth, //生成海报的w
}).then(canvas=>{
// canvas 其实就是我们所讲的res 的意思 返回报文的意思
let baseImg = canvas.toDataURL("image/png");
if (info.downExt == '.jpg') {
baseImg = canvas.toDataURL("image/jpg");
}
//创建a标签
let save = document.createElement('a');
// <a href=''></a>
save.href = baseImg;
// 下载的名字
save.download = 'yz'
// 直接回调a的点击事件
save.click()
})
}
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value
if (editor == null) return
editor.destroy()
})
//copy
// const copyRes = async (resStr: string) => {
// copy(resStr)
// }
</script>
<template>
<div class="flex flex-col mt-3 ml-4 flex-1 mr-10">
<DetailHeader :title="info.title"></DetailHeader>
<div class="">
<div>
<div class="">
<div class="flex items-center">
<el-text class="w-20">宽度</el-text>
<el-slider v-model="info.convasWidth" show-input size="large" :min="260" :max="1920"/>
</div>
</div>
<div class="mt-3 flex items-center justify-between">
<div class="">
<el-text>背景颜色</el-text>
<el-color-picker v-model="info.convasBackgroundColor" size="large" />
</div>
<div>
<el-select v-model="info.downExt" class="" placeholder="Select">
<el-option
v-for="item in info.downExts"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-button type="primary" class="ml-2" @click="goDown">下载</el-button>
</div>
</div>
</div>
<div class="border relative z-10 mt-3">
<Toolbar
class="border-b"
:editor="editorRef"
:defaultConfig="toolbarConfig"
:mode="info.mode"
/>
<Editor
v-model="valueHtml"
:defaultConfig="editorConfig"
:mode="info.mode"
@onCreated="handleCreated"
/>
<div ref="poster" class="absolute top-0 -z-10" v-html="valueHtml"></div>
</div>
<!-- v-html="valueHtml" -->
</div>
</div>
</template>
<style scoped>
</style>