feat: 新增3个工具,样式修复,修改logo,保存桌面

新增功能:
 - js代码格式化/压缩
 - html代码格式化
 - css代码格式化/压缩
 - 保存到桌面

其他修改:
 - 修改logo
 - 修复一些样式问题
 - 修复一些已知的问题
This commit is contained in:
taoran
2024-06-18 17:40:32 +08:00
parent f05ee53440
commit 95b7fec3b5
17 changed files with 1878 additions and 1030 deletions
+24 -11
View File
@@ -49,6 +49,22 @@ const searchTools = async (query: string) => {
loading.value = false
}
//保存到桌面
const createUrlShortcut = async () => {
try {
const blob = new Blob(
[`[InternetShortcut]\nURL=${encodeURI(window.location.href)}`],
{ type: 'text/plain' }
);
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'Tools-Web.url';
a.click();
} catch (error) {
console.error('创建URL快捷方式失败:', error);
}
}
const optionClick = (url: string) => {
router.push(url)
}
@@ -109,7 +125,7 @@ onMounted(() => {
placeholder="输入关键词搜索,如文本、json、图片等"
:remote-method="searchTools"
:loading="loading"
class="ml-3 mr-3 md:w-[45rem] c-xs:w-60"
class="ml-3"
size="large"
>
<el-option
@@ -153,10 +169,9 @@ onMounted(() => {
</el-tooltip>
</li>
<!-- <li class="hover:text-blue-500">
<el-link :href="www.baidu.com" size="large" target="_blank">建议/问题</el-link>
</li> -->
<li class="hover:text-blue-500">
<el-button type="primary" class="ml-3 bg-gradient-to-r from-cyan-500 to-blue-500" @click="createUrlShortcut">保存到桌面</el-button>
</li>
</ul>
</div>
</header>
@@ -174,15 +189,13 @@ onMounted(() => {
}
:deep(.el-input__wrapper) {
:deep(.el-select__wrapper) {
box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color)) inset;
cursor: default;
@apply md:w-[40rem] c-xs:w-60;
}
:deep(.el-input__wrapper) {
box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color)) inset;
cursor: default;
}
.el-select :deep(.el-input__wrapper){
.el-select :deep(.el-select__wrapper){
background-color: rgba(46, 51, 56, 0.05);
background-color: rgb(255, 255, 255);
}
@@ -136,8 +136,10 @@ onMounted(() => {
<div class="mb-6">
<el-input v-model="content" :rows="4" type="textarea" placeholder="请输入内容"></el-input>
<div class="mt-3 flex items-center">
<div class="flex items-center mr-3">
<el-text>风格</el-text>
<div class="flex items-center mr-3 w-36">
<div class="w-10">
<el-text class="">风格</el-text>
</div>
<el-select
v-model="fontStyle"
size="default"
@@ -0,0 +1,88 @@
<script setup lang="ts">
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { copy } from '@/utils/string';
import { Codemirror } from "vue-codemirror";
import '@codemirror/search';
import '@codemirror/state';
import '@codemirror/commands';
import * as prettier from "prettier/standalone";
import * as parserCss from 'prettier/parser-postcss';
import { ElMessage } from 'element-plus'
import { minify } from "csso"
const info = reactive({
title: "css代码格式化/压缩",
code: '',
isParseErr: false,
parseErr: '',
})
//格式化
const formatCode = async () => {
try {
info.code = await prettier.format(info.code, { parser: "css", plugins: [parserCss]})
} catch (error) {
console.log(error)
ElMessage({
showClose: true,
message: '请填入正确代码格式',
type: 'error',
})
}
}
//压缩
const compress = async () => {
try {
info.code = minify(info.code, {
restructure: true,
}).css
} catch (error) {
console.log(error)
}
}
//清空输入框
const clear = () => {
info.code = ''
}
const copyRes = async () => {
copy(info.code)
}
</script>
<template>
<div class="flex flex-col mt-3 flex-1">
<DetailHeader :title="info.title"></DetailHeader>
<div class="p-4 rounded-2xl bg-white ">
<div>
<codemirror
v-model="info.code"
placeholder="这里是代码..."
:style="{ height: '400px' }"
:autofocus="true"
:indent-with-tab="true"
:tabSize="2"
/>
</div>
<div class="mt-4">
<el-button type="primary" @click="formatCode">格式化</el-button>
<el-button type="primary" @click="compress">压缩</el-button>
<el-button type="primary" @click="copyRes">复制</el-button>
<el-button type="primary" @click="clear">清空</el-button>
</div>
<div class="mt-3 min-h-md bg-red-100 p-3 mb-3" v-show="info.isParseErr">
<el-text type="danger">{{ info.parseErr }}</el-text>
</div>
</div>
</div>
</template>
<style scoped>
</style>
@@ -0,0 +1,74 @@
<script setup lang="ts">
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { copy } from '@/utils/string';
import { Codemirror } from "vue-codemirror";
import '@codemirror/search';
import '@codemirror/state';
import '@codemirror/commands';
import * as prettier from "prettier/standalone";
import * as parserHtml from 'prettier/parser-html';
import { ElMessage } from 'element-plus';
const info = reactive({
title: "html格式化/压缩",
code: '',
isParseErr: false,
parseErr: '',
})
//格式化
const formatCode = async () => {
try {
info.code = await prettier.format(info.code, { parser: "html", plugins: [parserHtml]})
} catch (error) {
ElMessage({
showClose: true,
message: '请填入正确代码格式',
type: 'error',
})
}
}
//清空输入框
const clear = () => {
info.code = ''
}
const copyRes = async () => {
copy(info.code)
}
</script>
<template>
<div class="flex flex-col mt-3 flex-1">
<DetailHeader :title="info.title"></DetailHeader>
<div class="p-4 rounded-2xl bg-white ">
<div>
<codemirror
v-model="info.code"
placeholder="这里是代码..."
:style="{ height: '400px' }"
:autofocus="true"
:indent-with-tab="true"
:tabSize="2"
/>
</div>
<div class="mt-4">
<el-button type="primary" @click="formatCode">格式化</el-button>
<el-button type="primary" @click="copyRes">复制</el-button>
<el-button type="primary" @click="clear">清空</el-button>
</div>
<div class="mt-3 min-h-md bg-red-100 p-3 mb-3" v-show="info.isParseErr">
<el-text type="danger">{{ info.parseErr }}</el-text>
</div>
</div>
</div>
</template>
<style scoped>
</style>
+102
View File
@@ -0,0 +1,102 @@
<script setup lang="ts">
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { copy } from '@/utils/string';
import { Codemirror } from "vue-codemirror";
import '@codemirror/search';
import '@codemirror/state';
import '@codemirror/commands';
import * as prettier from "prettier/standalone";
import * as parserBabel from 'prettier/parser-babel';
import * as prettierPluginEstree from "prettier/plugins/estree";
import { ElMessage } from 'element-plus'
import { minify } from "terser"
const info = reactive({
title: "js代码格式化/压缩",
code: '',
isParseErr: false,
parseErr: '',
})
interface Error {
name: string;
message: string;
stack?: string;
}
//格式化
const formatCode = async () => {
try {
info.code = await prettier.format(info.code, { parser: "babel", plugins: [parserBabel, prettierPluginEstree]})
} catch (error) {
ElMessage({
showClose: true,
message: '请填入正确的js代码',
type: 'error',
})
}
}
//混淆压缩
const confuseCompress = async () => {
try {
let res = await minify(info.code, {
mangle: {
toplevel: true,
}
})
info.code = res.code != undefined ? res.code : info.code
} catch(error) {
ElMessage({
showClose: true,
message: '请填入正确的js代码: ' + (error as Error).message,
type: 'error',
})
}
}
//清空输入框
const clear = () => {
info.code = ''
}
const copyRes = async () => {
copy(info.code)
}
</script>
<template>
<div class="flex flex-col mt-3 flex-1">
<DetailHeader :title="info.title"></DetailHeader>
<div class="p-4 rounded-2xl bg-white ">
<div>
<codemirror
v-model="info.code"
placeholder="这里是代码..."
:style="{ height: '400px' }"
:autofocus="true"
:indent-with-tab="true"
:tabSize="2"
/>
</div>
<div class="mt-4">
<el-button type="primary" @click="formatCode">格式化</el-button>
<el-button type="primary" @click="confuseCompress">混淆压缩</el-button>
<el-button type="primary" @click="copyRes">复制</el-button>
<el-button type="primary" @click="clear">清空</el-button>
</div>
<div class="mt-3 min-h-md bg-red-100 p-3 mb-3" v-show="info.isParseErr">
<el-text type="danger">{{ info.parseErr }}</el-text>
</div>
</div>
</div>
</template>
<style scoped>
</style>
+1 -2
View File
@@ -5,7 +5,6 @@ import { transferred, copy } from '@/utils/string';
import { Codemirror } from "vue-codemirror";
import { json } from '@codemirror/lang-json';
import '@codemirror/search';
import { lineNumbers } from '@codemirror/view';
import '@codemirror/state';
import '@codemirror/commands';
// import { syntaxTree } from '@codemirror/language';
@@ -31,7 +30,7 @@ import '@codemirror/commands';
const info = reactive({
title: "Json在线转换",
code: '',
extensions: [json(), lineNumbers()],
extensions: [json()], //[json(), lineNumbers()],
isParseErr: false,
parseErr: ''
})
+23 -15
View File
@@ -68,25 +68,27 @@ const gen = () => {
<div class="w-16 mr-2"><el-text>尺寸</el-text></div>
<el-input v-model="info.size" class="">
<template #append>
<el-select v-model="info.size" class="w-32">
<el-option label="常规 200px" value="200" />
<el-option label="常规 300px" value="300" />
<el-option label="适中 350px" value="350" />
<el-option label="较大 500px" value="500" />
<!-- 分割线 start -->
<div class="flex justify-center bg-gray-200 w-full">
<div class="h-[1px] bg-gray-200 w-4/5"></div>
</div>
<!-- 分割线 end -->
<el-option label="超大 1000px" value="1000" />
<el-option label="超大 1200px" value="1200" />
</el-select>
<el-select v-model="info.size" class="size-select">
<el-option label="常规 200px" value="200" />
<el-option label="常规 300px" value="300" />
<el-option label="适中 350px" value="350" />
<el-option label="较大 500px" value="500" />
<!-- 分割线 start -->
<div class="flex justify-center bg-gray-200 w-full">
<div class="h-[1px] bg-gray-200 w-4/5"></div>
</div>
<!-- 分割线 end -->
<el-option label="超大 1000px" value="1000" />
<el-option label="超大 1200px" value="1200" />
</el-select>
</template>
</el-input>
</div>
<div class="flex mb-3">
<el-text class="w-16">纠错级别</el-text>
<el-select v-model="info.errorCorrectionLevel" class="w-36">
<div class="w-16">
<el-text>纠错级别</el-text>
</div>
<el-select v-model="info.errorCorrectionLevel" class="corr-select">
<el-option label="L 可遮挡 7%" value="L" />
<el-option label="M 可遮挡 15%" value="M" />
<el-option label="Q 可遮挡 25%" value="Q" />
@@ -178,4 +180,10 @@ const gen = () => {
.my-button{
background-color:red;
}
.size-select{
@apply w-36
}
.corr-select{
@apply w-36
}
</style>
+2 -2
View File
@@ -2,11 +2,11 @@
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { Codemirror } from "vue-codemirror"
import { lineNumbers } from '@codemirror/view';
// import { lineNumbers } from '@codemirror/view';
const info = reactive({
title: "正则表达式测试",
extensions: [lineNumbers()],
// extensions: [lineNumbers()],
reg: '',
content: `一些测试实例:
邮箱1[email protected]
+4 -1
View File
@@ -200,7 +200,7 @@ const copyRes = async (index: any) => {
<div class="mr-2 w-full">
<el-input v-model="info.content">
<template #prepend>
<el-select v-model="info.chooseTranOptions" placeholder="Select" class="w-24">
<el-select v-model="info.chooseTranOptions" placeholder="Select" class="choosetranoptions-select">
<el-option
v-for="item in info.tranOptions"
:key="item.value"
@@ -252,4 +252,7 @@ const copyRes = async (index: any) => {
</template>
<style scoped>
.choosetranoptions-select{
@apply w-24
}
</style>
+5 -2
View File
@@ -104,8 +104,8 @@ onBeforeUnmount(() => {
<el-text>背景颜色</el-text>
<el-color-picker v-model="info.convasBackgroundColor" size="large" />
</div>
<div>
<el-select v-model="info.downExt" class="" placeholder="Select">
<div class="flex">
<el-select v-model="info.downExt" class="downext-select" placeholder="Select">
<el-option
v-for="item in info.downExts"
:key="item.value"
@@ -139,4 +139,7 @@ onBeforeUnmount(() => {
</template>
<style scoped>
.downext-select{
@apply w-24
}
</style>
+4 -12
View File
@@ -95,16 +95,6 @@ const copyRes = async () => {
<div class="flex flex-direction mt-4 justify-start">
<el-text class="mr-2 w-12">时间戳</el-text>
<el-input v-model="info.waitTimeStamp" class="h-8 mr-2 w-60 max-w-[30%]" placeholder="毫秒/秒">
<!-- <template #append>
<el-select v-model="info.chooseTranDateOption" placeholder="Select" class="w-24">
<el-option
v-for="item in info.tranOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template> -->
</el-input>
<el-button class="mr-2 max-w-[25%]" @click="timeTran('toDate')">转换</el-button>
<el-input v-model="info.tranDate" class="h-8 w-72 mr-2 max-w-[30%]" placeholder="北京时间"></el-input>
@@ -116,7 +106,7 @@ const copyRes = async () => {
<el-button class="mr-2 max-w-[25%]" @click="timeTran('toStamp')">转换</el-button>
<el-input v-model="info.tranTimeStamp" :value="info.tranTimeStamp == 0 ? '' : info.tranTimeStamp" class="h-8 w-72 mr-2 max-w-[30%]" placeholder="时间戳">
<template #prepend>
<el-select v-model="info.chooseTranStampOption" placeholder="Select" class="w-24">
<el-select v-model="info.chooseTranStampOption" placeholder="Select" class="trantimestamp-select">
<el-option
v-for="item in info.tranOptions"
:key="item.value"
@@ -137,5 +127,7 @@ const copyRes = async () => {
</template>
<style scoped>
.trantimestamp-select{
@apply w-24
}
</style>
+2 -2
View File
@@ -2,13 +2,13 @@
import { reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { Codemirror } from "vue-codemirror"
import { lineNumbers } from '@codemirror/view';
// import { lineNumbers } from '@codemirror/view';
import { copy } from '@/utils/string'
const info = reactive({
title: "Unicode转中文",
extensions: [lineNumbers()],
// extensions: [lineNumbers()],
content: '',
tranRes: '',
})
+52 -5
View File
@@ -106,6 +106,33 @@ export function getToolsCate() {
url: '/HtmlEntity/',
cateId: 2,
cate: '开发运维',
},
{
id: 1,
title: 'js代码格式化/压缩',
logo: '/images/logo/HtmlEntity.png',
desc: 'JS格式化/压缩工具,提供在线JS格式化、JS压缩、JS混淆、JS解密',
url: '/JSForamt/',
cateId: 2,
cate: '开发运维',
},
{
id: 1,
title: 'Html代码格式化/压缩',
logo: '/images/logo/HtmlEntity.png',
desc: 'html格式化/压缩工具,提供在线html格式化、html压缩',
url: '/HtmlFormat/',
cateId: 2,
cate: '开发运维',
},
{
id: 1,
title: 'Css代码格式化/压缩',
logo: '/images/logo/HtmlEntity.png',
desc: 'css格式化/压缩工具,提供在线css格式化、css压缩',
url: '/CssFormat/',
cateId: 2,
cate: '开发运维',
}
]
},
@@ -475,11 +502,8 @@ export function getToolsCate() {
]
}
//获取工具
export function getTools(data: ToolsReqData) {
//接收参数
const { cateId, title } = data
//获取工具
//工具list
export function toolsList() {
let list = [] as any[]
let toolsCate = getToolsCate()
for (let item in toolsCate) {
@@ -487,6 +511,28 @@ export function getTools(data: ToolsReqData) {
list.push(toolsCate[item].list[_item])
}
}
return list
}
/**
* url为键名的工具list map
* @returns
*/
export function urlKeyMap() {
// let toolsMapByUrlKey = new Map()
// let list = toolsList()
// for (let item in list) {
// toolsMapByUrlKey.set(list[item].url, list[item])
// }
// return toolsMapByUrlKey
}
//获取工具
export function getTools(data: ToolsReqData) {
//接收参数
const { cateId, title } = data
//获取工具list
let list = toolsList()
//标题筛选
if (title != '') {
@@ -509,6 +555,7 @@ export function getTools(data: ToolsReqData) {
const ToolsExport = {
getTools,
getToolsCate,
toolsList,
};
export default ToolsExport;