wordset-managing functions

master
cast1e 2024-04-12 09:52:25 +08:00
parent 34ad23db7a
commit a4a5e7ce9b
9 changed files with 352 additions and 63 deletions

View File

@ -116,13 +116,19 @@ export default {
} }
} }
#app{
transition: .5s;
}
html { html {
--bg-color-solid:#e8e8e8;
--bg-color: #ffffffae; --bg-color: #ffffffae;
--text-color: #464646; --text-color: #464646;
--bd-color: #bbbbbb99; --bd-color: #bbbbbb99;
} }
html.dark { html.dark {
--bg-color-solid:#191919;
--bg-color: #2a2a2a88; --bg-color: #2a2a2a88;
--text-color: #c0c0c0; --text-color: #c0c0c0;
--bd-color: #7f7f7f7c; --bd-color: #7f7f7f7c;
@ -179,6 +185,10 @@ html.bgimged .card {
.para { .para {
margin: 15px; margin: 15px;
} }
.blured {
filter: blur(10px);
}
</style> </style>
<style scoped> <style scoped>

View File

@ -0,0 +1,96 @@
<template>
<div id="mask" v-if="visible">
<div ref="bg" id="bg">
<div id="content">
<slot name="content"></slot>
</div>
<div id="close" @click="handleClose"><box-icon color="var(--text-color)" size="20px" name="x"></box-icon></div>
</div>
</div>
</template>
<script>
export default {
name:"CDiaLog",
props:{
"visible":{
type:Boolean,
default:false
}
},
methods:{
handleClose(){
this.$refs.bg.style.animation = "cui-dialog-disappear .3s ease-in";
setTimeout(()=>this.$emit("update:visible",false),300);
}
}
}
</script>
<style>
@keyframes cui-dialog-appear {
0%{
opacity: 0%;
transform: translate(-50%,-50%) scale(0.5);
}
100%{
opacity: 100%;
transform: translate(-50%,-50%) scale(1);
}
}
@keyframes cui-dialog-disappear {
0%{
opacity: 100%;
transform: translate(-50%,-50%) scale(1);
}
100%{
opacity: 0%;
transform: translate(-50%,-50%) scale(0.5);
}
}
@keyframes cui-dialog-blur{
0%{
backdrop-filter:blur(0px);
}
100%{
backdrop-filter:blur(10px);
}
}
</style>
<style scoped>
#mask{
z-index: 500;
position: absolute;
top:0;
left: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(10px);
animation: cui-dialog-blur .5s ;
}
#bg{
position: absolute;
width: 500px;
height: 300px;
max-width: 80%;
border: solid var(--bd-color) 1px;
background-color: var(--bg-color-solid);
border-radius: 8px;
transform: translate(-50%,-50%);
top: 50%;
left: 50%;
animation: cui-dialog-appear .4s cubic-bezier(0, 0, 0.36, 1.29);
}
#content{
padding: 20px;
height: 100%;
}
#close{
position: absolute;
right:0;
top: 0;
margin: 5px;
cursor: pointer;
}
</style>

View File

