master
cast1e 2025-03-07 12:04:28 +08:00
parent 5c258b85e8
commit 4cf4fdce17
18 changed files with 374 additions and 130 deletions

2
.gitignore vendored
View File

@ -24,4 +24,4 @@ pnpm-debug.log*
*.sw?
auto-imports.d.ts
component.d.ts
components.d.ts

View File

@ -8,24 +8,8 @@
<title>
Wordin
</title>
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
#app {
height: 100%;
width: 100%;
overflow: hidden;
}
</style>
<link rel="stylesheet" crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/misans@4.0.0/lib/Normal/MiSans-Medium.min.css" />
</head>
<body>
<noscript>
<strong>We're sorry but doesn't work properly without JavaScript enabled.

View File

@ -11,6 +11,8 @@
"dependencies": {
"@jamescoyle/vue-icon": "^0.1.2",
"@mdi/font": "^7.4.47",
"@types/animejs": "^3.1.13",
"animejs": "^3.2.2",
"axios": "^1.5.1",
"boxicons": "^2.1.4",
"core-js": "^3.8.3",

View File

@ -14,6 +14,12 @@ importers:
'@mdi/font':
specifier: ^7.4.47
version: 7.4.47
'@types/animejs':
specifier: ^3.1.13
version: 3.1.13
animejs:
specifier: ^3.2.2
version: 3.2.2
axios:
specifier: ^1.5.1
version: 1.8.1
@ -1070,6 +1076,9 @@ packages:
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
engines: {node: '>=10.13.0'}
'@types/animejs@3.1.13':
resolution: {integrity: sha512-yWg9l1z7CAv/TKpty4/vupEh24jDGUZXv4r26StRkpUPQm04ztJaftgpto8vwdFs8SiTq6XfaPKCSI+wjzNMvQ==}
'@types/body-parser@1.19.5':
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
@ -1503,6 +1512,9 @@ packages:
alien-signals@1.0.4:
resolution: {integrity: sha512-DJqqQD3XcsaQcQ1s+iE2jDUZmmQpXwHiR6fCAim/w87luaW+vmLY8fMlrdkmRwzaFXhkxf3rqPCR59tKVv1MDw==}
animejs@3.2.2:
resolution: {integrity: sha512-Ao95qWLpDPXXM+WrmwcKbl6uNlC5tjnowlaRYtuVDHHoygjtIPfDUoK9NthrlZsQSKjZXlmji2TrBUAVbiH0LQ==}
ansi-escapes@3.2.0:
resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==}
engines: {node: '>=4'}
@ -5640,6 +5652,8 @@ snapshots:
'@trysound/sax@0.2.0': {}
'@types/animejs@3.1.13': {}
'@types/body-parser@1.19.5':
dependencies:
'@types/connect': 3.4.38
@ -6406,6 +6420,8 @@ snapshots:
alien-signals@1.0.4: {}
animejs@3.2.2: {}
ansi-escapes@3.2.0: {}
ansi-html-community@0.0.8: {}

View File

@ -11,11 +11,11 @@
<router-view style=""></router-view>
<div class="mbonly">
<div id="navibar">
<div class="navi-item"><box-icon name="home-alt-2" @click="$router.push('/')" color="var(--text-color)" size="27px"></box-icon><div></div></div>
<div class="navi-item"><box-icon name="book-open" @click="$router.push('/select')" color="var(--text-color)" size="27px"></box-icon><div></div></div>
<div class="navi-item"><box-icon name="folder" @click="$router.push('/manage')" color="var(--text-color)" size="27px"></box-icon><div></div></div>
<div class="navi-item"><box-icon name="file" @click="$router.push('/manual')" color="var(--text-color)" size="27px"></box-icon><div></div></div>
<div class="navi-item"><box-icon name="info-circle" @click="$router.push('/about')" color="var(--text-color)" size="27px"></box-icon><div></div></div>
<div class="navi-item"><v-icon @click="$router.push('/')">mdi-home</v-icon> <div>主页</div></div>
<div class="navi-item"><v-icon @click="$router.push('/select')">mdi-book</v-icon> <div>背诵</div></div>
<div class="navi-item"><v-icon @click="$router.push('/manage')">mdi-folder</v-icon><div>浏览</div></div>
<div class="navi-item"><v-icon @click="$router.push('/manual')">mdi-file</v-icon><div>说明</div></div>
<div class="navi-item"><v-icon @click="$router.push('/about')">mdi-information</v-icon><div>关于</div></div>
</div>
</div>
</template>

