389 lines
10 KiB
Vue
389 lines
10 KiB
Vue
<template>
|
|
<el-container id="main-container">
|
|
<el-header id="header" style="text-align: right;">
|
|
<div>
|
|
<el-button @click="manage_online_wordsets" type="primary"><box-icon color="white" name='world'
|
|
size="20px"></box-icon>管理在线单词本</el-button>
|
|
<el-button @click="export_set" type="success" class="pconly"><box-icon color="white" name='export'
|
|
size="18px"></box-icon>导出</el-button>
|
|
<el-button @click="import_set" type="warning" class="pconly"><box-icon color="white" name='import'
|
|
size="18px"></box-icon>导入</el-button>
|
|
<el-button @click="$router.push('/manage/new')" type="primary"><box-icon color="white"
|
|
name='plus'></box-icon>新建单词本</el-button>
|
|
</div>
|
|
</el-header>
|
|
<el-container style="height:calc(100% - 40px);">
|
|
<el-aside id="sidebar">
|
|
<div class="sidebar-title">
|
|
|本地
|
|
</div>
|
|
<div v-for="(set_class, class_name) in wordsets" :title="class_name" :key="class_name"
|
|
@click="view(class_name)" class="sidebar-item">
|
|
{{ class_name }}
|
|
</div>
|
|
<div class="sidebar-title">
|
|
|在线
|
|
</div>
|
|
</el-aside>
|
|
<el-main id="wordsets-container">
|
|
<div id="sets-container">
|
|
<div class="colbox wordclass">
|
|
<div v-for="(wordset, index) in wordsets[view_class]" :key="index" class="wordset rowbox">
|
|
<div class="no">
|
|
{{ index + 1 }}
|
|
</div>
|
|
<div class="title">
|
|
{{ wordset.name }}
|
|
</div>
|
|
<div class="created-date">
|
|
创建日期:{{ (new Date(wordset.created)).toLocaleString() }}
|
|
</div>
|
|
<div class="option">
|
|
<box-icon class="btn" name='edit' color="var(--text-color)"
|
|
@click="edit(wordset, class_name)"></box-icon>
|
|
<box-icon class="btn" name='trash' color="var(--text-color)"
|
|
@click="del(class_name, wordset.id, index)"></box-icon>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="mbonly" id="show-sidebar" @click="taggle_sidebar">
|
|
<box-icon name='list-ul' color="var(--text-color)"></box-icon>
|
|
</div>
|
|
</el-main>
|
|
</el-container>
|
|
</el-container>
|
|
</template>
|
|
|
|
<script>
|
|
import { ElNotification, ElMessage, ElMessageBox } from 'element-plus';
|
|
|
|
export default {
|
|
name: "SetList",
|
|
data() {
|
|
return {
|
|
wordsets: window.wordsets,
|
|
view_class: "",
|
|
}
|
|
},
|
|
methods: {
|
|
view(classname) {
|
|
this.view_class = classname;
|
|
let node = document.getElementById("wordsets-container").style;
|
|
node.animation = "";
|
|
setTimeout(() => {
|
|
node.animation = "enter ease-out .6s backwards";
|
|
}, 0);
|
|
},
|
|
manage_online_wordsets() {
|
|
window.location.href = '/dashboard';
|
|
},
|
|
del(set_class_name, id, index) {
|
|
ElMessageBox.confirm("确定要删除吗?")
|
|
.then(() => {
|
|
localStorage.removeItem(id);
|
|
this.wordsets[set_class_name].splice(index, 1);
|
|
if (!this.wordsets[set_class_name].length) {
|
|
delete this.wordsets[set_class_name];
|
|
}
|
|
localStorage.setItem("wordsets", JSON.stringify(this.wordsets));
|
|
ElMessage(`已经删除 ${set_class_name} `);
|
|
});
|
|
},
|
|
edit(set, set_class_name) {
|
|
window.editing = { set, set_class_name };
|
|
this.$router.push({
|
|
path: "/manage/edit",
|
|
})
|
|
},
|
|
async export_set() {
|
|
let fileHandle = await window.showSaveFilePicker({
|
|
types: [
|
|
{
|
|
description: "JSON file",
|
|
accept: {
|
|
'text/json': ['.json'],
|
|
},
|
|
},
|
|
],
|
|
});
|
|
let writestream = await fileHandle.createWritable();
|
|
let data = {
|
|
wordsets: this.wordsets,
|
|
words: {}
|
|
};
|
|
for (let i of Object.values(this.wordsets)) {
|
|
for (let j of i) {
|
|
let temp = localStorage.getItem(j.id);
|
|
data.words[j.id] = temp;
|
|
}
|
|
}
|
|
writestream.write(JSON.stringify(data));
|
|
writestream.close();
|
|
},
|
|
async import_set() {
|
|
let [fileHandle] = await window.showOpenFilePicker({
|
|
types: [
|
|
{
|
|
description: "JSON file",
|
|
accept: {
|
|
'text/json': ['.json'],
|
|
},
|
|
},
|
|
],
|
|
});
|
|
let file = await fileHandle.getFile();
|
|
let data = JSON.parse(await file.text());
|
|
let cnt = 0;
|
|
for (let i of Object.keys(data.wordsets)) {
|
|
for (let j of data.wordsets[i]) {
|
|
if (!localStorage.getItem(j.id)) {
|
|
if (!this.wordsets[i]) this.wordsets[i] = [];
|
|
this.wordsets[i].push(j);
|
|
localStorage.setItem(j.id, data.words[j.id]);
|
|
cnt++;
|
|
}
|
|
}
|
|
}
|
|
localStorage.setItem("wordsets", JSON.stringify(this.wordsets));
|
|
ElNotification({
|
|
type: "success",
|
|
title: "添加成功",
|
|
message: `已添加 ${cnt} 本单词本`
|
|
});
|
|
},
|
|
taggle_sidebar(){
|
|
let node = document.getElementById("sidebar");
|
|
if(node.style.width === "180px") node.style.width = "0";
|
|
else node.style.width = "180px";
|
|
return;
|
|
}
|
|
},
|
|
created() {
|
|
let first_set = Object.keys(this.wordsets)[0];
|
|
if (first_set) {
|
|
setTimeout(() => {
|
|
this.view(first_set);
|
|
}, 0);
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
@media screen and (max-width: 500px) {
|
|
@keyframes sidebar-enter {
|
|
0% {
|
|
translate: -100px 0;
|
|
opacity: 0;
|
|
}
|
|
|
|
100% {
|
|
translate: 0 0;
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
#sidebar {
|
|
width: 0;
|
|
transition: .5s;
|
|
}
|
|
|
|
.wordset {
|
|
border-radius: 13px;
|
|
padding: 10px;
|
|
height: 180px;
|
|
width: 40%;
|
|
box-shadow: var(--el-box-shadow);
|
|
margin: 5px;
|
|
background-color: var(--bg-color);
|
|
color: var(--text-color);
|
|
}
|
|
|
|
.no {
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.title {
|
|
font-weight: 800;
|
|
color: var(--text-color);
|
|
font-size: 30px;
|
|
flex-grow: 1;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
min-height: 60px;
|
|
}
|
|
|
|
.created-date {
|
|
font-size: 12px;
|
|
font-weight: 200;
|
|
height: 45px;
|
|
}
|
|
|
|
.wordset .option {
|
|
opacity: 1;
|
|
}
|
|
|
|
#show-sidebar {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 100%;
|
|
width: 40px;
|
|
height: 40px;
|
|
position: absolute;
|
|
bottom: 20px;
|
|
left: 20px;
|
|
color: var(--text-color);
|
|
box-shadow: var(--el-box-shadow);
|
|
background-color: var(--bg-color);
|
|
cursor: pointer;
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
#wordsets-container{
|
|
width: 100%;
|
|
display: flex;
|
|
}
|
|
#sets-container{
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
@media screen and (min-width: 500px) {
|
|
@keyframes sidebar-enter {
|
|
0% {
|
|
translate: -100px 0;
|
|
opacity: 0;
|
|
filter: blur(20px);
|
|
}
|
|
|
|
100% {
|
|
translate: 0 0;
|
|
opacity: 1;
|
|
filter: blur(0px);
|
|
}
|
|
}
|
|
|
|
#sidebar {
|
|
width: 180px;
|
|
}
|
|
|
|
.wordset {
|
|
border-radius: 13px;
|
|
padding: 20px;
|
|
height: 220px;
|
|
width: 170px;
|
|
box-shadow: var(--el-box-shadow);
|
|
margin: 20px;
|
|
background-color: var(--bg-color);
|
|
color: var(--text-color);
|
|
}
|
|
|
|
.no {
|
|
font-size: 20px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
.title {
|
|
font-weight: 800;
|
|
color: var(--text-color);
|
|
font-size: 35px;
|
|
flex-grow: 1;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
min-height: 60px;
|
|
}
|
|
|
|
.created-date {
|
|
font-size: 17px;
|
|
font-weight: 200;
|
|
}
|
|
|
|
.wordset:hover .option {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#sidebar {
|
|
background-color: var(--bg-color);
|
|
border-radius: 0 5px 5px 0;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
animation: sidebar-enter ease-out .6s backwards;
|
|
}
|
|
|
|
.sidebar-title {
|
|
width: 100%;
|
|
font-size: 25px;
|
|
line-height: 60px;
|
|
padding-left: 5px;
|
|
font-weight: 800;
|
|
letter-spacing: 3px;
|
|
}
|
|
|
|
html.bgimged #sidebar {
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
|
|
html.bgimged .wordset {
|
|
backdrop-filter: blur(10px);
|
|
}
|
|
|
|
.sidebar-item {
|
|
margin-left: 10px;
|
|
width: 100%;
|
|
font-size: 20px;
|
|
line-height: 50px;
|
|
padding-left: 5px;
|
|
cursor: pointer;
|
|
transition: .5s;
|
|
}
|
|
|
|
.sidebar-item:hover {
|
|
background-color: #00000033;
|
|
}
|
|
|
|
.option {
|
|
display: flex;
|
|
justify-content: space-around;
|
|
opacity: 0;
|
|
transition: .5s;
|
|
}
|
|
|
|
#header {
|
|
/* border-bottom: solid 1px #bcbcbc; */
|
|
justify-content: space-between;
|
|
height: 40px;
|
|
}
|
|
|
|
#wordsets-container {
|
|
overflow-x: auto;
|
|
height: 100%;
|
|
position: relative;
|
|
}
|
|
|
|
#main-container {
|
|
height: 100%;
|
|
width: 100%;
|
|
}
|
|
|
|
.wordclass {
|
|
flex-wrap: wrap
|
|
}
|
|
|
|
.card div {
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.el-collapse {
|
|
--el-collapse-header-bg-color: #FFFFFF00;
|
|
--el-collapse-content-bg-color: #FFFFFF00;
|
|
--el-collapse-header-font-size: 18px;
|
|
}
|
|
</style> |