Compare commits
10 Commits
bb7863d578
...
1146f3b180
Author | SHA1 | Date | |
---|---|---|---|
1146f3b180 | |||
5131b9396b | |||
a8f0a86e07 | |||
3ed03f0496 | |||
05c1b0d29b | |||
2f54cf304a | |||
109357e8e2 | |||
8563930e68 | |||
8d07d60566 | |||
4cdce770d8 |
5
.gitignore
vendored
5
.gitignore
vendored
@ -23,5 +23,6 @@ pnpm-debug.log*
|
||||
# jetbrains setting folder
|
||||
.idea/
|
||||
|
||||
# test articles
|
||||
src/content/
|
||||
# ignore test articles except for article definitions
|
||||
src/content/*
|
||||
!src/content/config.ts
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import sitemap from "@astrojs/sitemap";
|
||||
import vue from "@astrojs/vue";
|
||||
import remarkToc from 'remark-toc';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
markdown: {
|
||||
smartypants: false,
|
||||
syntaxHighlight: 'shiki',
|
||||
shikiConfig: {
|
||||
// Choose from Shiki's built-in themes (or add your own)
|
||||
@ -25,7 +27,10 @@ export default defineConfig({
|
||||
// Add custom transformers: https://shiki.style/guide/transformers
|
||||
// Find common transformers: https://shiki.style/packages/transformers
|
||||
transformers: []
|
||||
}
|
||||
},
|
||||
remarkPlugins: [
|
||||
[remarkToc, { heading: "(table[ -]of[ -])?contents?|toc|目录" }]
|
||||
],
|
||||
},
|
||||
site: 'https://lishouzhong.com',
|
||||
integrations: [
|
||||
|
37
package-lock.json
generated
37
package-lock.json
generated
@ -14,6 +14,7 @@
|
||||
"astro": "^4.9.2",
|
||||
"bignumber.js": "^9.1.2",
|
||||
"pinyin-pro": "^3.22.0",
|
||||
"remark-toc": "^9.0.0",
|
||||
"typescript": "^5.4.5",
|
||||
"vue": "^3.4.29"
|
||||
}
|
||||
@ -1903,6 +1904,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ungap__structured-clone": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/@types/ungap__structured-clone/-/ungap__structured-clone-1.2.0.tgz",
|
||||
"integrity": "sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA=="
|
||||
},
|
||||
"node_modules/@types/unist": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.2.tgz",
|
||||
@ -4357,6 +4363,24 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-toc": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/mdast-util-toc/-/mdast-util-toc-7.1.0.tgz",
|
||||
"integrity": "sha512-2TVKotOQzqdY7THOdn2gGzS9d1Sdd66bvxUyw3aNpWfcPXCLYSJCCgfPy30sEtuzkDraJgqF35dzgmz6xlvH/w==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"@types/ungap__structured-clone": "^1.0.0",
|
||||
"@ungap/structured-clone": "^1.0.0",
|
||||
"github-slugger": "^2.0.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"unist-util-is": "^6.0.0",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
@ -5575,6 +5599,19 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/remark-toc": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/remark-toc/-/remark-toc-9.0.0.tgz",
|
||||
"integrity": "sha512-KJ9txbo33GjDAV1baHFze7ij4G8c7SGYoY8Kzsm2gzFpbhL/bSoVpMMzGa3vrNDSWASNd/3ppAqL7cP2zD6JIA==",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-toc": "^7.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/request-light": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmmirror.com/request-light/-/request-light-0.7.0.tgz",
|
||||
|
@ -16,6 +16,7 @@
|
||||
"astro": "^4.9.2",
|
||||
"bignumber.js": "^9.1.2",
|
||||
"pinyin-pro": "^3.22.0",
|
||||
"remark-toc": "^9.0.0",
|
||||
"typescript": "^5.4.5",
|
||||
"vue": "^3.4.29"
|
||||
}
|
||||
|
@ -9,7 +9,9 @@ original_article_home="/home/ld/Documents/ld_article"
|
||||
original_article_destination="/opt/ld-site/src/content"
|
||||
ld_site_dist_target="/opt/nginx_targets/ld_site_dist"
|
||||
|
||||
rsync -a "${original_article_home}/" "${original_article_destination}/"
|
||||
rsync -a --delete-after -f"P config.ts" \
|
||||
"${original_article_home}/" \
|
||||
"${original_article_destination}/"
|
||||
|
||||
cd "${script_path}/../"
|
||||
npm run build
|
||||
@ -21,4 +23,4 @@ fi
|
||||
|
||||
mv ${ld_site_dist_target} "${ld_site_dist_target}-old"
|
||||
mv dist ${ld_site_dist_target}
|
||||
rm -rf "${ld_site_dist_target}-old" ${original_article_destination}
|
||||
rm -rf "${ld_site_dist_target}-old"
|
||||
|
37
src/components/article/article_body/ArticleBody.astro
Normal file
37
src/components/article/article_body/ArticleBody.astro
Normal file
@ -0,0 +1,37 @@
|
||||
---
|
||||
// get rendered ArticleBodyContent HTML
|
||||
const html = await Astro.slots.render("default");
|
||||
|
||||
// If some lines are not started with ASCII character,
|
||||
// join them to their previous line.
|
||||
// This is important.
|
||||
// Because I add one newline character to wrap Chinese.
|
||||
const arr = html.split("\n");
|
||||
let articleHTMLFinal = arr[0];
|
||||
// Whether the current line belongs to the area where
|
||||
// the line break should be kept.
|
||||
let remainIntactArea = false;
|
||||
for (let i = 1; i < arr.length; i++) {
|
||||
if (arr[i].match(/^(<pre|<code|<blockquote|<table)/) !== null) {
|
||||
remainIntactArea = true;
|
||||
} else {
|
||||
remainIntactArea = false;
|
||||
}
|
||||
if (
|
||||
// If the first character is not ascii character,
|
||||
// or the final character of previous line is not character.
|
||||
// AND
|
||||
// Current line should not belong to area that remains intact.
|
||||
(arr[i].charAt(0).match(/[ -~]/) === null ||
|
||||
arr[i - 1].charAt(arr[i - 1].length - 1).match(/[ -~]/) === null) &&
|
||||
!remainIntactArea
|
||||
) {
|
||||
articleHTMLFinal += arr[i];
|
||||
} else {
|
||||
articleHTMLFinal += "\n";
|
||||
articleHTMLFinal += arr[i];
|
||||
}
|
||||
}
|
||||
---
|
||||
|
||||
<Fragment set:html={articleHTMLFinal} />
|
@ -45,10 +45,14 @@ const articlePrettyName = article!.id.split("/").pop()!.replace(".md", "");
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
/* reduce indent of TOC list */
|
||||
:global(.article-title + ul) {
|
||||
:global(.article-title ~ ul:nth-of-type(1)) {
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0 0 0 20px;
|
||||
}
|
||||
/* hide TOC headint */
|
||||
:global(.article-title ~ h2:nth-of-type(1)) {
|
||||
display: none;
|
||||
}
|
||||
/* font for all code */
|
||||
:global(.article code) {
|
||||
font-family: "Consolas", "Tahoma", sans-serif;
|
18
src/components/article/article_body/ArticleBodyWrapper.astro
Normal file
18
src/components/article/article_body/ArticleBodyWrapper.astro
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
import type { CollectionKey } from "astro:content";
|
||||
import ArticleBody from "./ArticleBody.astro";
|
||||
import ArticleBodyContent from "./ArticleBodyContent.astro";
|
||||
|
||||
interface Props {
|
||||
articleSlug: string;
|
||||
collectionName: CollectionKey;
|
||||
}
|
||||
const { articleSlug, collectionName } = Astro.props;
|
||||
---
|
||||
|
||||
<ArticleBody>
|
||||
<ArticleBodyContent
|
||||
collectionName={collectionName}
|
||||
articleSlug={articleSlug}
|
||||
/>
|
||||
</ArticleBody>
|
@ -1,53 +1,86 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
const unitToByte: { [name: string]: number } = {
|
||||
"unit-k-byte": 1000,
|
||||
"unit-m-byte": 1000 * 1000,
|
||||
"unit-g-byte": 1000 * 1000 * 1000,
|
||||
"unit-t-byte": 1000 * 1000 * 1000 * 1000,
|
||||
"unit-ki-byte": 1024,
|
||||
"unit-mi-byte": 1024 * 1024,
|
||||
"unit-gi-byte": 1024 * 1024 * 1024,
|
||||
"unit-ti-byte": 1024 * 1024 * 1024 * 1024,
|
||||
"unit-byte": 1,
|
||||
"unit-bit": 1 / 8,
|
||||
"unit-k-bit": 1000 / 8,
|
||||
"unit-m-bit": 1000000 / 8,
|
||||
"unit-g-bit": 1000000000 / 8,
|
||||
"unit-t-bit": 1000000000000 / 8,
|
||||
}
|
||||
/**
|
||||
* @typedef {string} UnitNameStr
|
||||
*/
|
||||
|
||||
let variable: { [name: keyof typeof unitToByte]: string } = {
|
||||
"unit-k-byte": '',
|
||||
"unit-m-byte": '',
|
||||
"unit-g-byte": '',
|
||||
"unit-t-byte": '',
|
||||
"unit-ki-byte": '',
|
||||
"unit-mi-byte": '',
|
||||
"unit-gi-byte": '',
|
||||
"unit-ti-byte": '',
|
||||
"unit-byte": '',
|
||||
"unit-bit": '',
|
||||
"unit-k-bit": '',
|
||||
"unit-m-bit": '',
|
||||
"unit-g-bit": '',
|
||||
"unit-t-bit": '',
|
||||
}
|
||||
/**
|
||||
* @enum {UnitNameStr}
|
||||
*/
|
||||
const UnitName = Object.freeze({
|
||||
KBYTE: "unit-k-byte",
|
||||
MBYTE: "unit-m-byte",
|
||||
GBYTE: "unit-g-byte",
|
||||
TBYTE: "unit-t-byte",
|
||||
KIBYTE: "unit-ki-byte",
|
||||
MIBYTE: "unit-mi-byte",
|
||||
GIBYTE: "unit-gi-byte",
|
||||
TIBYTE: "unit-ti-byte",
|
||||
BYTE: "unit-byte",
|
||||
BIT: "unit-bit",
|
||||
KBIT: "unit-k-bit",
|
||||
MBIT: "unit-m-bit",
|
||||
GBIT: "unit-g-bit",
|
||||
TBIT: "unit-t-bit",
|
||||
})
|
||||
|
||||
const size = ref(variable);
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
const UnitNameToSize = Object.freeze({
|
||||
[UnitName.KBYTE]: 1000,
|
||||
[UnitName.MBYTE]: 1000 * 1000,
|
||||
[UnitName.GBYTE]: 1000 * 1000 * 1000,
|
||||
[UnitName.TBYTE]: 1000 * 1000 * 1000 * 1000,
|
||||
[UnitName.KIBYTE]: 1024,
|
||||
[UnitName.MIBYTE]: 1024 * 1024,
|
||||
[UnitName.GIBYTE]: 1024 * 1024 * 1024,
|
||||
[UnitName.TIBYTE]: 1024 * 1024 * 1024 * 1024,
|
||||
[UnitName.BYTE]: 1,
|
||||
[UnitName.BIT]: 1 / 8,
|
||||
[UnitName.KBIT]: 1000 / 8,
|
||||
[UnitName.MBIT]: 1000000 / 8,
|
||||
[UnitName.GBIT]: 1000000000 / 8,
|
||||
[UnitName.TBIT]: 1000000000000 / 8,
|
||||
});
|
||||
|
||||
function sizeChanged(unitName: keyof typeof unitToByte):void {
|
||||
let result: { [name in keyof typeof unitToByte]: string } = Object();
|
||||
const size = ref({
|
||||
[UnitName.KBYTE]: '',
|
||||
[UnitName.MBYTE]: '',
|
||||
[UnitName.GBYTE]: '',
|
||||
[UnitName.TBYTE]: '',
|
||||
[UnitName.KIBYTE]: '',
|
||||
[UnitName.MIBYTE]: '',
|
||||
[UnitName.GIBYTE]: '',
|
||||
[UnitName.TIBYTE]: '',
|
||||
[UnitName.BYTE]: '',
|
||||
[UnitName.BIT]: '',
|
||||
[UnitName.KBIT]: '',
|
||||
[UnitName.MBIT]: '',
|
||||
[UnitName.GBIT]: '',
|
||||
[UnitName.TBIT]: '',
|
||||
});
|
||||
|
||||
/**
|
||||
* Change ref variable when user inputs some characters.
|
||||
* @param {UnitNameStr} unitName
|
||||
* @returns {void}
|
||||
*/
|
||||
function sizeChanged(unitName) {
|
||||
/**
|
||||
* @type {object.<UnitNameStr, string>}
|
||||
*/
|
||||
let result = {};
|
||||
// assign 0 to current input if nothing is passed
|
||||
if (size.value[unitName].length === 0) result[unitName] = '0';
|
||||
let inputedBytes: BigNumber = new BigNumber(unitToByte[unitName]).multipliedBy(size.value[unitName]);
|
||||
for (const key in unitToByte) {
|
||||
result[key] = inputedBytes.div(unitToByte[key]).toString();
|
||||
let inputedBytes = new BigNumber(UnitNameToSize[unitName]).multipliedBy(size.value[unitName]);
|
||||
for (const key in UnitNameToSize) {
|
||||
result[key] = inputedBytes.div(UnitNameToSize[key]).toString();
|
||||
}
|
||||
result[unitName] = size.value[unitName];
|
||||
for (const key in unitToByte) {
|
||||
for (const key in UnitNameToSize) {
|
||||
if (result[key] !== 'NaN') {
|
||||
size.value[key] = result[key];
|
||||
} else if (result[key] === 'NaN') {
|
||||
@ -57,7 +90,7 @@ function sizeChanged(unitName: keyof typeof unitToByte):void {
|
||||
}
|
||||
|
||||
const isMultipleOf4KiB = computed(() => {
|
||||
let userInput: BigNumber = new BigNumber(size.value["unit-ki-byte"])
|
||||
let userInput = new BigNumber(size.value[UnitName.KIBYTE]);
|
||||
if (userInput.toNumber() === 0) return false;
|
||||
return userInput.mod(4).toNumber() === 0 ? true : false;
|
||||
})
|
||||
@ -66,82 +99,84 @@ const isMultipleOf4KiB = computed(() => {
|
||||
<template>
|
||||
<h1>数据单位换算</h1>
|
||||
<div class="unit-conversion-computation-area 1000-in-byte">
|
||||
<p>1000 进制并以 Byte 计: </p>
|
||||
<p>1000 进制并以 Byte 计:</p>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-k-byte" type="text" v-model="size['unit-k-byte']"
|
||||
@input="sizeChanged('unit-k-byte')">
|
||||
<input class="size-text" :id="UnitName.KBYTE" type="text" v-model="size[UnitName.KBYTE]"
|
||||
@input="sizeChanged(UnitName.KBYTE)">
|
||||
<span class="unit-name">KB</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-m-byte" type="text" v-model="size['unit-m-byte']"
|
||||
@input="sizeChanged('unit-m-byte')">
|
||||
<input class="size-text" :id="UnitName.MBYTE" type="text" v-model="size[UnitName.MBYTE]"
|
||||
@input="sizeChanged(UnitName.MBYTE)">
|
||||
<span class="unit-name">MB</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-g-byte" type="text" v-model="size['unit-g-byte']"
|
||||
@input="sizeChanged('unit-g-byte')">
|
||||
<input class="size-text" :id="UnitName.GBYTE" type="text" v-model="size[UnitName.GBYTE]"
|
||||
@input="sizeChanged(UnitName.GBYTE)">
|
||||
<span class="unit-name">GB</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-t-byte" type="text" v-model="size['unit-t-byte']"
|
||||
@input="sizeChanged('unit-t-byte')">
|
||||
<input class="size-text" :id="UnitName.TBYTE" type="text" v-model="size[UnitName.TBYTE]"
|
||||
@input="sizeChanged(UnitName.TBYTE)">
|
||||
<span class="unit-name">TB</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-area 1024-in-byte">
|
||||
<p>1024 进制并以 Byte 计</p>
|
||||
<p>1024 进制并以 Byte 计:</p>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-ki-byte" type="text" v-model="size['unit-ki-byte']"
|
||||
@input="sizeChanged('unit-ki-byte')">
|
||||
<input class="size-text" :id="UnitName.KIBYTE" type="text" v-model="size[UnitName.KIBYTE]"
|
||||
@input="sizeChanged(UnitName.KIBYTE)">
|
||||
<span class="unit-name">KiB</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-mi-byte" type="text" v-model="size['unit-mi-byte']"
|
||||
@input="sizeChanged('unit-mi-byte')">
|
||||
<input class="size-text" :id="UnitName.MIBYTE" type="text" v-model="size[UnitName.MIBYTE]"
|
||||
@input="sizeChanged(UnitName.MIBYTE)">
|
||||
<span class="unit-name">MiB</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-gi-byte" type="text" v-model="size['unit-gi-byte']"
|
||||
@input="sizeChanged('unit-gi-byte')">
|
||||
<input class="size-text" :id="UnitName.GIBYTE" type="text" v-model="size[UnitName.GIBYTE]"
|
||||
@input="sizeChanged(UnitName.GIBYTE)">
|
||||
<span class="unit-name">GiB</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-ti-byte" type="text" v-model="size['unit-ti-byte']"
|
||||
@input="sizeChanged('unit-ti-byte')">
|
||||
<input class="size-text" :id="UnitName.TIBYTE" type="text" v-model="size[UnitName.TIBYTE]"
|
||||
@input="sizeChanged(UnitName.TIBYTE)">
|
||||
<span class="unit-name">TiB</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-area byte-bit">
|
||||
<p>以 Byte (B) / bit (b) 计:</p>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-byte" type="text" v-model="size['unit-byte']" @input="sizeChanged('unit-byte')">
|
||||
<input class="size-text" :id="UnitName.BYTE" type="text" v-model="size[UnitName.BYTE]"
|
||||
@input="sizeChanged(UnitName.BYTE)">
|
||||
<span class="unit-name">B</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-bit" type="text" v-model="size['unit-bit']" @input="sizeChanged('unit-bit')">
|
||||
<input class="size-text" :id="UnitName.BIT" type="text" v-model="size[UnitName.BIT]"
|
||||
@input="sizeChanged(UnitName.BIT)">
|
||||
<span class="unit-name">b</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-area 1000-in-bit">
|
||||
<p>1000 进制并以 bit 计:</p>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-k-bit" type="text" v-model="size['unit-k-bit']"
|
||||
@input="sizeChanged('unit-k-bit')">
|
||||
<input class="size-text" :id="UnitName.KBIT" type="text" v-model="size[UnitName.KBIT]"
|
||||
@input="sizeChanged(UnitName.KBIT)">
|
||||
<span class="unit-name">Kb</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-m-bit" type="text" v-model="size['unit-m-bit']"
|
||||
@input="sizeChanged('unit-m-bit')">
|
||||
<input class="size-text" :id="UnitName.MBIT" type="text" v-model="size[UnitName.MBIT]"
|
||||
@input="sizeChanged(UnitName.MBIT)">
|
||||
<span class="unit-name">Mb</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-g-bit" type="text" v-model="size['unit-g-bit']"
|
||||
@input="sizeChanged('unit-g-bit')">
|
||||
<input class="size-text" :id="UnitName.GBIT" type="text" v-model="size[UnitName.GBIT]"
|
||||
@input="sizeChanged(UnitName.GBIT)">
|
||||
<span class="unit-name">Gb</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" id="unit-t-bit" type="text" v-model="size['unit-t-bit']"
|
||||
@input="sizeChanged('unit-t-bit')">
|
||||
<input class="size-text" :id="UnitName.TBIT" type="text" v-model="size[UnitName.TBIT]"
|
||||
@input="sizeChanged(UnitName.TBIT)">
|
||||
<span class="unit-name">Tb</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -165,7 +200,7 @@ p,
|
||||
|
||||
.size-text {
|
||||
margin: 0 6px 0 0;
|
||||
width: 130px
|
||||
width: 125px
|
||||
}
|
||||
|
||||
@media screen and (max-width: 395px) {
|
||||
@ -174,7 +209,7 @@ p,
|
||||
}
|
||||
|
||||
.size-text {
|
||||
width: 90px;
|
||||
width: 85px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
---
|
||||
import DataUnitConversion from "./DataUnitConversion.vue";
|
||||
import WeightConversion from "./WeightConversion.vue";
|
||||
---
|
||||
|
||||
<DataUnitConversion client:load />
|
||||
|
||||
<WeightConversion client:load />
|
||||
|
147
src/components/tool/unit_conversion/WeightConversion.vue
Normal file
147
src/components/tool/unit_conversion/WeightConversion.vue
Normal file
@ -0,0 +1,147 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
/**
|
||||
* @typedef {string} UnitNameStr
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {UnitNameStr}
|
||||
*/
|
||||
const twToMetricUnitName = Object.freeze({
|
||||
JIN: "jin",
|
||||
LIANG: "liang",
|
||||
QIAN: "qian",
|
||||
FEN: "fen",
|
||||
GRAM: "gram",
|
||||
KILOGRAM: "kilogram"
|
||||
})
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
const twToMetricUnitNameToWeight = Object.freeze({
|
||||
[twToMetricUnitName.JIN]: 600,
|
||||
[twToMetricUnitName.LIANG]: 600 / 16,
|
||||
[twToMetricUnitName.QIAN]: 600 / 16 / 10,
|
||||
[twToMetricUnitName.FEN]: 600 / 16 / 10 / 10,
|
||||
[twToMetricUnitName.GRAM]: 1,
|
||||
[twToMetricUnitName.KILOGRAM]: 1 * 1000,
|
||||
})
|
||||
|
||||
const weight = ref({
|
||||
[twToMetricUnitName.JIN]: '',
|
||||
[twToMetricUnitName.LIANG]: '',
|
||||
[twToMetricUnitName.QIAN]: '',
|
||||
[twToMetricUnitName.FEN]: '',
|
||||
[twToMetricUnitName.GRAM]: '',
|
||||
[twToMetricUnitName.KILOGRAM]: '',
|
||||
});
|
||||
|
||||
/**
|
||||
* Change ref variable when user inputs some characters.
|
||||
* @param {UnitNameStr} unitName
|
||||
* @returns {void}
|
||||
*/
|
||||
function weightChanged(unitName) {
|
||||
/**
|
||||
* @type {object.<UnitNameStr, string>}
|
||||
*/
|
||||
let result = {};
|
||||
// assign 0 to current input if nothing is passed
|
||||
if (weight.value[unitName].length === 0) result[unitName] = '0';
|
||||
let inputedGram = new BigNumber(twToMetricUnitNameToWeight[unitName]).multipliedBy(weight.value[unitName]);
|
||||
for (const key in twToMetricUnitNameToWeight) {
|
||||
result[key] = inputedGram.div(twToMetricUnitNameToWeight[key]).toString();
|
||||
}
|
||||
result[unitName] = weight.value[unitName];
|
||||
for (const key in twToMetricUnitNameToWeight) {
|
||||
if (result[key] !== 'NaN') {
|
||||
weight.value[key] = result[key];
|
||||
} else if (result[key] === 'NaN') {
|
||||
weight.value[key] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>重量换算</h1>
|
||||
<div class="unit-conversion-computation-area metric">
|
||||
<p>公制重量:</p>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" :id="twToMetricUnitName.KILOGRAM" type="text"
|
||||
v-model="weight[twToMetricUnitName.KILOGRAM]" @input="weightChanged(twToMetricUnitName.KILOGRAM)">
|
||||
<span class="unit-name">千克</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" :id="twToMetricUnitName.GRAM" type="text" v-model="weight[twToMetricUnitName.GRAM]"
|
||||
@input="weightChanged(twToMetricUnitName.GRAM)">
|
||||
<span class="unit-name">克</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-area tw">
|
||||
<p>台湾制重量:</p>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" :id="twToMetricUnitName.JIN" type="text" v-model="weight[twToMetricUnitName.JIN]"
|
||||
@input="weightChanged(twToMetricUnitName.JIN)">
|
||||
<span class="unit-name">斤</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" :id="twToMetricUnitName.LIANG" type="text" v-model="weight[twToMetricUnitName.LIANG]"
|
||||
@input="weightChanged(twToMetricUnitName.LIANG)">
|
||||
<span class="unit-name">两</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" :id="twToMetricUnitName.QIAN" type="text" v-model="weight[twToMetricUnitName.QIAN]"
|
||||
@input="weightChanged(twToMetricUnitName.QIAN)">
|
||||
<span class="unit-name">钱</span>
|
||||
</div>
|
||||
<div class="unit-conversion-computation-node">
|
||||
<input class="size-text" :id="twToMetricUnitName.FEN" type="text" v-model="weight[twToMetricUnitName.FEN]"
|
||||
@input="weightChanged(twToMetricUnitName.FEN)">
|
||||
<span class="unit-name">分</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
h1,
|
||||
p,
|
||||
.unit-conversion-computation-node {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
.unit-conversion-computation-node {
|
||||
float: left;
|
||||
width: 170px;
|
||||
margin: 0 8px 0 0;
|
||||
}
|
||||
|
||||
.size-text {
|
||||
margin: 0 6px 0 0;
|
||||
width: 115px
|
||||
}
|
||||
|
||||
@media screen and (max-width: 395px) {
|
||||
.unit-conversion-computation-node {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.size-text {
|
||||
width: 85px;
|
||||
}
|
||||
}
|
||||
|
||||
.unit-conversion-computation-area::after {
|
||||
content: '';
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.unit-conversion-computation-result {
|
||||
margin: 0.5em 0 0.5em 0;
|
||||
height: 1em;
|
||||
}
|
||||
</style>
|
35
src/content/config.ts
Normal file
35
src/content/config.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { z, defineCollection } from 'astro:content';
|
||||
|
||||
const blogCollection = defineCollection({
|
||||
type: 'content',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
category: z.string(),
|
||||
lastUpdate: z.string()
|
||||
}),
|
||||
});
|
||||
const noteCollection = defineCollection({
|
||||
type: 'content',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
category: z.string(),
|
||||
lastUpdate: z.string()
|
||||
}),
|
||||
});
|
||||
const translationCollection = defineCollection({
|
||||
type: 'content',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
category: z.string(),
|
||||
lastUpdate: z.string()
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = {
|
||||
'blog': blogCollection,
|
||||
'note': noteCollection,
|
||||
'translation': translationCollection,
|
||||
};
|
@ -2,11 +2,11 @@
|
||||
import DefaultLayout from "../layouts/DefaultLayout.astro";
|
||||
import Nav from "../components/Nav.astro";
|
||||
import Footer from "../components/Footer.astro";
|
||||
import ArticleBody from "../components/article/ArticleBody.astro";
|
||||
import ArticleBodyWrapper from "../components/article/article_body/ArticleBodyWrapper.astro";
|
||||
---
|
||||
|
||||
<DefaultLayout title="404">
|
||||
<Nav />
|
||||
<ArticleBody collectionName="site" articleSlug="404" />
|
||||
<ArticleBodyWrapper collectionName="site" articleSlug="404" />
|
||||
<Footer />
|
||||
</DefaultLayout>
|
||||
|
@ -7,7 +7,7 @@ import type {
|
||||
} from "astro:content";
|
||||
import Footer from "../../../components/Footer.astro";
|
||||
import Nav from "../../../components/Nav.astro";
|
||||
import ArticleBody from "../../../components/article/ArticleBody.astro";
|
||||
import ArticleBodyWrapper from "../../../components/article/article_body/ArticleBodyWrapper.astro";
|
||||
import DefaultLayout from "../../../layouts/DefaultLayout.astro";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
@ -29,6 +29,6 @@ const articlePrettyName:string = entry.id.split("/").pop()!.replace(".md", "");
|
||||
|
||||
<DefaultLayout title=`${articlePrettyName} - 李守中`>
|
||||
<Nav />
|
||||
<ArticleBody collectionName="blog" articleSlug={entry.slug} />
|
||||
<ArticleBodyWrapper collectionName="blog" articleSlug={entry.slug} />
|
||||
<Footer />
|
||||
</DefaultLayout>
|
||||
|
@ -7,7 +7,7 @@ import type {
|
||||
} from "astro:content";
|
||||
import Footer from "../../../components/Footer.astro";
|
||||
import Nav from "../../../components/Nav.astro";
|
||||
import ArticleBody from "../../../components/article/ArticleBody.astro";
|
||||
import ArticleBodyWrapper from "../../../components/article/article_body/ArticleBodyWrapper.astro";
|
||||
import DefaultLayout from "../../../layouts/DefaultLayout.astro";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
@ -29,6 +29,6 @@ const articlePrettyName:string = entry.id.split("/").pop()!.replace(".md", "");
|
||||
|
||||
<DefaultLayout title=`${articlePrettyName} - 李守中`>
|
||||
<Nav />
|
||||
<ArticleBody collectionName="note" articleSlug={entry.slug} />
|
||||
<ArticleBodyWrapper collectionName="note" articleSlug={entry.slug} />
|
||||
<Footer />
|
||||
</DefaultLayout>
|
||||
|
@ -7,7 +7,7 @@ import type {
|
||||
} from "astro:content";
|
||||
import Footer from "../../../components/Footer.astro";
|
||||
import Nav from "../../../components/Nav.astro";
|
||||
import ArticleBody from "../../../components/article/ArticleBody.astro";
|
||||
import ArticleBodyWrapper from "../../../components/article/article_body/ArticleBodyWrapper.astro";
|
||||
import DefaultLayout from "../../../layouts/DefaultLayout.astro";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
@ -29,6 +29,6 @@ const articlePrettyName:string = entry.id.split("/").pop()!.replace(".md", "");
|
||||
|
||||
<DefaultLayout title=`${articlePrettyName} - 李守中`>
|
||||
<Nav />
|
||||
<ArticleBody collectionName="translation" articleSlug={entry.slug} />
|
||||
<ArticleBodyWrapper collectionName="translation" articleSlug={entry.slug} />
|
||||
<Footer />
|
||||
</DefaultLayout>
|
||||
|
@ -2,11 +2,11 @@
|
||||
import DefaultLayout from "../layouts/DefaultLayout.astro";
|
||||
import Nav from "../components/Nav.astro";
|
||||
import Footer from "../components/Footer.astro";
|
||||
import ArticleBody from "../components/article/ArticleBody.astro";
|
||||
import ArticleBodyWrapper from "../components/article/article_body/ArticleBodyWrapper.astro";
|
||||
---
|
||||
|
||||
<DefaultLayout title="李守中">
|
||||
<Nav />
|
||||
<ArticleBody collectionName="site" articleSlug="关于本站" />
|
||||
<ArticleBodyWrapper collectionName="site" articleSlug="关于本站" />
|
||||
<Footer />
|
||||
</DefaultLayout>
|
||||
|
Loading…
x
Reference in New Issue
Block a user