View File

@ -1,39 +1,12 @@
<style scoped>
.container {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
html:not(.dark) .dynamic-bg-container {
background: linear-gradient(135deg,
#ffe8f3,
#d9f3ff);
/* Soft pastel gradient background */
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
position: relative;
}
.wrapper {
position: relative;
width: 100%;
/* Fill the entire screen */
height: 100%;
overflow: hidden;
background: radial-gradient(circle,
rgba(255, 255, 255, 0.2),
rgba(0, 0, 0, 0.1));
}
.wrapper::before,
.wrapper::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 200%;
height: 200%;
html:not(.dark) .dynamic-bg-wrapper::before,
html:not(.dark) .dynamic-bg-wrapper::after {
background: conic-gradient(from 0deg,
#ff9aa2,
/* Soft pink */
@ -49,15 +22,71 @@
/* Lavender */
#ffb7b2,
#ff9aa2);
}
html.dark .dynamic-bg-container {
background: linear-gradient(135deg,
#331a26,
#1a2a33);
}
html.dark .dynamic-bg-wrapper::before,
html.dark .dynamic-bg-wrapper::after {
background: conic-gradient(from 0deg,
#662a30,
#663a36,
#664a40,
#3a4a33,
#2a4a66,
#3a2a66,
#663a36,
#662a30);
opacity: 0.6;
}
.dynamic-bg-container {
margin: 0;
padding: 0;
height: fit-content;
width: 100%;
/* Soft pastel gradient background */
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
position: relative;
}
.dynamic-bg-wrapper {
position: absolute;
width: 100%;
/* Fill the entire screen */
height: 100%;
overflow: hidden;
background: radial-gradient(circle,
rgba(255, 255, 255, 0.2),
rgba(0, 0, 0, 0.1));
}
.dynamic-bg-wrapper::before,
.dynamic-bg-wrapper::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 200%;
height: 200%;
transform: translate(-50%, -50%);
animation: rotate 8s linear infinite;
filter: blur(50px);
/* Create a soft glowing effect */
opacity: 0.8;
z-index: 9;
}
/* Secondary rotating layer for depth */
.wrapper::after {
.dynamic-bg-wrapper::after {
width: 180%;
height: 180%;
animation: rotate-reverse 10s linear infinite;
@ -84,20 +113,20 @@
transform: translate(-50%, -50%) rotate(-360deg);
}
}
.dynamic-bg-content {
width: 100%;
height: fit-content;
padding: 10px;
z-index: 10;
}
</style>
<template>
<div class="container">
<div class="wrapper">
<div class="dynamic-bg-container">
<div class="dynamic-bg-wrapper"></div>
<div class="dynamic-bg-content">
<slot name="content"></slot>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue';
onMounted(() => {
console.log("DynamicBackground component loaded");
});
</script>

View File

@ -1,7 +1,5 @@
# 关于 wordIn
---
## 1. wordIn 是什么
wordIn 是一款基于 vue.js 的单词默写器,致力于为用户提供便捷有效的单词记忆方式

View File

@ -1,7 +1,5 @@
# wordIn 使用说明
---
- 近期发现ZJUWLAN无法访问unpkg.com导致部分图标无法显示,请使用ZJUWLAN-Secure访问
## 1. 背诵单词

View File

@ -1,7 +1,7 @@
import {createRouter,createWebHashHistory} from 'vue-router'
const manage = ()=>import('@/views/ManageView.vue');
const editor = ()=>import('@/views/manage/EditorView.vue');
const home = ()=>import("@/views/HomeView.vue");
import home from "@/views/HomeView.vue";
const recite = ()=>import('@/views/recite/ReciteView.vue');
const setlist = ()=>import('@/views/manage/SetListView.vue');
const newset = ()=>import('@/views/manage/NewSetView.vue');

View File

@ -1,3 +1,33 @@
html{
height: 100%;
width: 100%;
}
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
overflow: hidden;
font-family:
'MiSans',
-apple-system, /* macOS, iOS */
BlinkMacSystemFont, /* Chrome macOS */
"Segoe UI", /* Windows */
Roboto, /* Android */
"Helvetica Neue", /* 一些 macOS 和 iOS 系统 */
Arial, /* 常见替代字体 */
"Noto Sans", /* 国际化字体 */
"Liberation Sans", /* Linux 系统的替代字体 */
sans-serif; /* 默认字体 */
}
#app {
height: 100%;
width: 100%;
overflow: hidden;
}
@media screen and (max-width: 500px) {
.pconly {
display: none;
@ -43,6 +73,7 @@
html {
--bg-color-solid: #e8e8e8;
--bg-color: #ffffffae;
--bg-color-acrylic:#ffffff54;
--text-color: #464646;
--bd-color: #bbbbbb99;
}
@ -50,6 +81,7 @@ html {
html.dark {
--bg-color-solid: #191919;
--bg-color: #2a2a2a88;
--bg-color-acrylic:rgba(42, 42, 42, 0.263);
--text-color: #c0c0c0;
--bd-color: #7f7f7f7c;
--navi-bg-color: #131313e2;

View File

@ -0,0 +1,155 @@
/* Markdown Typography */
.markdown {
line-height: 1.6;
color: #333;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
/* Headings */
.markdown h1,
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
/* margin-top: 1.5em; */
margin-bottom: 0.5em;
font-weight: 600;
line-height: 1.25;
}
.markdown h1 {
font-size: 2.5em;
border-bottom: 1px solid var(--bd-color);
padding-bottom: 0.3em;
}
.markdown h2 {
font-size: 1.75em;;
padding-bottom: 0.3em;
}
.markdown h3 {
font-size: 1.25em;
}
.markdown h4 {
font-size: 1em;
}
.markdown h5 {
font-size: 0.875em;
}
.markdown h6 {
font-size: 0.85em;
color: #6a737d;
}
/* Lists */
.markdown ul,
.markdown ol {
padding-left: 2em;
margin-top: 0.5em;
margin-bottom: 1em;
}
.markdown ul {
list-style-type: disc;
}
.markdown ol {
list-style-type: decimal;
}
.markdown li {
margin-bottom: 0.25em;
}
.markdown li > ul,
.markdown li > ol {
margin-top: 0.25em;
margin-bottom: 0.5em;
}
/* Paragraphs and spacing */
.markdown p {
margin-top: 0;
margin-bottom: 1em;
}
/* Links */
.markdown a {
text-decoration: none;
}
.markdown a:hover {
text-decoration: underline;
}
/* Code blocks */
.markdown pre {
background-color: #f6f8fa;
border-radius: 3px;
padding: 16px;
overflow: auto;
margin-bottom: 1em;
}
.markdown code {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
background-color: var(--bg-color-solid);
border-radius: 3px;
padding: 0.2em 0.4em;
font-size: 85%;
}
.markdown pre code {
background-color: transparent;
padding: 0;
}
/* Blockquotes */
.markdown blockquote {
margin-left: 0;
padding: 0 1em;
color: var(--text-color);
border-left: 0.25em solid var(--bd-color);
}
/* Tables */
.markdown table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1em;
}
.markdown table th,
.markdown table td {
padding: 6px 13px;
border: 1px solid var(--bd-color);
}
.markdown table tr {
background-color: var(--bg-color-solid);
border-top: 1px solid var(--bd-color);
}
.markdown table tr:nth-child(2n) {
background-color: var(--bg-color-solid);
}
/* Horizontal rule */
.markdown hr {
height: 0.25em;
padding: 0;
margin: 24px 0;
background-color: var(--bg-color-solid);
border: 0;
}
/* Images */
.markdown img {
max-width: 100%;
box-sizing: border-box;
}

View File

@ -1,17 +1,14 @@
<template>
<div class="container rowbox" style="height: calc(100% - 65px); align-items: center;width: 100%;overflow: auto;">
<DynamicBackground>
<div class="home-view-container">
<DynamicBackground class="home-view-header">
<template #content>
</template>
</DynamicBackground>
<div class="colbox" style="width: 95%;margin-top: 10px;">
<div style="flex-grow: 2;margin:30px;" class="rowbox">
<div style="font-size: 25px;color: var(--text-color);font-weight: 600;">欢迎使用</div>
<div id="title">wordIn</div>
<div>当前版本: 1.02 <br /> 更新时间:2025年3月7日 10:35 PM</div>
<div>当前版本: 1.03 beta1 <br /> 更新时间:2025年3月7日 12:03</div>
</div>
<div style="flex-grow: 1;align-items: center;" class="colbox card">
<div class="colbox card home-view-option-wrapper">
<router-link to="/select" class="button">
开始新背诵
</router-link>
@ -20,9 +17,12 @@
</router-link>
</div>
</div>
<div id="history" class="wrapper">
<div class="title" style="margin-left: 20px;margin-top: 10px;width: 95%;">历史记录</div>
<div class="card colbox history-item" v-for="(history, index) in store.history._content" :key="index">
</template>
</DynamicBackground>
<div class="wrapper home-view-history">
<div class="home-view-history-title" style="margin-left: 20px;margin-top: 10px;width: 95%;">历史记录</div>
<div class="home-view-history-item" v-for="(history, index) in store.history._content" :key="index">
<div class="card colbox" >
<div style="width: 25px;">{{ index + 1 }}</div>
<div style="width: 200px;">背诵进度: {{ history.current }}/{{ history.total || "Unknown" }}</div>
<div style="flex-grow: 1;"> {{ (new Date(history.modified)) }}</div>
@ -30,8 +30,9 @@
</div>
</div>
</div>
</div>
<div id="setting">
<box-icon class="btn" color="var(--text-color)" name='cog' @click="open_setting_dialog"></box-icon>
<v-icon class="btn" @click="open_setting_dialog">mdi-cog</v-icon>
</div>
<el-dialog v-model="settingVisible" title="设置" width="75%">
<div class="title">更换自定义背景</div>
@ -44,9 +45,10 @@
<script setup lang="ts">
import { useMainStore } from '@/store';
import { ref } from 'vue';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import DynamicBackground from '@/components/DynamicBackground.vue';
import animejs from 'animejs';
const store = useMainStore();
const router = useRouter();
@ -68,6 +70,21 @@ const restart = (index: number): void => {
query: { index }
});
};
onMounted(()=>{
animejs({
targets:".home-view-header",
translateY: [-50,0],
opacity: [0,1],
})
animejs({
targets:".home-view-history-title,.home-view-history-item",
translateX: [50,0],
opacity: [0,1],
delay: animejs.stagger(50),
})
})
</script>
<style scoped>
@ -78,7 +95,7 @@ const restart = (index: number): void => {
text-shadow: #00000057 5px 5px 20px;
}
.title {
.home-view-history-title {
font-weight: 800;
color: var(--text-color);
font-size: 15px;
@ -107,6 +124,10 @@ const restart = (index: number): void => {
}
@media screen and (min-width: 500px) {
.home-view-container{
display: flex;
flex-direction: column;
}
#title {
font-size: 100px;
color: var(--text-color);
@ -116,7 +137,7 @@ const restart = (index: number): void => {
margin-bottom: 15px;
}
.title {
.home-view-history-title {
font-weight: 600;
color: var(--text-color);
font-size: 35px;
@ -140,22 +161,12 @@ const restart = (index: number): void => {
}
}
#history {
width: calc(95% - 20px);
flex-grow: 1;
}
.wrapper {
border: 1px solid var(--bd-color);
/* border: 1px solid var(--bd-color); */
border-radius: 5px;
margin-top: 10px;
}
.history-item {
margin: 20px;
padding: 15px;
}
#setting {
position: absolute;
right: 0;
@ -192,17 +203,30 @@ html.dark .button {
.button:hover {
box-shadow: var(--el-box-shadow) inset #00000017 0px 500px;
}
</style>
#ball {
background-image: linear-gradient(120deg, #e0c3fcca 0%, #8ec5fcc4 100%);
border-radius: 100%;
position: absolute;
animation: enter .8s ease-out;
box-shadow: #e0c3fcca 0px 0px 50px 10px;
z-index: -1;
<style>
.home-view-history {
width: 100%;
padding: 20px;
padding-top: 10px;
box-sizing: border-box;
flex-grow: 1;
overflow: hidden;
}
html.bgimged #ball {
backdrop-filter: blur(20px);
.home-view-container{
height: calc(100% - 65px);
align-items: center;
width: 100%;
overflow: auto;
}
.home-view-option-wrapper{
flex-grow: 1;
align-items: center;
justify-content: center;
background-color: var(--bg-color-acrylic);
}
</style>

View File

@ -7,12 +7,12 @@
<template #extra>
<el-dropdown trigger="click">
<el-button>
操作<box-icon color="var(--text-color)" name='chevron-down' size="20px"></box-icon>
操作<v-icon size="20px">mdi-chevron-down</v-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="download"><box-icon color="var(--text-color)" name='download'
size="20px"></box-icon></el-dropdown-item>
<el-dropdown-item @click="download"><v-icon
size="20px">mdi-download</v-icon></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
@ -113,7 +113,7 @@ onMounted(() => {
padding-top: 0;
}
#main{
#main {
height: calc(100% - 50px);
}

View File

@ -7,7 +7,7 @@
<template #extra>
<el-dropdown trigger="click">
<el-button>
操作<box-icon color="var(--text-color)" name='chevron-down' size="20px"></box-icon>
操作<v-icon size="20px">mdi-chevron-down</v-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>

View File

@ -1,11 +1,12 @@
<template>
<div id="wrapper" class="rowbox container">
<Post id="post"/>
<Post class="markdown" id="post"/>
</div>
</template>
<script setup lang="ts">
import Post from '@/md/about.md';
import '@/styles/markdown.css';
</script>
<style scoped>

View File

@ -1,11 +1,12 @@
<template>
<div id="wrapper" class="rowbox container">
<Post id="post"/>
<Post class="markdown" id="post"/>
</div>
</template>
<script setup lang="ts">
import Post from '@/md/manual.md';
import '@/styles/markdown.css';
</script>
<style scoped>

View File

@ -19,7 +19,7 @@
<el-checkbox-group v-model="local.checkedSets" @change="(res: string[]) => { handleChange(local, res) }">
<div class="set_radios" v-for="(set_class, set_class_name) in store.wordsets._inner"
:key="set_class_name">
<p>{{ set_class_name }}</p>
<p class="mb-4 mt-2">{{ set_class_name }}</p>
<el-checkbox class="checkbox" v-for="set in set_class" :key="set.id" :label="set.id"
size="large" border>
<div style="font-size: 18px;font-weight: 500;">
@ -37,7 +37,7 @@
<div class="set_radios" v-for="(set, set_name) in online_sets" :key="set_name">
<div class="subtitle">{{ set_name }}</div>
<div v-for="(book, book_name) in set" :key="book_name">
<p>{{ book_name }}</p>
<p class="mb-4 mt-2">{{ book_name }}</p>
<el-checkbox class="checkbox" v-for="(config, id) in book" :key="id" :label="id"
size="large" border>
<div style="font-size: 18px;font-weight: 500;">

View File

@ -35,7 +35,11 @@ export default defineConfig({
},
server: {
proxy: {
'/': {
'/wordset': {
target: 'https://app.cast1e.top/wordin',
changeOrigin: true,
},
'/upload': {
target: 'https://app.cast1e.top/wordin',
changeOrigin: true,
},