Merge pull request #173 from zyronon/dev

feat:add feedback link & migrate notice
This commit is contained in:
Zyronon
2025-11-25 16:54:12 +08:00
committed by GitHub
5 changed files with 102 additions and 88 deletions

View File

@@ -82,7 +82,6 @@ async function transfer() {
Toast.success('迁移完成')
model.value = false
emit('ok')
} catch (e) {
Toast.error('迁移失败:' + e)
console.error('迁移失败', e);
@@ -91,21 +90,21 @@ async function transfer() {
</script>
<template>
<Dialog v-model="model" title="迁移数据">
<div class="px-4 flex-col center text-align-center w-100">
<h2>
<Dialog v-model="model"
:footer="true"
@ok="transfer"
confirmButtonText="迁移数据"
title="迁移数据">
<div class="px-4 flex-col center w-100">
<h2 class="text-align-center">
本网站已启用新域名 <span class="color-blue">{{ Origin }}</span>
</h2>
<h3>
老域名即将停用由于浏览器安全限制新老网站数据无法互通需要您手动点击转移数据
</h3>
<h3>
<BaseButton
size="large"
@click="transfer">
转移数据
</BaseButton>
</h3>
<div>
如果您不想此时迁移关闭弹窗后您可随时在设置 -> 数据管理 里面再次进行
</div>
</div>
</Dialog>
</template>

View File

@@ -18,7 +18,7 @@ import dayjs from "dayjs";
import isBetween from "dayjs/plugin/isBetween";
import isoWeek from 'dayjs/plugin/isoWeek'
import { useFetch } from "@vueuse/core";
import { AppEnv, DICT_LIST, PracticeSaveArticleKey } from "@/config/env.ts";
import {AppEnv, DICT_LIST, Host, PracticeSaveArticleKey} from "@/config/env.ts";
import { myDictList } from "@/apis";
dayjs.extend(isoWeek)
@@ -162,11 +162,16 @@ const weekList = $computed(() => {
const {data: recommendBookList, isFetching} = useFetch(resourceWrap(DICT_LIST.ARTICLE.RECOMMENDED)).json()
let isNewHost = $ref(window.location.host === Host)
</script>
<template>
<BasePage>
<div class="mb-4" v-if="!isNewHost">
新域名已启用后续请访问 <a href="https://typewords.cc/words?from_old_site=1">https://typewords.cc</a>。当前 2study.top 域名将在不久后停止使用
</div>
<div class="card flex flex-col md:flex-row justify-between gap-space p-4 md:p-6">
<div class="">
<Book

View File

@@ -17,6 +17,9 @@ const {toggleTheme, getTheme} = useTheme()
function goHome() {
window.location.href = '/';
}
function goFeedback() {
window.open('https://v.wjx.cn/vm/ev0W7fv.aspx#', '_blank');
}
</script>
<template>
@@ -44,6 +47,10 @@ function goHome() {
<span v-if="settingStore.sideExpand">设置</span>
<div class="red-point" :class="!settingStore.sideExpand && 'top-1 right-0'" v-if="runtimeStore.isNew"></div>
</div>
<div class="row" @click="goFeedback">
<IconFluentCommentEdit20Regular/>
<span v-if="settingStore.sideExpand">建议反馈</span>
</div>
<!-- <div class="row" @click="router.push('/user')">-->
<!-- <IconFluentPerson20Regular/>-->
<!-- <span v-if="settingStore.sideExpand">用户</span>-->

View File

@@ -1,17 +1,17 @@
<script setup lang="ts">
import { nextTick, ref, watch } from "vue";
import { useSettingStore } from "@/stores/setting.ts";
import { getAudioFileUrl, usePlayAudio } from "@/hooks/sound.ts";
import { getShortcutKey, useEventListener } from "@/hooks/event.ts";
import { checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, cloneDeep, loadJsLib, shakeCommonDict } from "@/utils";
import { DefaultShortcutKeyMap, ShortcutKey, WordPracticeMode } from "@/types/types.ts";
import {nextTick, onMounted, ref, watch} from "vue";
import {useSettingStore} from "@/stores/setting.ts";
import {getAudioFileUrl, usePlayAudio} from "@/hooks/sound.ts";
import {getShortcutKey, useEventListener} from "@/hooks/event.ts";
import {checkAndUpgradeSaveDict, checkAndUpgradeSaveSetting, cloneDeep, loadJsLib, shakeCommonDict} from "@/utils";
import {DefaultShortcutKeyMap, ShortcutKey, WordPracticeMode} from "@/types/types.ts";
import BaseButton from "@/components/BaseButton.vue";
import VolumeIcon from "@/components/icon/VolumeIcon.vue";
import { useBaseStore } from "@/stores/base.ts";
import { saveAs } from "file-saver";
import {useBaseStore} from "@/stores/base.ts";
import {saveAs} from "file-saver";
import {
APP_NAME, APP_VERSION, EMAIL,
EXPORT_DATA_KEY, GITHUB,
EXPORT_DATA_KEY, GITHUB, Host,
LOCAL_FILE_KEY,
Origin,
PracticeSaveArticleKey,
@@ -20,7 +20,7 @@ import {
import dayjs from "dayjs";
import BasePage from "@/components/BasePage.vue";
import Toast from '@/components/base/toast/Toast.ts'
import { Option, Select } from "@/components/base/select";
import {Option, Select} from "@/components/base/select";
import Switch from "@/components/base/Switch.vue";
import Slider from "@/components/base/Slider.vue";
import RadioGroup from "@/components/base/radio/RadioGroup.vue";
@@ -29,10 +29,11 @@ import InputNumber from "@/components/base/InputNumber.vue";
import PopConfirm from "@/components/PopConfirm.vue";
import Textarea from "@/components/base/Textarea.vue";
import SettingItem from "@/pages/setting/SettingItem.vue";
import { get, set } from "idb-keyval";
import { useRuntimeStore } from "@/stores/runtime.ts";
import { useUserStore } from "@/stores/user.ts";
import { useExport } from "@/hooks/export.ts";
import {get, set} from "idb-keyval";
import {useRuntimeStore} from "@/stores/runtime.ts";
import {useUserStore} from "@/stores/user.ts";
import {useExport} from "@/hooks/export.ts";
import MigrateDialog from "@/components/MigrateDialog.vue";
const emit = defineEmits<{
toggleDisabledDialogEscKey: [val: boolean]
@@ -42,7 +43,6 @@ const tabIndex = $ref(0)
const settingStore = useSettingStore()
const runtimeStore = useRuntimeStore()
const store = useBaseStore()
const userStore = useUserStore()
//@ts-ignore
const gitLastCommitHash = ref(LATEST_COMMIT_HASH);
@@ -99,7 +99,7 @@ useEventListener('keydown', (e: KeyboardEvent) => {
} else {
// 忽略单独的修饰键
if (shortcutKey === 'Ctrl+' || shortcutKey === 'Alt+' || shortcutKey === 'Shift+' ||
e.key === 'Control' || e.key === 'Alt' || e.key === 'Shift') {
e.key === 'Control' || e.key === 'Alt' || e.key === 'Shift') {
return;
}
@@ -300,6 +300,15 @@ function importOldData() {
}
}, 1000)
}
let isNewHost = $ref(window.location.host === Host)
let showTransfer = $ref(false)
function transferOk() {
setTimeout(() => {
window.location.href = '/words'
}, 1500)
}
</script>
<template>
@@ -372,8 +381,8 @@ function importOldData() {
v-if="settingStore.ignoreSimpleWord"
>
<Textarea
placeholder="多个单词用英文逗号隔号"
v-model="simpleWords" :autosize="{minRows: 6, maxRows: 10}"/>
placeholder="多个单词用英文逗号隔号"
v-model="simpleWords" :autosize="{minRows: 6, maxRows: 10}"/>
</SettingItem>
<!-- 音效-->
@@ -401,16 +410,16 @@ function importOldData() {
class="w-50!"
>
<Option
v-for="item in SoundFileOptions"
:key="item.value"
:label="item.label"
:value="item.value"
v-for="item in SoundFileOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
<div class="flex justify-between items-center w-full">
<span>{{ item.label }}</span>
<VolumeIcon
:time="100"
@click="usePlayAudio(getAudioFileUrl(item.value)[0])"/>
:time="100"
@click="usePlayAudio(getAudioFileUrl(item.value)[0])"/>
</div>
</Option>
</Select>
@@ -528,16 +537,16 @@ function importOldData() {
<SettingItem mainTitle="字体设置"/>
<SettingItem title="外语字体">
<Slider
:min="10"
:max="100"
v-model="settingStore.fontSize.wordForeignFontSize"/>
:min="10"
:max="100"
v-model="settingStore.fontSize.wordForeignFontSize"/>
<span class="w-10 pl-5">{{ settingStore.fontSize.wordForeignFontSize }}px</span>
</SettingItem>
<SettingItem title="中文字体">
<Slider
:min="10"
:max="100"
v-model="settingStore.fontSize.wordTranslateFontSize"/>
:min="10"
:max="100"
v-model="settingStore.fontSize.wordTranslateFontSize"/>
<span class="w-10 pl-5">{{ settingStore.fontSize.wordTranslateFontSize }}px</span>
</SettingItem>
</div>
@@ -550,7 +559,6 @@ function importOldData() {
<!-- 发音-->
<!-- 发音-->
<!-- 发音-->
<div class="line"></div>
<SettingItem mainTitle="音效"/>
<SettingItem title="自动播放句子">
<Switch v-model="settingStore.articleSound"/>
@@ -586,7 +594,7 @@ function importOldData() {
<input ref="shortcutInput" :value="item[1]?item[1]:'未设置快捷键'" readonly type="text"
@blur="handleInputBlur">
<span @click.stop="editShortcutKey = ''">按键盘进行设置<span
class="text-red!">设置完成点击这里</span></span>
class="text-red!">设置完成点击这里</span></span>
</div>
<div v-else>
<div v-if="item[1]">{{ item[1] }}</div>
@@ -623,11 +631,20 @@ function importOldData() {
@change="importData">
</div>
<PopConfirm
title="导入老版本数据前,请先备份当前数据,确定要导入老版本数据吗?"
@confirm="importOldData">
title="导入老版本数据前,请先备份当前数据,确定要导入老版本数据吗?"
@confirm="importOldData">
<BaseButton>老版本数据导入</BaseButton>
</PopConfirm>
</div>
<template v-if="!isNewHost">
<div class="line my-3"></div>
<div>请注意如果本地已有使用记录请先备份当前数据迁移数据后将<b class="text-red"> 完全覆盖 </b>当前所有数据请谨慎操作
</div>
<div class="flex gap-space mt-3">
<BaseButton @click="showTransfer = true">迁移 2study.top 网站数据</BaseButton>
</div>
</template>
</div>
<div v-if="tabIndex === 5">
@@ -798,29 +815,6 @@ function importOldData() {
<div v-if="tabIndex === 6" class="center flex-col">
<h1>Type Words</h1>
<!-- 用户信息部分 -->
<div v-if="userStore.isLoggedIn && userStore.user" class="user-info-section mb-6">
<div class="user-avatar mb-4">
<img v-if="userStore.user.avatar" :src="userStore.user.avatar" alt="头像" class="avatar-img"/>
<div v-else class="avatar-placeholder">
{{ userStore.user.nickname?.charAt(0) || 'U' }}
</div>
</div>
<h3 class="mb-2">{{ userStore.user.nickname || '用户' }}</h3>
<p v-if="userStore.user.email" class="text-sm color-gray mb-1">{{ userStore.user.email }}</p>
<p v-if="userStore.user.phone" class="text-sm color-gray">{{ userStore.user.phone }}</p>
<BaseButton
@click="userStore.logout"
type="info"
class="mt-4"
:loading="userStore.isLoading"
>
退出登录
</BaseButton>
</div>
<p class="w-100 text-xl">
感谢使用本项目本项目是开源项目如果觉得有帮助请在 GitHub 点个 Star您的支持是我持续改进的动力
</p>
@@ -837,10 +831,14 @@ function importOldData() {
Build {{ gitLastCommitHash }}
</div>
</div>
</div>
</div>
</BasePage>
<MigrateDialog
v-model="showTransfer"
@ok="transferOk"
/>
</template>
<style scoped lang="scss">
@@ -1054,85 +1052,85 @@ function importOldData() {
@media (max-width: 768px) {
.setting {
flex-direction: column;
.left {
width: 100%;
border-right: none;
border-bottom: 2px solid gainsboro;
.tabs {
flex-direction: row;
overflow-x: auto;
padding: 0.5rem;
gap: 0.3rem;
.tab {
white-space: nowrap;
padding: 0.4rem 0.6rem;
font-size: 0.9rem;
span {
display: none;
}
}
}
}
.content {
padding: 0 1rem;
.row {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
min-height: auto;
padding: 0.5rem 0;
.wrapper {
width: 100%;
justify-content: flex-start;
.set-key {
width: 100%;
input {
width: 100%;
max-width: 200px;
}
}
// 补充:选择器和输入框优化
.base-select, .base-input {
width: 100% !important;
max-width: none;
}
// 单选按钮组优化
.radio-group {
flex-direction: column;
gap: 0.5rem;
.radio {
min-height: 44px;
width: 100%;
}
}
// 滑块优化
.slider {
width: 100%;
}
}
.main-title {
font-size: 1rem;
}
.item-title {
font-size: 0.9rem;
}
}
.body {
height: auto;
max-height: 60vh;

View File

@@ -19,7 +19,7 @@ import PracticeSettingDialog from "@/pages/word/components/PracticeSettingDialog
import ChangeLastPracticeIndexDialog from "@/pages/word/components/ChangeLastPracticeIndexDialog.vue";
import { useSettingStore } from "@/stores/setting.ts";
import { useFetch } from "@vueuse/core";
import { AppEnv, DICT_LIST, PracticeSaveWordKey } from "@/config/env.ts";
import {AppEnv, DICT_LIST, Host, PracticeSaveWordKey} from "@/config/env.ts";
import { myDictList } from "@/apis";
import PracticeWordListDialog from "@/pages/word/components/PracticeWordListDialog.vue";
import ShufflePracticeSettingDialog from "@/pages/word/components/ShufflePracticeSettingDialog.vue";
@@ -32,6 +32,7 @@ const {nav} = useNav()
const runtimeStore = useRuntimeStore()
let loading = $ref(true)
let isSaveData = $ref(false)
let currentStudy = $ref({
new: [],
review: [],
@@ -196,11 +197,15 @@ const {
isFetching
} = useFetch(resourceWrap(DICT_LIST.WORD.RECOMMENDED)).json()
let isNewHost = $ref(window.location.host === Host)
</script>
<template>
<BasePage>
<div class="mb-4" v-if="!isNewHost">
新域名已启用后续请访问 <a href="https://typewords.cc/words?from_old_site=1">https://typewords.cc</a>。当前 2study.top 域名将在不久后停止使用
</div>
<div class="card flex flex-col md:flex-row gap-8">
<div class="flex-1 w-full flex flex-col justify-between">
<div class="flex gap-3">