产品需求文档 (PRD) - 英语单词记忆应用

1. 引言 (Introduction)

1.1 文档目的

本文档旨在详细定义“英语单词记忆应用”的功能需求、非功能需求及相关规则,作为产品设计、开发、测试和后续迭代的主要依据,确保各方对产品有统一的理解和预期。

1.2 项目概述

本项目旨在开发一款移动应用程序,帮助用户高效、便捷地学习和复习英语单词。应用将提供多种学习模式(如闪卡、拼写),支持标准化词库(如考研词汇)和用户自定义词库(含生词本功能),并通过用户账户系统实现学习进度和数据的跨设备同步。此外,应用还将提供学习统计功能,帮助用户跟踪进展、保持动力。

1.3 目标用户

需要系统性背诵特定词库的学生(如备考四六级、考研、雅思、托福等)。
希望通过积累生词、自定义词汇列表来提升英语能力的普通学习者。
需要在碎片化时间进行单词学习和复习的用户。
希望通过量化数据跟踪自己学习进展的用户。

1.4 产品目标

核心目标: 提供高效、灵活的英语单词学习与复习工具。
用户价值: 帮助用户有效记忆单词,提升词汇量,达成学习目标。
产品体验: 提供简洁、流畅、易用的用户界面和交互体验。
数据驱动: 实现用户学习数据的安全存储、跨设备同步及可视化统计分析。

More...

用 MinIO 自建对象存储服务

对象存储服务

对象存储服务适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,比较著名的服务有 AWS 的 S3 服务。
MinIO 是一款基于Go语言的高性能对象存储服务,在Github上已有19K+Star。它采用了Apache License v2.0开源协议,本文将通过 Docker 搭建 MinIO 来自建一个对象存储服务。

安装

  • 下载MinIO的Docker镜像:

    1
    docker pull minio/minio
  • 创建数据卷

    1
    2
    docker volume create --driver local --opt device=C:\10.VM\minio\data --opt type=none --opt o=bind miniodata
    docker volume create --driver local --opt device=C:\10.VM\minio\config --opt type=none --opt o=bind minioconfig
  • 启动 docker

    1
    docker run -p 9090:9000 -p 9100:9001 --name minio -v miniodata:/data -v minioconfig:/root/.minio -d minio/minio server /data --console-address ":9001"
More...

可供练习的公开数据集

背景

最近想研究一下数据可视化在 AI 领域的应用,需要有一些数据进行练习,如果自己造的话,没有实际场景。搜索了一下,网上其实有现成的公开数据集,还挺方便,推荐一下,大家如果有需要,也可以去下载使用。

Maven

Maven 这个网址会列出公开的数据集,大家可以按自己的需求,下载相关数据。我下载的是 CRM Sales Opportunities :

More...

如何在 Next.js 应用中集成 Clerk Webhook 来同步用户信息

我们将使用 Clerk 提供的官方 @clerk/nextjs 库和 svix 库(Clerk 底层使用 svix 处理 webhooks)来验证传入的 webhook 请求。

核心思路

  1. 在 Clerk Dashboard 配置一个 Webhook Endpoint,指向你 Next.js 应用的一个特定 API 路由。
  2. 创建这个 Next.js API 路由。
  3. 在该 API 路由中:
    • 验证请求是否确实来自 Clerk(使用 Signing Secret)。
    • 解析 webhook 事件的类型和数据。
    • 根据事件类型(如 user.created, user.updated, user.deleted)执行相应的数据库操作或其他同步逻辑。
    • 向 Clerk 返回成功的响应,告知已收到并处理事件。
More...

React中如何拆分大组件

背景

项目中我发现一个 table 组件代码特别多,修改起来比较麻烦,想按模块化的思想进行拆分。

重构的核心思想:

  1. 分离职责 (Isolate Responsibilities): 每个组件应该只负责单一且明确定义的功能或目的。
  2. 数据流 (Data Flow): 将必要的数据和回调函数通过 props 向下传递。当状态与多个组件相关时,通常应将其存放在这些组件最近的共同父(祖先)组件中。
  3. 组件粒度 (Component Granularity): 为界面中不同的独立部分创建组件,例如搜索栏、表格的每一行、以及单个的单元格(特别是那些逻辑复杂的单元格)。
More...

如何设计幂等API

幂等的概念

