Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/the guardian support #90

Merged
merged 4 commits into from
Feb 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
{
"files.autoSave": "afterDelay",
"editor.bracketPairColorization.independentColorPoolPerBracketType": true
"editor.bracketPairColorization.independentColorPoolPerBracketType": true,
"cSpell.words": [
"dsense",
"FUIYOH",
"HIYAA",
"thisweek",
"usersetting",
"wordgroup",
"wordlist"
]
}
11 changes: 0 additions & 11 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,18 @@ declare module 'vue' {
export interface GlobalComponents {
ElAffix: typeof import('element-plus/es')['ElAffix']
ElBacktop: typeof import('element-plus/es')['ElBacktop']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCol: typeof import('element-plus/es')['ElCol']
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
ElOption: typeof import('element-plus/es')['ElOption']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRow: typeof import('element-plus/es')['ElRow']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
Header: typeof import('./src/components/Header.vue')['default']
IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']
IconDocumentation: typeof import('./src/components/icons/IconDocumentation.vue')['default']
Expand Down
10 changes: 10 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ const router = createRouter({
name: 'register',
component: () => import('@/views/UserRegister.vue'),
},
{
path: '/reading',
name: 'reading',
component: () => import('@/views/ReadingArticle.vue'),
},
{
path: '/reading/:articleID',
name: 'readingDetail',
component: () => import('@/views/ReadingArticleDetail.vue'),
},
{
path: '/review/word/:groupID',
name: 'reviewWord',
Expand Down
2 changes: 1 addition & 1 deletion src/utils/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function createRequest(service: AxiosInstance) {
Authorization: token ? `Bearer ${token}` : '',
'Content-Type': 'application/json',
},
timeout: 10000,
timeout: 100000,
baseURL: import.meta.env.VITE_BASE_API,
data: {},
};
Expand Down
39 changes: 33 additions & 6 deletions src/views/HomePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,20 @@

<el-row justify="space-around">
<el-col :span="11">
<el-card class="cursor-pointer text-center" shadow-sm="always" @click="redirect('group-manage')"
<el-card
class="cursor-pointer text-center hover:bg-pink-500 hover:text-white"
shadow="always"
@click="redirect('group-manage')"
>我的词组</el-card
>
</el-col>
<el-col :span="11">
<el-card class="cursor-pointer text-center" shadow-sm="always" @click="redirect('today')">
今日收藏
<el-card
class="cursor-pointer text-center hover:bg-pink-500 hover:text-white"
shadow="always"
@click="redirect('recite')"
>
单词背诵
</el-card>
</el-col>
</el-row>
Expand All @@ -61,12 +68,31 @@
</el-row> -->
<el-row justify="space-around" style="margin-top: 15px">
<el-col :span="11">
<el-card class="cursor-pointer text-center" shadow-sm="always" @click="redirect('feedback')"
<el-card
class="cursor-pointer text-center hover:bg-pink-500 hover:text-white"
shadow="always"
@click="redirect('reading')"
>阅读理解</el-card
>
</el-col>
<el-col :span="11">
<el-card class="cursor-not-allowed text-center" shadow="always">即将开放 </el-card>
</el-col>
</el-row>
<el-row justify="space-around" style="margin-top: 15px">
<el-col :span="11">
<el-card
class="hover:bg-pink-500 hover:text-white cursor-pointer text-center"
shadow="always"
@click="redirect('feedback')"
>反馈建议</el-card
>
</el-col>
<el-col :span="11">
<el-card class="cursor-pointer text-center" shadow-sm="always" @click="redirect('settings')"
<el-card
class="hover:bg-pink-500 hover:text-white cursor-pointer text-center"
shadow="always"
@click="redirect('settings')"
>用户设置</el-card
>
</el-col>
Expand Down Expand Up @@ -135,7 +161,7 @@ function createCollectionChart() {
const dom = document.getElementById('collection');

if (dom) {
const chart = new Chart('collection', {
new Chart('collection', {
type: 'bar',
data: {
labels: everyDayWordCount.value.map(row => row.year),
Expand Down Expand Up @@ -176,6 +202,7 @@ function redirect(condition: string) {
if (condition === 'settings') router.push('/settings');
if (condition === 'help') router.push('/help');
if (condition === 'square') router.push('/square');
if (condition === 'reading') router.push('/reading');
if (condition === 'today') router.push('/today');
}

Expand Down
77 changes: 77 additions & 0 deletions src/views/ReadingArticle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<template>
<Header :title="'Reading Article'" @go-back="handleGoBack" />
<div class="px-3 py-2" v-if="articleList.length > 0">
<span
@click="handleGenerateAllQuestionsAnswers"
class="px-2 py-1 bg-cyan-400 select-none cursor-pointer active:shadow-sm active:shadow-cyan-600 rounded"
>一键生成</span
>
<div v-for="article in articleList" :key="article._id">
<div class="my-3 font-bold text-lg">{{ article._id }}</div>
<div
@click="handleGoToArticleDetail(i._id)"
class="px-1 py-2 bg-slate-50 mb-2 cursor-pointer"
v-for="i in article.documents"
:key="i"
>
<div @click.stop class="cursor-auto">{{ i.title }}</div>
<div class="flex items-center" v-if="i.questions">
<div class="h-2 w-5 bg-green-300"></div>
<div class="ml-1"><span>问题已生成</span></div>
</div>
<div class="flex items-center" v-else>
<div class="h-2 w-5 bg-red-500"></div>
<div class="ml-1"><span>问题未生成</span></div>
</div>
</div>
</div>
</div>
<el-empty description="暂无数据,请访问The Guardian网站,阅读新闻,系统会自动添加。" v-else />
</template>

<script setup lang="ts">
import Header from '@/components/Header.vue';
import { request } from '@/utils/service';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';

const router = useRouter();

const articleList = ref([]);

async function handleGenerateAllQuestionsAnswers() {
let availableList = [];

articleList.value.forEach(article => {
article.documents.forEach(doc => {
if (!doc.questions) {
availableList.push(doc._id);
}
});
});

console.log(availableList);
for (let i = 0; i < availableList.length; i++) {
const r = await request({ url: '/deepseek', method: 'post', data: { articleId: availableList[i] } });
console.log(r);
}
}

function handleGoToArticleDetail(id) {
router.push(`/reading/${id}`);
}

async function getGuardianArticles() {
const r = await request({ url: '/article/guardian' });
console.log(r);
articleList.value = r.data;
}

function handleGoBack() {
router.go(-1);
}

onMounted(() => {
getGuardianArticles();
});
</script>
95 changes: 95 additions & 0 deletions src/views/ReadingArticleDetail.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<template>
<Header :title="'Reading Article Detail'" @go-back="handleGoBack" />
<div class="px-3 py-3 bg-slate-50">
<h1 class="text-center text-xl font-bold">{{ articleDetail.title }}</h1>
<div class="mx-2 flex gap-2 my-5 text-slate-500">
<div class="bg-cyan-500 h-full w-1">&nbsp;</div>
<div>{{ articleDetail.summary }}</div>
</div>
<div>
<p class="text-lg mx-2 my-4" v-for="pp in articleDetail.content" :key="pp">{{ pp }}</p>
</div>
<div class="flex gap-2 items-center">
<a class="px-2 py-1 bg-cyan-500 cursor-pointer round rounded text-white" @click="handleOriginalUrl"
>原文链接</a
>
<div
@click="generateQuestions"
class="cursor-pointer active:shadow active:shadow-slate-400 px-2 py-1 bg-pink-500 rounded text-white"
>
生成问题
</div>
<div
@click="displayAnswers"
class="cursor-pointer active:shadow active:shadow-slate-400 px-2 py-1 bg-pink-500 rounded text-white"
>
查看答案
</div>
<div
@click="refreshPage"
class="cursor-pointer active:shadow active:shadow-slate-400 px-2 py-1 bg-pink-500 rounded text-white"
>
刷新页面
</div>
</div>
<div class="mt-16">
<div class="font-bold">Questions:</div>
<p class="whitespace-pre-wrap">{{ articleDetail.questions }}</p>
</div>
<div class="mt-16" v-if="isAnswersVisible">
<div class="font-bold">Answers:</div>
<p class="whitespace-pre-wrap">{{ articleDetail.answers }}</p>
</div>
</div>
</template>
<script setup lang="ts">
import Header from '@/components/Header.vue';
import { request } from '@/utils/service';
import { ElNotification } from 'element-plus';
import { onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';

const router = useRouter();
const route = useRoute();
const articleDetail = ref({});
const isAnswersVisible = ref(false);

function refreshPage(){
window.location.reload();
}

function displayAnswers() {
isAnswersVisible.value = !isAnswersVisible.value;
}

function handleOriginalUrl() {
window.open(articleDetail.value.originalUrl);
}

function handleGoBack() {
router.go(-1);
}

async function getArticleDetail(id) {
const r = await request({ url: '/article/guardian/' + id });
console.log(r);
return r;
}

async function generateQuestions() {
const r = await request({ url: '/deepseek', method: 'post', data: { articleId: articleDetail.value._id } });
console.log(r);
if (r.code === 200) {
ElNotification({ type: 'success', title: '问题已生成' });
} else {
ElNotification({ type: 'error', title: '问题生成失败,请重试' });
}
}

onMounted(async () => {
const id = route.params.articleID;
console.log(id);
const t = await getArticleDetail(id);
articleDetail.value = t.data;
});
</script>
30 changes: 15 additions & 15 deletions src/views/RecordWord.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@
<div>
<el-select style="width: 180px" v-model="defaultGroup">
<el-option value="" label=""></el-option>
<el-option v-for="group in groupList" :value="group._id" :label="group.name"></el-option>
<el-option
v-for="group in groupList"
:value="group._id"
:label="group.name"
:key="group.name"
></el-option>
</el-select>
</div>
<div><el-button type="warning" @click="playAudio(form.englishName)">&nbsp;Audio&nbsp;</el-button></div>
Expand All @@ -34,27 +39,32 @@
:title="`${card.name} - ${card.property} - ${card.phonetic}`"
:name="index"
v-for="(card, index) in cardList"
:key="index"
>
<div class="collapse-header">{{ card.property }} {{ card.phonetic }}</div>
<template v-for="dsenseObj in card.dsenseObjList">
<el-card style="margin-bottom: 15px" v-for="dsense in dsenseObj.defBlockObjList">
<el-card style="margin-bottom: 15px" v-for="dsense in dsenseObj.defBlockObjList" :key="dsense.en">
<template #header>
<div class="dsense-title-container">{{ dsense.en }}</div>
<div class="dsense-title-container">{{ dsense.zh }}</div>
</template>
<div>
<div v-for="sentence in dsense.sentence">
<div v-for="sentence in dsense.sentence" :key="sentence">
{{ sentence }}
</div>
</div>
</el-card>
<el-card style="margin-bottom: 15px" v-for="dsense in dsenseObj.phraseBlockObjList">
<el-card
style="margin-bottom: 15px"
v-for="dsense in dsenseObj.phraseBlockObjList"
:key="dsense.en"
>
<template #header>
<div class="dsense-title-container">{{ dsense.en }}</div>
<div class="dsense-title-container">{{ dsense.zh }}</div>
</template>
<div>
<div v-for="sentence in dsense.sentence">
<div v-for="sentence in dsense.sentence" :key="sentence">
{{ sentence }}
</div>
</div>
Expand Down Expand Up @@ -98,10 +108,8 @@ interface WDL {
// #region variable
let timer = ref(null);
const grabWordInput = ref(null);
let groupID = ref('');
const router = useRouter();
let activeNames = ref([]);
let wordDescription: Ref<WD>;
let audioUrl = ref('https://dict.youdao.com/dictvoice?type=1&audio=');
let originUrl = ref('https://dict.youdao.com/dictvoice?type=1&audio=');
const form: Ref<WDL> = ref({
Expand Down Expand Up @@ -134,14 +142,6 @@ onMounted(() => {
}
}, 1200);
});
wordDescription = ref({
englishDescription: '',
partOfSpeech: '',
level: '',
chineseDescription: '',
sentence: '',
group: '',
});
getDefaultGroup();
getGroupList();
});
Expand Down