@ -4,6 +4,19 @@
<template #content> <template #content>
<span class="text-large font-600 mr-3"> {{ set }} : {{ book }} ({{ id }}) </span> <span class="text-large font-600 mr-3"> {{ set }} : {{ book }} ({{ id }}) </span>
</template> </template>
<template #extra>
<el-dropdown trigger="click">
<el-button>
操作<box-icon color="var(--text-color)" name='chevron-down' size="20px"></box-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-menu>
</template>
</el-dropdown>
</template>
</el-page-header> </el-page-header>
<div class="colbox" id="main"> <div class="colbox" id="main">
<div style="flex-grow: 1;" class="card"> <div style="flex-grow: 1;" class="card">
@ -19,6 +32,8 @@
</template> </template>
<script> <script>
import { ElMessage } from 'element-plus';
export default { export default {
name: "NoteEditor", name: "NoteEditor",
data() { data() {
@ -26,10 +41,17 @@ export default {
table: [], table: [],
} }
}, },
methods:{
download(){
this.$store.state.wordsets.fromArray(this.table,this.book,this.name);
ElMessage("下载完毕");
}
},
created() { created() {
this.set = this.$route.query.set; this.set = this.$route.query.set;
this.book = this.$route.query.book; this.book = this.$route.query.book;
this.id = this.$route.query.id; this.id = this.$route.query.id;
this.name = this.$route.query.name || "default";
if (this.set && this.book && this.id) { if (this.set && this.book && this.id) {
this.$axios.get("wordset/detail", { this.$axios.get("wordset/detail", {
params:{ params:{

View File

@ -4,12 +4,28 @@
<template #content> <template #content>
<span class="text-large font-600 mr-3"> {{ name }} ({{ id }}) </span> <span class="text-large font-600 mr-3"> {{ name }} ({{ id }}) </span>
</template> </template>
<template #extra>
<el-dropdown trigger="click">
<el-button>
操作<box-icon color="var(--text-color)" name='chevron-down' size="20px"></box-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="del_set"><box-icon color="var(--text-color)" name='trash'
size="20px"></box-icon></el-dropdown-item>
<el-dropdown-item @click="addTo"><box-icon color="var(--text-color)" name='plus'
size="18px"></box-icon></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-page-header> </el-page-header>
<div class="colbox" id="main"> <div class="colbox" id="main">
<div class="rowbox"> <div class="rowbox">
<div class="card"> <div class="card">
<div class="title">添加单词</div> <div class="title">添加单词</div>
<el-input ref="input1" autofocus @change="focusnext($refs.input2)" v-model="new_word.word"></el-input> <el-input ref="input1" autofocus @change="focusnext($refs.input2)"
v-model="new_word.word"></el-input>
<div class="colbox"> <div class="colbox">
<el-text class="mx-1" style="width: 60px;">翻译:</el-text> <el-text class="mx-1" style="width: 60px;">翻译:</el-text>
<el-input ref="input2" @change="focusnext($refs.input3)" v-model="new_word.trans"></el-input> <el-input ref="input2" @change="focusnext($refs.input3)" v-model="new_word.trans"></el-input>
@ -17,7 +33,8 @@
<div class="colbox"> <div class="colbox">
<el-text class="mx-1" style="width: 80px;">词性</el-text> <el-text class="mx-1" style="width: 80px;">词性</el-text>
<el-select ref="input3" v-model="new_word.type" class="m-2" placeholder="Select"> <el-select ref="input3" v-model="new_word.type" class="m-2" placeholder="Select">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in options" :key="item.value" :label="item.label"
:value="item.value" />
</el-select> </el-select>
</div> </div>
<el-button @click="add_word()" type="primary">添加</el-button> <el-button @click="add_word()" type="primary">添加</el-button>
@ -51,7 +68,8 @@
</div> </div>
</div> </div>
</div> </div>
<el-dialog v-model="word_editing" width="80%"> <CDialog v-model:visible="word_editing">
<template #content>
<div class="title">修改单词</div> <div class="title">修改单词</div>
<el-input v-model="editing_word.word"></el-input> <el-input v-model="editing_word.word"></el-input>
<div class="colbox"> <div class="colbox">
@ -65,14 +83,39 @@
</el-select> </el-select>
</div> </div>
<el-button @click="save_word" type="primary">更改</el-button> <el-button @click="save_word" type="primary">更改</el-button>
</el-dialog> </template>
</CDialog>
<CDialog v-model:visible="select.visible">
<template #content>
<el-text class="mx-1 title">选择加入的单词本</el-text>
<div class="colbox para">
<div class="mid-text">分组:</div>
<el-select v-model="select.set_class" class="m-2" placeholder="Select">
<el-option v-for="item in $store.state.wordsets._allclass" :key="item" :label="item"
:value="item" />
</el-select>
</div>
<div class="colbox para">
<div class="mid-text">单词本:</div>
<el-select v-model="select.id" class="m-2" placeholder="Select">
<el-option v-for="item in $store.state.wordsets.getClass(select.set_class)" :key="item.id"
:label="item.name" :value="item.id" />
</el-select>
</div>
<el-button @click="select.confirm(select.id)" type="primary">确认</el-button>
</template>
</CDialog>
</template> </template>
<script> <script>
import { ElMessage } from 'element-plus'; import { ElMessage, ElMessageBox } from 'element-plus';
import CDialog from '../UI/CDialog.vue'
export default { export default {
name: "NoteEditor", name: "NoteEditor",
components: {
CDialog
},
data() { data() {
return { return {
new_word: { new_word: {
@ -91,8 +134,13 @@ export default {
word_editing: false, word_editing: false,
new_name: "", new_name: "",
name: "", name: "",
id: "",
select: {
visible: false,
set_class: "",
id: "" id: ""
} }
}
}, },
methods: { methods: {
focusnext(node) { focusnext(node) {
@ -169,7 +217,29 @@ export default {
type: 'warning', type: 'warning',
}); });
}, },
del_set() {
ElMessageBox.confirm("确定要删除吗?")
.then(() => {
let index = this.$store.state.wordsets.getId(this.class_name, this.id);
this.$store.state.wordsets.delSet(this.class_name, index);
ElMessage(`已经删除 ${this.class_name} ${this.id}`);
this.$router.push("/manage");
});
},
addTo() {
this.select.visible = true;
this.select.confirm = (dest_id) => {
if (this.id) {
if(this.id != dest_id){
let failed = this.$store.state.wordsets.addSetTo(this.id, dest_id);
ElMessage(`已经添加到 ${dest_id}, 已经去除 ${failed} 个重复单词`);
}
else ElMessage(`请选择一个不同的单词本`);
}
this.select.visible = false;
}
},
}, },
created() { created() {
this.class_name = this.$route.query.classname; this.class_name = this.$route.query.classname;

View File

@ -6,15 +6,24 @@
<span class="text-large font-600 mr-3"> 编辑单词本 </span> <span class="text-large font-600 mr-3"> 编辑单词本 </span>
</template> </template>
<template #extra> <template #extra>
<div class="pconly"> <div>
<el-button @click="manage_online_wordsets" type="primary"><box-icon color="white" name='world' <el-button @click="$router.push('/manage/new')" type="success"><box-icon color="white"
size="20px"></box-icon>线</el-button>
<el-button @click="export_set" type="success"><box-icon color="white" name='export'
size="18px"></box-icon></el-button>
<el-button @click="import_set" type="warning"><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> name='plus'></box-icon></el-button>
<el-dropdown trigger="click" class="pconly" style="margin-left: 20px;">
<el-button type="primary">
更多<box-icon color="white" name='chevron-down' size="20px"></box-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="manage_online_wordsets"><box-icon color="white"
name='world' size="20px"></box-icon>线</el-dropdown-item>
<el-dropdown-item @click="export_set"><box-icon color="white" name='export'
size="18px"></box-icon></el-dropdown-item>
<el-dropdown-item @click="import_set"><box-icon color="white" name='import'
size="18px"></box-icon></el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div> </div>
</template> </template>
</el-page-header> </el-page-header>
@ -45,7 +54,8 @@
<el-main id="wordsets-container"> <el-main id="wordsets-container">
<div id="sets-container"> <div id="sets-container">
<div v-if="mode === 0" class="colbox wordclass"> <div v-if="mode === 0" class="colbox wordclass">
<div v-for="(wordset, index) in $store.state.wordsets.getClass(view_wordsets)" :key="index" class="wordset rowbox"> <div v-for="(wordset, index) in $store.state.wordsets.getClass(view_wordsets)" :key="index"
class="wordset rowbox">
<div class="no"> <div class="no">
{{ index + 1 }} {{ index + 1 }}
</div> </div>
@ -73,7 +83,8 @@
创建日期{{ (new Date(wordset.created)).toLocaleString() }} 创建日期{{ (new Date(wordset.created)).toLocaleString() }}
</div> </div>
<div class="option"> <div class="option">
<box-icon class="btn" name='show' color="var(--text-color)" @click="show(index)"></box-icon> <box-icon class="btn" name='show' color="var(--text-color)"
@click="show(index,wordset.name)"></box-icon>
</div> </div>
</div> </div>
</div> </div>
@ -137,10 +148,10 @@ export default {
query: { id, classname: this.view_wordsets } query: { id, classname: this.view_wordsets }
}) })
}, },
show(id) { show(id,name) {
this.$router.push({ this.$router.push({
path: "./manage/show", path: "./manage/show",
query: { set: this.viewing.set, book: this.viewing.book, id } query: { set: this.viewing.set, book: this.viewing.book, id,name }
}) })
}, },
async export_set() { async export_set() {

View File

@ -41,6 +41,14 @@ export default class _wordset {
} }
return null; return null;
} }
getId(class_name,id){
let set_class = this.sets[class_name];
for(let index in set_class){
if(set_class[index].id === id){
return index;
}
}
}
getSet(id) { getSet(id) {
let sets = JSON.parse(localStorage.getItem(id)); let sets = JSON.parse(localStorage.getItem(id));
if (sets) { if (sets) {
@ -76,7 +84,7 @@ export default class _wordset {
}); });
localStorage.setItem(id, JSON.stringify([])); localStorage.setItem(id, JSON.stringify([]));
this.save(); this.save();
return; return id;
} }
saveSet(id,data){ saveSet(id,data){
localStorage.setItem(id, JSON.stringify(data)); localStorage.setItem(id, JSON.stringify(data));
@ -93,6 +101,24 @@ export default class _wordset {
} }
} }
} }
addSetTo(origin_id,dest_id){
let origin_set = this.getSet(origin_id);
let dest_set = this.getSet(dest_id);
let set={};
origin_set.forEach(element => {
set[element.word] = element;
});
dest_set.forEach(element => {
set[element.word] = element;
});
set = Object.values(set);
this.saveSet(dest_id,set);
return origin_set.length + dest_set.length - set.length;
}
fromArray(arr,class_name,name){
let id = this.addSet(class_name,name);
this.saveSet(id,arr);
}
async import_set(callback){ async import_set(callback){
let [fileHandle] = await window.showOpenFilePicker({ let [fileHandle] = await window.showOpenFilePicker({
types: [ types: [

View File

@ -0,0 +1,53 @@
import {
ElForm,
ElButton,
ElInput,
ElCheckbox,
ElDialog,
ElTable,
ElStep,
ElLink,
ElCard,
ElCheckboxGroup,
ElDropdown,
ElFooter,
ElMain,
ElContainer,
ElHeader,
ElPageHeader,
ElTabs,
ElTabPane,
ElSteps,
ElSwitch,
ElSelect,
ElOption,
} from 'element-plus'
const element = {
install: function(app) {
app.use(ElForm)
app.use(ElButton)
app.use(ElInput)
app.use(ElCheckbox)
app.use(ElDialog)
app.use(ElTable)
app.use(ElStep)
app.use(ElLink)
app.use(ElCard)
app.use(ElCheckboxGroup)
app.use(ElDropdown)
app.use(ElFooter)
app.use(ElMain)
app.use(ElContainer)
app.use(ElHeader)
app.use(ElPageHeader)
app.use(ElTabPane)
app.use(ElSteps)
app.use(ElTabs)
app.use(ElSwitch)
app.use(ElSelect)
app.use(ElOption)
}
}
export default element

View File

@ -1,7 +1,8 @@
import {createApp} from 'vue' import {createApp} from 'vue'
import App from './App.vue' import App from './App.vue'
import { createStore } from 'vuex' import { createStore } from 'vuex'
import ElementPlus from 'element-plus' // import ElementPlus from 'element-plus'
import element from './loader/el-loader'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css' import 'element-plus/theme-chalk/dark/css-vars.css'
import 'boxicons' import 'boxicons'
@ -14,7 +15,7 @@ const store = createStore({
} }
}); });
app.use(store); app.use(store);
app.use(ElementPlus); app.use(element);
app.use(router); app.use(router);
app.config.globalProperties.$axios = axios; app.config.globalProperties.$axios = axios;
app.mount('#app'); app.mount('#app');

View File

@ -4,7 +4,7 @@ module.exports = defineConfig({
transpileDependencies: true, transpileDependencies: true,
publicPath:"./", publicPath:"./",
devServer: { devServer: {
proxy: 'https://localhost:443' proxy: 'https://app.cast1e.top/wordin'
}, },
chainWebpack: config => { chainWebpack: config => {
config.module config.module