This commit is contained in:
2021-11-14 16:28:03 +08:00
parent 8617de5c38
commit 3a20686bfb
10 changed files with 301 additions and 286 deletions

View File

@@ -10,7 +10,7 @@ module.exports = {
mediaQuery: true,
propList: ['*'],
rootValue: 16,
unitPrecision: 3,
unitPrecision: 4,
}
}
};

View File

@@ -142,6 +142,11 @@ body {
}
.el-input {
&.is-disabled .el-input__inner {
background-color: #FFF;
color: #888;
}
input::-webkit-inner-spin-button,
input::-webkit-outer-spin-button {
-webkit-appearance: none;

View File

@@ -10,11 +10,7 @@ class Utils {
* @param {string} [value] 新的标题
*/
changeTitle(value) {
if (value) {
document.title = config.siteName + ' - ' + value;
} else {
document.title = config.siteName;
}
document.title = (value ? (value + ' - ') : '') + config.siteName;
}
/**

View File

@@ -1,5 +1,5 @@
<template>
<div class="tool-elem">
<div class="tool-page">
<div class="ctrl">
<div class="title">控制</div>

View File

@@ -1,5 +1,5 @@
<template>
<div class="tool-elem">
<div class="tool-page">
<div class="info">
<div class="title">配置选项 &amp; 结果</div>

View File

@@ -1,5 +1,5 @@
<template>
<div class="tool-elem">
<div class="tool-page">
<div class="info">
<div class="title">信息</div>

View File

@@ -1,5 +1,5 @@
<template>
<div class="tool-elem">
<div class="tool-page">
<!-- 输入 -->
<div class="input">
@@ -137,7 +137,7 @@ export default {
</script>
<style lang="less" scoped>
.tool-elem {
.tool-page {
@lineHeight: 1.25rem;
padding-bottom: 5rem;

View File

@@ -1,5 +1,5 @@
<template>
<div class="tool-elem">
<div class="tool-page">
<!-- 操作 -->
<div class="ctrl">

View File

@@ -1,251 +1,262 @@
<template>
<el-container class="tools">
<el-container class="tools">
<div class="wrapper">
<div class="wrapper">
<!-- 工具分类 -->
<div v-for="(categoryItem, categoryKey) in toolList" :key="categoryKey" class="category">
<!-- 工具分类 -->
<div
v-for="(categoryItem, categoryKey) in toolList"
:key="categoryKey"
class="category"
>
<!-- 标题 -->
<div class="title">{{ categoryItem.title }}</div>
<!-- 工具项 -->
<div v-for="(toolItem, toolKey) in categoryItem.list" :key="toolKey"
:class="['tool-item', 'shadow-2', { disabled: !toolItem.enabled }]"
@click="detailOpen(categoryKey, toolKey)"
>
<div class="item-title limit-line-1">{{ toolItem.title }}</div>
<div class="item-content limit-line-3">{{ toolItem.desc || '无简介' }}</div>
</div>
</div>
<!-- 标题 -->
<div class="title">{{ categoryItem.title }}</div>
<!-- 工具项 -->
<div
v-for="(toolItem, toolKey) in categoryItem.list"
:key="toolKey"
:class="['tool-item', 'shadow-2', { disabled: !toolItem.enabled }]"
@click="detailOpen(categoryKey, toolKey)"
>
<div class="item-title limit-line-1">{{ toolItem.title }}</div>
<div class="item-content limit-line-3">{{ toolItem.desc || '无简介' }}</div>
</div>
<!-- 弹出 -->
<el-drawer custom-class="drawer-full" direction="btt" size="100%"
:append-to-body="true" :destroy-on-close="true" :title="detail.title"
:visible.sync="detail.show" :before-close="detailClose"
>
</div>
<!-- 标题区域 -->
<div slot="title" class="header">
<span class="title">{{ detail.title }}</span>
<el-tooltip content="在新标签页中打开本工具" placement="left">
<i class="btn el-icon-copy-document" @click="detailOpenNewTab()"></i>
</el-tooltip>
</div>
</div>
<!-- 内容区域 -->
<router-view></router-view>
<!-- 弹出层 -->
<el-drawer
custom-class="drawer-full"
direction="btt"
size="100%"
:append-to-body="true"
:destroy-on-close="true"
:title="detail.title"
:visible.sync="detail.show"
:before-close="detailClose"
>
</el-drawer>
<!-- 标题区域 -->
<div slot="title" class="header">
<span class="title">{{ detail.title }}</span>
<el-tooltip content="在新标签页中打开本工具" placement="left">
<i class="btn el-icon-copy-document" @click="detailOpenNewTab()"></i>
</el-tooltip>
</div>
</el-container>
<!-- 内容区域 -->
<router-view></router-view>
</el-drawer>
</el-container>
</template>
<script>
import navTools from '@/assets/js/navTools.js';
export default {
name: 'Tools',
data() {
return {
utils: this.$root.utils,
toolList: navTools,
detail: {
show: false,
title: ''
},
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
var route = vm.$route;
name: 'Tools',
data() {
return {
utils: this.$root.utils,
toolList: navTools,
detail: {
show: false,
title: ''
},
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
const { name: rName, params: rParams } = vm.$route;
// 判断进入的路由
if (route.name === 'ToolsDetail') {
// 进入:工具内容页面
vm.detailOpen(route.params.category, route.params.name);
} else {
// 进入:工具列表页面
vm.utils.changeTitle('小工具');
}
// 判断进入的路由
if (rName === 'ToolsDetail') {
// [工具内容页面]
vm.detailOpen(rParams.category, rParams.name);
} else {
// [工具列表页面]
vm.utils.changeTitle('小工具');
}
});
},
methods: {
/**
* 关闭工具
*/
detailClose(done) {
this.$confirm('是否关闭?').then(() => {
// 关闭 drawer
done();
// 返回工具页面
this.$router.push({
name: 'Tools'
}).then(() => {
// 更新标题
this.utils.changeTitle('小工具');
});
}).catch(() => { });
},
methods: {
/**
* 关闭工具
*/
detailClose(done) {
this.$confirm('是否关闭?').then(() => {
// 关闭 drawer
done();
// 路由跳转
this.$router.push({
name: 'Tools'
});
// 更新页面标题
this.utils.changeTitle('小工具');
}).catch(() => { });
},
/**
* 打开工具
*
* @param {string} toolCatrgory 工具分类
* @param {string} toolName 工具名称
*/
detailOpen(toolCatrgory, toolName) {
const errMsg = `无法打开该工具(分类:${toolCatrgory} 名称:${toolName}`;
/**
* 打开工具
*
* @param {string} toolCatrgory 工具分类
* @param {string} toolName 工具名称
*/
detailOpen(toolCatrgory, toolName) {
// 当前工具信息
var info = {
title: '',
update: '',
version: '',
};
// 错误提示
var errMsg = `无法打开该工具(分类:${toolCatrgory} 名称:${toolName}`;
try {
try {
var info = this.toolList[toolCatrgory]['list'][toolName];
if (info === undefined) {
throw new Error(errMsg);
}
info = this.toolList[toolCatrgory]['list'][toolName];
} catch (err) {
if (info === undefined) {
throw new Error(errMsg);
}
console.warn('[打开工具]', err);
this.$message({
message: errMsg,
type: 'error'
});
return;
} catch (err) {
}
console.warn('[打开工具]', err);
this.$message({
message: errMsg,
type: 'warning'
});
return;
// 禁用
if (!info.enabled) {
this.$message({
message: '该工具未启用',
type: 'warning'
});
return;
}
}
// 禁用
if (!info.enabled) {
this.$message({
message: '该工具未启用',
type: 'warning'
});
return;
}
// 更新页面标题
this.utils.changeTitle(info.title);
// 更新 drawer 标题
this.detail.title = `${info.title} [${info.version || '未知'}][${info.update || '未知'}]`;
// 路由跳转
// 注:当前路由相同时也进行跳转,以更新 query
this.$router.push({
name: 'ToolsDetail',
params: {
category: toolCatrgory,
name: toolName
}
}).catch((err) => {
console.log('[路由跳转]', err.name);
});
// 显示 drawer
this.detail.show = true;
},
/**
* 打开工具(新标签页)
*/
detailOpenNewTab() {
const url = window.location.href;
window.open(url, '_blank');
},
const {
title: iTitle,
version: iVersion,
update: iUpdate,
} = info;
// 路由跳转
// 注:当前路由相同时也进行跳转
this.$router.push({
name: 'ToolsDetail',
params: {
category: toolCatrgory,
name: toolName
}
}).catch((err) => {
console.log('[打开工具]', err.name);
}).finally(() => {
// 更新标题
this.utils.changeTitle(iTitle);
this.detail.title = `${iTitle} [${iVersion || '未知'}][${iUpdate || '未知'}]`;
// 显示 drawer
this.detail.show = true;
});
},
/**
* 打开工具(新标签页)
*/
detailOpenNewTab() {
const url = window.location.href;
window.open(url, '_blank');
},
},
}
</script>
<style lang="less" scoped>
.tools {
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem;
background-color: @colorWhite;
overflow-y: auto;
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem;
background-color: @colorWhite;
overflow-y: auto;
}
.wrapper {
width: 100%;
.wrapper {
width: 100%;
}
.category {
display: flex;
align-items: flex-start;
flex-wrap: wrap;
justify-content: flex-start;
position: relative;
padding-top: 3rem;
width: 100%;
.title {
position: absolute;
top: 1rem;
left: 0;
font-weight: bold;
color: @textPrimary;
}
.tool-item {
flex-shrink: 0;
margin: 0.5rem;
padding: 1rem;
width: 16rem;
border-left: 0.2rem solid @colorPrimary;
border-radius: 0.25rem;
background-color: #FFF;
font-size: 0;
color: @textPrimary;
overflow: hidden;
transition: all @transitionTime;
cursor: pointer;
&:hover {
border-left-color: @colorSecondary;
transform: translateY(-0.2rem);
}
.category {
display: flex;
align-items: flex-start;
flex-wrap: wrap;
justify-content: flex-start;
position: relative;
padding-top: 3rem;
width: 100%;
.title {
position: absolute;
top: 1rem;
left: 0;
font-weight: bold;
color: @textPrimary;
}
.tool-item {
flex-shrink: 0;
margin: 0.5rem;
padding: 1rem;
width: 16rem;
border-left: 0.2rem solid @colorPrimary;
border-radius: 0.25rem;
background-color: #FFF;
font-size: 0;
color: @textPrimary;
overflow: hidden;
transition: all @transitionTime;
cursor: pointer;
&:hover {
border-left-color: @colorSecondary;
transform: translateY(-0.2rem);
}
&.disabled {
border-left-color: @colorGrey;
}
.item-title {
margin-bottom: 0.5rem;
font-weight: bold;
font-size: 0.9rem;
}
.item-content {
height: calc(1.5em * 2);
line-height: 1.5em;
font-size: 0.75rem;
color: @textSecondary;
}
}
&.disabled {
border-left-color: @colorGrey;
}
.item-title {
margin-bottom: 0.5rem;
font-weight: bold;
font-size: 0.9rem;
}
.item-content {
height: calc(1.5em * 2);
line-height: 1.5em;
font-size: 0.75rem;
color: @textSecondary;
}
}
}
.drawer-full {
.header {
display: flex;
align-items: center;
justify-content: space-between;
.header {
display: flex;
align-items: center;
justify-content: space-between;
.btn {
margin: 0 0.5rem;
font-size: inherit;
cursor: pointer;
}
.btn {
margin: 0 0.5rem;
font-size: inherit;
cursor: pointer;
}
}
}
</style>

View File

@@ -1,90 +1,93 @@
<template>
<div class="tools-detail">
<component :is="toolElem" />
</div>
<div class="tools-detail">
<component :is="toolPage" />
</div>
</template>
<script>
import navTools from '@/assets/js/navTools.js';
export default {
name: 'ToolsDetail',
data() {
return {
utils: this.$root.utils,
toolList: navTools,
toolElem: null,
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
var params = vm.$route.params;
var toolComponent = vm.toolList[params.category]['list'][params.name].component;
var loading = null;
name: 'ToolsDetail',
data() {
return {
utils: this.$root.utils,
toolList: navTools,
toolPage: null,
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
const { params, query } = vm.$route;
const { category: cCategory, name: cName } = params;
const componentName = vm.toolList[cCategory]['list'][cName].component;
console.log('[打开工具] params', params);
var loading = null;
// 异步,防止找不到 target
setTimeout(() => {
// 开启 Loading
loading = vm.$loading({
background: '#FFF',
lock: true,
// Loading 需要覆盖的 DOM 节点
target: '.drawer-full .el-drawer__body'
});
}, 0);
console.log('[打开工具]', { params, query });
vm.toolElem = (() => {
// 动态引入组件
var elem = import(`@/components/tools/${toolComponent}.vue`);
Promise.all([elem]).then(() => {
setTimeout(() => {
// 关闭 Loading
loading.close();
}, 200);
});
return elem;
});
// 异步,防止找不到 target
setTimeout(() => {
// 开启 Loading
loading = vm.$loading({
background: '#FFF',
lock: true,
// Loading 需要覆盖的 DOM 节点
target: '.drawer-full .el-drawer__body'
});
},
}, 0);
vm.toolPage = (() => {
// 动态引入组件
const component = import(`@/components/tools/${componentName}.vue`);
Promise.all([component]).then(() => {
setTimeout(() => {
// 关闭 Loading
loading.close();
}, 200);
});
return component;
});
});
},
}
</script>
<style lang="less" scoped>
.tools-detail {
display: flex;
align-items: flex-start;
justify-content: center;
display: flex;
align-items: flex-start;
justify-content: center;
}
/deep/ .tool-elem {
width: 100%;
max-width: 60rem;
/deep/ .tool-page {
width: 100%;
max-width: 60rem;
> div {
> .title {
position: relative;
margin: 1.5rem 0;
font-size: 1rem;
color: @textPrimary;
}
> .title::before {
content: "";
position: absolute;
top: 0;
left: -0.5rem;
width: 0.2rem;
height: 100%;
background-color: @colorPrimary;
}
> .content {
font-size: 0.9rem;
}
}
> div {
> .title {
position: relative;
margin: 1.5rem 0;
font-size: 1rem;
color: @textPrimary;
}
> .title::before {
content: "";
position: absolute;
top: 0;
left: -0.5rem;
width: 0.2rem;
height: 100%;
background-color: @colorPrimary;
}
> .content {
line-height: 1.6em;
font-size: 0.9rem;
}
}
}
</style>