添加工具:比例计算、生成批量下载链接、Unix 时间戳转换
This commit is contained in:
@@ -11,7 +11,7 @@ let navTools = {
|
|||||||
// 工具标题
|
// 工具标题
|
||||||
title: '计算下载用时',
|
title: '计算下载用时',
|
||||||
// 工具简介
|
// 工具简介
|
||||||
desc: '根据设定的文件大小和下载速度简单计算大约下载完成所需的时间',
|
desc: '根据设定的文件大小和下载速度简单计算大约下载完成所需的时间。',
|
||||||
// 组件名称
|
// 组件名称
|
||||||
component: 'CalcDownloadTime',
|
component: 'CalcDownloadTime',
|
||||||
// 更新时间
|
// 更新时间
|
||||||
@@ -20,8 +20,12 @@ let navTools = {
|
|||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
'ratio': {
|
'ratio': {
|
||||||
title: '计算比例',
|
title: '比例计算',
|
||||||
component: 'CalcRatio'
|
desc: '按设定的比例计算给出的数值所对应的数值。',
|
||||||
|
component: 'CalcRatio',
|
||||||
|
update: '2021-11-14',
|
||||||
|
version: '1',
|
||||||
|
enabled: true
|
||||||
},
|
},
|
||||||
'simple': {
|
'simple': {
|
||||||
title: '简易计算器',
|
title: '简易计算器',
|
||||||
@@ -35,13 +39,15 @@ let navTools = {
|
|||||||
list: {
|
list: {
|
||||||
'links': {
|
'links': {
|
||||||
title: '生成批量下载链接',
|
title: '生成批量下载链接',
|
||||||
desc: '根据设置,生成有一定规律的用于批量下载的链接',
|
desc: '根据设置,生成有一定规律的用于批量下载的链接。',
|
||||||
component: 'GenLinks',
|
component: 'GenLinks',
|
||||||
enabled: false
|
update: '2021-11-14',
|
||||||
|
version: '1',
|
||||||
|
enabled: true
|
||||||
},
|
},
|
||||||
'random-str': {
|
'random-str': {
|
||||||
title: '生成随机字符串',
|
title: '生成随机字符串',
|
||||||
desc: '生成随机组合的字符串,可用于密码',
|
desc: '生成随机组合的字符串,可用于密码。',
|
||||||
component: 'GenRandomStr',
|
component: 'GenRandomStr',
|
||||||
update: '2021-05-04',
|
update: '2021-05-04',
|
||||||
version: '1',
|
version: '1',
|
||||||
@@ -68,9 +74,11 @@ let navTools = {
|
|||||||
},
|
},
|
||||||
'timestamp': {
|
'timestamp': {
|
||||||
title: 'Unix 时间戳转换',
|
title: 'Unix 时间戳转换',
|
||||||
desc: 'Unix 时间戳转时间 / 时间转 Unix 时间戳',
|
desc: '时间戳转时间 / 时间转时间戳',
|
||||||
component: 'ConvertTimestamp',
|
component: 'ConvertTimestamp',
|
||||||
enabled: false
|
update: '2021-11-14',
|
||||||
|
version: '1',
|
||||||
|
enabled: true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -84,13 +92,13 @@ let navTools = {
|
|||||||
},
|
},
|
||||||
'dynmap-renderdata-gen': {
|
'dynmap-renderdata-gen': {
|
||||||
title: 'Dynmap renderdata 生成',
|
title: 'Dynmap renderdata 生成',
|
||||||
desc: '生成用于 Minecraft Dynmap 插件 / 模组的 renderdata 数据',
|
desc: '生成用于 Minecraft Dynmap 插件 / 模组的 renderdata 数据。',
|
||||||
component: 'MinecraftDynmapRenderdataGen',
|
component: 'MinecraftDynmapRenderdataGen',
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
'uuidConverter': {
|
'uuidConverter': {
|
||||||
title: 'UUID 转换',
|
title: 'UUID 转换',
|
||||||
desc: 'UUID 与 UUID Least、UUID Most 相互转换',
|
desc: 'UUID 与 UUID Least、UUID Most 相互转换。',
|
||||||
component: 'MinecraftUUIDConverter',
|
component: 'MinecraftUUIDConverter',
|
||||||
enabled: false
|
enabled: false
|
||||||
},
|
},
|
||||||
|
135
src/components/tools/CalcRatio.vue
Normal file
135
src/components/tools/CalcRatio.vue
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-page">
|
||||||
|
|
||||||
|
<div class="calc-mode">
|
||||||
|
<div class="title">计算模式</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-select v-model="mode" size="small">
|
||||||
|
<el-option label="1 -> 2" value="1-to-2"></el-option>
|
||||||
|
<el-option label="2 -> 1" value="2-to-1"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="digits">
|
||||||
|
<div class="title">小数位数</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-input-number
|
||||||
|
v-model="digits"
|
||||||
|
controls-position="right"
|
||||||
|
size="small"
|
||||||
|
:min="0"
|
||||||
|
:max="10"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
@change="update()"
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ratio-base">
|
||||||
|
<div class="title">基础比例</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-input-number
|
||||||
|
v-model="base.a"
|
||||||
|
controls-position="right"
|
||||||
|
size="small"
|
||||||
|
:step="1"
|
||||||
|
@change="update()"
|
||||||
|
></el-input-number>
|
||||||
|
<span class="split">:</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="base.b"
|
||||||
|
controls-position="right"
|
||||||
|
size="small"
|
||||||
|
:step="1"
|
||||||
|
@change="update()"
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ratio-calc">
|
||||||
|
<div class="title">计算比例</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-input-number
|
||||||
|
v-model="calc.a"
|
||||||
|
controls-position="right"
|
||||||
|
size="small"
|
||||||
|
:step="1"
|
||||||
|
:disabled="mode === '2-to-1'"
|
||||||
|
@change="update()"
|
||||||
|
></el-input-number>
|
||||||
|
<span class="split">:</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="calc.b"
|
||||||
|
controls-position="right"
|
||||||
|
size="small"
|
||||||
|
:step="1"
|
||||||
|
:disabled="mode === '1-to-2'"
|
||||||
|
@change="update()"
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { divide, multiply, round } from 'mathjs';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CalcRatio',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 基础比例
|
||||||
|
base: {
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
},
|
||||||
|
// 计算比例
|
||||||
|
calc: {
|
||||||
|
a: 1,
|
||||||
|
b: 1,
|
||||||
|
},
|
||||||
|
// 小数位数
|
||||||
|
digits: 5,
|
||||||
|
// 模式
|
||||||
|
mode: '1-to-2',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
const base = this.base;
|
||||||
|
const calc = this.calc;
|
||||||
|
const digits = this.digits;
|
||||||
|
const mode = this.mode;
|
||||||
|
const ratio = base.a / base.b;
|
||||||
|
|
||||||
|
if (mode === '1-to-2') {
|
||||||
|
calc.b = round(divide(calc.a, ratio), digits);
|
||||||
|
} else if (mode === '2-to-1') {
|
||||||
|
calc.a = round(multiply(calc.b, ratio), digits);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.el-input-number,
|
||||||
|
.el-select {
|
||||||
|
width: 10rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split {
|
||||||
|
display: inline-block;
|
||||||
|
width: 2em;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
323
src/components/tools/ConvertTimestamp.vue
Normal file
323
src/components/tools/ConvertTimestamp.vue
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-page">
|
||||||
|
|
||||||
|
<div class="ctrl">
|
||||||
|
<div class="title">控制</div>
|
||||||
|
<div class="content">
|
||||||
|
<!-- 转换模式 -->
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">转换模式</span>
|
||||||
|
<el-select v-model="mode" size="medium">
|
||||||
|
<el-option
|
||||||
|
v-for="item in modes"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.name"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<!-- 时间戳类型 -->
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">时间戳类型</span>
|
||||||
|
<el-select v-model="tsType" size="medium">
|
||||||
|
<el-option
|
||||||
|
v-for="item in tsTypes"
|
||||||
|
:key="item.name"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.name"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<!-- 操作 -->
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">操作</span>
|
||||||
|
<el-button
|
||||||
|
:type="update ? 'success' : 'warning'"
|
||||||
|
size="small"
|
||||||
|
plain
|
||||||
|
@click="toggleUpdate()"
|
||||||
|
>状态:{{ update ? '自动更新' : '暂停更新' }}</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
plain
|
||||||
|
@click="convert()"
|
||||||
|
>转换</el-button>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
size="small"
|
||||||
|
plain
|
||||||
|
@click="clear()"
|
||||||
|
>清空</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="current">
|
||||||
|
<div class="title">当前</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">时间</span>
|
||||||
|
<el-input
|
||||||
|
v-model="current.t"
|
||||||
|
size="medium"
|
||||||
|
readonly
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="label">时间戳</span>
|
||||||
|
<el-input
|
||||||
|
v-model="current.ts"
|
||||||
|
size="medium"
|
||||||
|
readonly
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="inputs">
|
||||||
|
<div class="title">输入</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="notice">
|
||||||
|
<p>注意:</p>
|
||||||
|
<p>在“本地时间 -> 时间戳”的模式中,若省略“时间”,将会加上本地时区与零时区的时差后计算;</p>
|
||||||
|
<p>例如北京时间(UTC+8)按 08:00 计算,东京时间(UTC+9)按 09:00 计算。</p>
|
||||||
|
</div>
|
||||||
|
<el-input
|
||||||
|
v-model="textInputs"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
size="medium"
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="outputs">
|
||||||
|
<div class="title">结果</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-input
|
||||||
|
v-model="textOutputs"
|
||||||
|
size="medium"
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ConvertTimestamp',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 转换模式
|
||||||
|
mode: 't-to-ts',
|
||||||
|
modes: [
|
||||||
|
{ name: 't-to-ts', label: '本地时间 -> 时间戳' },
|
||||||
|
{ name: 'ts-to-t', label: '时间戳 -> 本地时间' },
|
||||||
|
],
|
||||||
|
// 定时器
|
||||||
|
timer: null,
|
||||||
|
// 是否更新当前时间
|
||||||
|
update: true,
|
||||||
|
// 时间戳类型
|
||||||
|
tsType: 'ms',
|
||||||
|
tsTypes: [
|
||||||
|
{ name: 'ms', label: '毫秒' },
|
||||||
|
{ name: 's', label: '秒' },
|
||||||
|
],
|
||||||
|
// 当前时间
|
||||||
|
current: {
|
||||||
|
t: '',
|
||||||
|
ts: '',
|
||||||
|
},
|
||||||
|
// 输入
|
||||||
|
textInputs: '',
|
||||||
|
// 输出
|
||||||
|
textOutputs: '',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
// 输入占位文本
|
||||||
|
placeholder() {
|
||||||
|
const mode = this.mode;
|
||||||
|
const type = this.tsType;
|
||||||
|
|
||||||
|
if (mode === 't-to-ts') {
|
||||||
|
return '参考格式:年-月-日 时:分:秒';
|
||||||
|
} else if (mode === 'ts-to-t') {
|
||||||
|
if (type === 's') {
|
||||||
|
return '参考范例:1577808000';
|
||||||
|
} else if (type === 'ms') {
|
||||||
|
return '参考范例:1577808000000';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
created () {
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
beforeDestroy () {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
if (this.update) {
|
||||||
|
this.current.t = this.tsToTime();
|
||||||
|
this.current.ts = this.timeToTs();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空
|
||||||
|
*/
|
||||||
|
clear() {
|
||||||
|
this.textInputs = '';
|
||||||
|
this.textOutputs = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换
|
||||||
|
*/
|
||||||
|
convert() {
|
||||||
|
const mode = this.mode;
|
||||||
|
|
||||||
|
if (mode === 't-to-ts') {
|
||||||
|
this.textOutputs = this.timeToTs(this.textInputs);
|
||||||
|
} else if (mode === 'ts-to-t') {
|
||||||
|
this.textOutputs = this.tsToTime(this.textInputs);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间 -> 时间戳
|
||||||
|
*
|
||||||
|
* @param {string} [timeStr] 时间字符串(年-月-日 时:分:秒)
|
||||||
|
* @returns {string} 转换结果
|
||||||
|
*/
|
||||||
|
timeToTs(timeStr) {
|
||||||
|
const date = (timeStr ? new Date(timeStr) : new Date());
|
||||||
|
|
||||||
|
if (date.toString() === 'Invalid Date') {
|
||||||
|
return '格式错误';
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = date.getTime();
|
||||||
|
|
||||||
|
if (this.tsType === 'ms') {
|
||||||
|
// 毫秒
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// 秒
|
||||||
|
return (result / 1000).toFixed(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间戳 -> 时间
|
||||||
|
*
|
||||||
|
* @param {(number|string)} [ts] 时间戳
|
||||||
|
* @returns {string} 转换结果(年-月-日 时:分:秒)
|
||||||
|
*/
|
||||||
|
tsToTime(ts = null) {
|
||||||
|
if (ts === '') {
|
||||||
|
ts = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否有参数
|
||||||
|
const tsParam = (ts !== null);
|
||||||
|
|
||||||
|
// 时间戳是秒
|
||||||
|
if (tsParam && this.tsType === 's') {
|
||||||
|
ts += '000';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转为数值
|
||||||
|
const timestamp = parseInt(ts);
|
||||||
|
|
||||||
|
if (tsParam && isNaN(timestamp)) {
|
||||||
|
return '格式错误';
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = (tsParam ? new Date(timestamp) : new Date());
|
||||||
|
const t = {
|
||||||
|
y: date.getFullYear(),
|
||||||
|
m: date.getMonth() + 1,
|
||||||
|
d: date.getDate(),
|
||||||
|
h: date.getHours(),
|
||||||
|
i: date.getMinutes(),
|
||||||
|
s: date.getSeconds(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 补零
|
||||||
|
for (let key in t) {
|
||||||
|
(t[key] < 10) && (t[key] = ('0' + t[key]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${t.y}-${t.m}-${t.d} ${t.h}:${t.i}:${t.s}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换自动更新
|
||||||
|
*/
|
||||||
|
toggleUpdate() {
|
||||||
|
this.update = !this.update;
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.ctrl, .current {
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
margin: 0.5rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ctrl {
|
||||||
|
.el-select {
|
||||||
|
width: 12em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.current {
|
||||||
|
.el-input {
|
||||||
|
width: 20em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
width: 3.5em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs, .outputs {
|
||||||
|
.el-input {
|
||||||
|
max-width: 25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
449
src/components/tools/GenLinks.vue
Normal file
449
src/components/tools/GenLinks.vue
Normal file
@@ -0,0 +1,449 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tool-page">
|
||||||
|
|
||||||
|
<div class="link-base">
|
||||||
|
<div class="title">链接模板</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-input
|
||||||
|
v-model="linkBase"
|
||||||
|
size="medium"
|
||||||
|
placeholder="使用 {n} 表示变量"
|
||||||
|
clearable
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="config">
|
||||||
|
<div class="title">参数配置</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-radio-group v-model="mode">
|
||||||
|
|
||||||
|
<!-- 等差数列 -->
|
||||||
|
<div class="mode-item mode-as">
|
||||||
|
|
||||||
|
<div class="config-row">
|
||||||
|
<el-radio label="as">等差数列</el-radio>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="config-row">
|
||||||
|
<div class="config-item">
|
||||||
|
<span class="label">首项</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="modes.as.first"
|
||||||
|
controls-position="right"
|
||||||
|
size="medium"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
<div class="config-item">
|
||||||
|
<span class="label">公差</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="modes.as.diff"
|
||||||
|
controls-position="right"
|
||||||
|
size="medium"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
<div class="config-item">
|
||||||
|
<span class="label">项数</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="modes.as.count"
|
||||||
|
controls-position="right"
|
||||||
|
size="medium"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="config-row">
|
||||||
|
<div class="config-item">
|
||||||
|
<span class="label">格式</span>
|
||||||
|
<el-checkbox
|
||||||
|
v-model="modes.as.zero"
|
||||||
|
>补零</el-checkbox>
|
||||||
|
<el-checkbox
|
||||||
|
v-model="modes.as.reverse"
|
||||||
|
>倒序</el-checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- 等差数列 -->
|
||||||
|
|
||||||
|
<!-- 等比数列 -->
|
||||||
|
<div class="mode-item mode-ps">
|
||||||
|
|
||||||
|
<div class="config-row">
|
||||||
|
<el-radio label="ps">等比数列</el-radio>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="config-row">
|
||||||
|
<div class="config-item">
|
||||||
|
<span class="label">首项</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="modes.ps.first"
|
||||||
|
controls-position="right"
|
||||||
|
size="medium"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
<div class="config-item">
|
||||||
|
<span class="label">公比</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="modes.ps.diff"
|
||||||
|
controls-position="right"
|
||||||
|
size="medium"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
<div class="config-item">
|
||||||
|
<span class="label">项数</span>
|
||||||
|
<el-input-number
|
||||||
|
v-model="modes.ps.count"
|
||||||
|
controls-position="right"
|
||||||
|
size="medium"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
></el-input-number>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="config-row">
|
||||||
|
<div class="config-item">
|
||||||
|
<span class="label">格式</span>
|
||||||
|
<el-checkbox
|
||||||
|
v-model="modes.ps.zero"
|
||||||
|
>补零</el-checkbox>
|
||||||
|
<el-checkbox
|
||||||
|
v-model="modes.ps.reverse"
|
||||||
|
>倒序</el-checkbox>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- 等比数列 -->
|
||||||
|
|
||||||
|
<!-- 字母变化 -->
|
||||||
|
<div class="mode-item mode-lc">
|
||||||
|
|
||||||
|
<div class="config-row">
|
||||||
|
<el-radio label="lc">字母变化</el-radio>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="config-row">
|
||||||
|
<span class="label">从</span>
|
||||||
|
<el-input
|
||||||
|
v-model="modes.lc.start"
|
||||||
|
size="medium"
|
||||||
|
:maxlength="1"
|
||||||
|
></el-input>
|
||||||
|
<span class="label">到</span>
|
||||||
|
<el-input
|
||||||
|
v-model="modes.lc.end"
|
||||||
|
size="medium"
|
||||||
|
:maxlength="1"
|
||||||
|
></el-input>
|
||||||
|
<el-checkbox
|
||||||
|
v-model="modes.lc.reverse"
|
||||||
|
>倒序</el-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- 字母变化 -->
|
||||||
|
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action">
|
||||||
|
<div class="title">操作</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
plain
|
||||||
|
@click="generate()"
|
||||||
|
>生成链接</el-button>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
size="small"
|
||||||
|
plain
|
||||||
|
@click="clear()"
|
||||||
|
>清空结果</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="link-result">
|
||||||
|
<div class="title">生成结果</div>
|
||||||
|
<div class="content">
|
||||||
|
<el-input
|
||||||
|
v-model="linkResult"
|
||||||
|
type="textarea"
|
||||||
|
:rows="10"
|
||||||
|
></el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'GenLinks',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 链接模板
|
||||||
|
linkBase: '',
|
||||||
|
// 生成结果
|
||||||
|
linkResult: '',
|
||||||
|
// 正则,匹配链接变量
|
||||||
|
linkReg: /\{n\}/g,
|
||||||
|
// 当前模式
|
||||||
|
mode: 'as',
|
||||||
|
modes: {
|
||||||
|
// 等差数列(Arithmetic Sequence)
|
||||||
|
as: {
|
||||||
|
first: 0,
|
||||||
|
diff: 1,
|
||||||
|
count: 10,
|
||||||
|
zero: false,
|
||||||
|
reverse: false,
|
||||||
|
},
|
||||||
|
// 等比数列(Proportional Sequence)
|
||||||
|
ps: {
|
||||||
|
first: 1,
|
||||||
|
diff: 2,
|
||||||
|
count: 10,
|
||||||
|
zero: false,
|
||||||
|
reverse: false,
|
||||||
|
},
|
||||||
|
// 字母变化(Letter Change)
|
||||||
|
lc: {
|
||||||
|
start: 'a',
|
||||||
|
end: 'z',
|
||||||
|
reverse: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空
|
||||||
|
*/
|
||||||
|
clear() {
|
||||||
|
this.linkResult = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成
|
||||||
|
*/
|
||||||
|
generate() {
|
||||||
|
const mode = this.mode;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case 'as':
|
||||||
|
this.linkResult = this.generateSeq('as');
|
||||||
|
break;
|
||||||
|
case 'ps':
|
||||||
|
this.linkResult = this.generateSeq('ps');
|
||||||
|
break;
|
||||||
|
case 'lc':
|
||||||
|
this.linkResult = this.generateLetter();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成数列
|
||||||
|
*
|
||||||
|
* @param {string} typs 类型(as - 等差数列,ps - 等比数列)
|
||||||
|
* @returns {string} 生成结果
|
||||||
|
*/
|
||||||
|
generateSeq(type) {
|
||||||
|
const linkBase = this.linkBase;
|
||||||
|
const linkReg = this.linkReg;
|
||||||
|
|
||||||
|
if (!linkBase) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = this.modes[type];
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const nFirst = data.first
|
||||||
|
const nCount = data.count;
|
||||||
|
const nDiff = data.diff;
|
||||||
|
|
||||||
|
const nResult = {
|
||||||
|
digits: 0, // 最大位数
|
||||||
|
numbers: [], // 生成的数值
|
||||||
|
};
|
||||||
|
|
||||||
|
const links = [];
|
||||||
|
|
||||||
|
// 等差数列公式
|
||||||
|
const expAS = (i) => {
|
||||||
|
return (nFirst + (i - 1) * nDiff);
|
||||||
|
};
|
||||||
|
// 等比数列公式
|
||||||
|
const expPS = (i) => {
|
||||||
|
return (nFirst * Math.pow(nDiff, (i - 1)));
|
||||||
|
};
|
||||||
|
// 实际使用的公式
|
||||||
|
const exp = (type === 'as' ? expAS : expPS);
|
||||||
|
|
||||||
|
// 生成数值
|
||||||
|
for (let i = 1; i <= nCount; i++) {
|
||||||
|
// 等差数列 / 等比数列
|
||||||
|
const n = exp(i);
|
||||||
|
const digits = Math.abs(n).toString().length;
|
||||||
|
|
||||||
|
(digits > nResult.digits) && (nResult.digits = digits);
|
||||||
|
nResult.numbers.push(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 补零
|
||||||
|
if (data.zero) {
|
||||||
|
const digits = nResult.digits;
|
||||||
|
const base = Math.pow(10, digits);
|
||||||
|
const numbers = nResult.numbers;
|
||||||
|
|
||||||
|
for (let i = 0; i < numbers.length; i++) {
|
||||||
|
const n = numbers[i];
|
||||||
|
|
||||||
|
if (n >= 0) {
|
||||||
|
numbers[i] = (n / base).toFixed(digits).substr(2);
|
||||||
|
} else {
|
||||||
|
numbers[i] = '-' + (n / base).toFixed(digits).substr(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 倒序
|
||||||
|
if (data.reverse) {
|
||||||
|
nResult.numbers.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成链接
|
||||||
|
nResult.numbers.forEach((n) => {
|
||||||
|
links.push(linkBase.replace(linkReg, n));
|
||||||
|
});
|
||||||
|
|
||||||
|
return links.join('\n');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成字母
|
||||||
|
*/
|
||||||
|
generateLetter() {
|
||||||
|
const linkBase = this.linkBase;
|
||||||
|
const linkReg = this.linkReg;
|
||||||
|
|
||||||
|
if (!linkBase) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = this.modes.lc;
|
||||||
|
|
||||||
|
// 编码数值
|
||||||
|
const cStart = data.start.charCodeAt(0);
|
||||||
|
const cEnd = data.end.charCodeAt(0);
|
||||||
|
|
||||||
|
const chars = [];
|
||||||
|
const links = [];
|
||||||
|
|
||||||
|
// 生成字母
|
||||||
|
if (cStart >= 65 && cStart <= 122 && cEnd >= 65 && cEnd <= 122) {
|
||||||
|
if (cStart < cEnd) {
|
||||||
|
for (let i = cStart; i <= cEnd; i++) {
|
||||||
|
// 跳过符号 [ \ ] ^ _ `
|
||||||
|
if (i >= 91 && i <= 96) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
chars.push(String.fromCharCode(i));
|
||||||
|
}
|
||||||
|
} else if (cStart > cEnd) {
|
||||||
|
return '字母先后顺序有误。注意:大写字母需要在前。';
|
||||||
|
} else if (cStart === cEnd) {
|
||||||
|
return '仅有 1 条链接,无需生成。';
|
||||||
|
} else {
|
||||||
|
return '未知错误。';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return '输入有误,请检查。';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 倒序
|
||||||
|
if (data.reverse) {
|
||||||
|
chars.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成链接
|
||||||
|
chars.forEach((c) => {
|
||||||
|
links.push(linkBase.replace(linkReg, c));
|
||||||
|
});
|
||||||
|
|
||||||
|
return links.join('\n');
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.config {
|
||||||
|
.el-input-number {
|
||||||
|
width: 8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-item {
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-bottom: 0.0625rem solid #EEE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-item {
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 1em;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-lc {
|
||||||
|
/deep/ .el-checkbox {
|
||||||
|
margin: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-input {
|
||||||
|
width: 3.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-input__inner {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Reference in New Issue
Block a user