幂等(idempotency)是一个设计稳定和健壮API的关键属性,特别是在分布式系统环境中,这些环境中,由于网络问题或者客户端重试等原因,相同的请求被发送多次是很常见的。一个幂等的API对于相同的请求,始终产生相同的结果,无论这个API被调用多少次。

如何设计幂等API

下面是设计幂等API的步骤:

1.使用唯一的请求ID

这个ID要满足:

  • 客户端提供:通常和推荐的做法是,对于客户端的请求,生成一个唯一ID(比如UUID),作为请求的一部分,放到Header或者其他地方。
  • 服务端跟踪:服务器应该储存每一个唯一请求ID的状态和请求的结果。
  • 请求顺序:当服务器收到请求后, 如果存在一个唯一请求ID相同的前请求:
    • 如果前请求已经成功执行完毕,服务器返回前请求的结果,不用重新执行请求;
    • 如果前请求已经失败,服务器返回前请求的错误结果并执行潜在的重试操作;
    • 如果前请求正在执行中,服务器可以等待前请求执行结束,然后根据执行结果返回结果。
      如果可以满足上述要求,我们可以定义它为幂等码

2.跟踪操作状态

More...

如何通过API抽取数据并存入数据库

通过 axios 调用API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const abcApi = env.CONTEST_API_URL;
const abcApiToken = env.CONTEST_API_TOKEN;

console.log(`${abcApi} start`);
const { data } = await axios.get(`${abcApi}/` , {
headers: {
Accept: 'application/json',
Authorization: `ApiKey ${abcApiToken}`
},
params: {
resource_id: 93,
limit: 700,
order_by: '-end',
},
});
return data.objects as ContestAPIType[];

其中 ContestAPIType 可以根据返回值定义。

More...

从零搭建基于 AI GitHub 分析平台 (17) 保存答案

添加 saveAnswer 函数

修改 src/server/api/routers/project.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
saveAnswer: authenticatedProcedure.input( z.object({
projectId: z.string(),
question: z.string(),
answer: z.string(),
fileReferences: z.any(),
})).mutation( async ( { ctx, input }) => {
return await ctx.db.question.create({
data: {
answer: input.answer,
fileReferences: input.fileReferences,
projectId: input.projectId,
question: input.question,
userId: ctx.user.userId!,
}
})
})

修改 AskQuestionCard 页面

修改 `src/app/(protected)/dashboard/AskQuestionCard.tsx’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import { api } from '@/trpc/react';
import { toast } from 'sonner';
...
const [ fileReferences, setFileReferences ] = useState<{ fileName :string, sourceCode: string, summary:string }[]>([])
const saveAnswer = api.project.saveAnswer.useMutation();
...
const onSubmit = async ( e: React.FormEvent<HTMLFormElement>) => {
setAnswer("");
setFileReferences([]);
e.preventDefault();
if(!project?.id) return;
setLoading(true);

const {output , fileReferences} = await askQuestion(question,project.id);
setFileReferences(fileReferences);
setAnswer(output);

}
...
<div className='flex items-center gap-2'>
<DialogTitle>
<Image src='/logo.png' alt='aigithub' width={40} height={40} />
</DialogTitle>
<Button disabled={saveAnswer.isPending} variant={'outline'} onClick={()=>{
saveAnswer.mutate({
projectId: project!.id,
question,
answer,
fileReferences
}, {
onSuccess: ()=>{
toast.success('答案保存成功')
},
onError: () => {
toast.error('答案保存错误');
}
})
}}>
保存答案
</Button>
</div>

作者:Bearalise
出处:从零搭建基于 AI GitHub 分析平台 (17) 保存答案
版权:本文版权归作者所有
转载:欢迎转载,但未经作者同意,必须保留此段声明,必须在文章中给出原文链接。

如何刷新 VS Code 中 Prisma 更新的表和字段

背景

当我更新 Prisma Schema 的时候,有时会出现即使通过 prisma db pushprisma generate 更新了数据库,也显示成功,但在 VS Code 中依然无法通过代码自动完成看到更新的字段,比较困扰,有时重新打开 VS Code 会好,有时不会

解决方案

原因主要是 VS Code 的缓存没有及时更新,查询后发现一个立即更新缓存的方法,就是在 VS Code 中,找到 node_modules/.prisma/client/index.d.ts ,并打开,这时 VS Code 就会自动更新缓存。我测试了一下有效,大家可以试试。

More...

请我喝杯咖啡吧~

支付宝
微信