从零开始:用 Android Studio 开发一个 AI 智能日记 App - 指南

news/2026/1/18 10:59:27/文章来源:https://www.cnblogs.com/yangykaifa/p/19497976

我最近完成了一个个人项目——一个能帮我整理日记的 Android App。整个开发过程踩了不少坑,也学到了很多东西。写这篇文章的目的,是想把我从完全不懂 Android 开发,到做出一个能用的 App 的过程记录下来,希望对同样想入门移动端开发的朋友有所帮助。

这不是一篇面面俱到的教科书,而是一个真实项目的开发笔记。我会尽量少讲理论,多讲实操,遇到什么问题就说什么问题。

一、先聊聊这个项目是干什么的
在开始写代码之前,我想先说说这个 App 要解决的问题。

我有记日记的习惯,但总是坚持不下去。原因很简单:每天晚上想起来今天发生了什么,脑子里一片空白。等想起来的时候,又懒得动笔(打字)。

后来我在 YouTube 上看到一个视频,博主用 iPhone 的快捷指令做了一个工作流:白天随时用语音记录零碎的想法(比如"今天中午吃的拉面不错"、“下午开会被老板骂了”),晚上让 AI 把这些碎片整理成一篇完整的日记。

这思路太妙了!但那个方案是 iOS 专属的,我用的是 Android。于是我决定自己做一个。

核心功能就三个:

随时记录碎片想法(语音或打字)
一键让 AI 整理成日记
顺便把日记里的待办事项提取出来
听起来不复杂对吧?但真正动手做的时候,你会发现需要学的东西还挺多。好,废话不多说,开始搞。

二、开发环境:Android Studio 的安装和配置
2.1 下载 Android Studio
去 Google 官网下载:https://developer.android.com/studio

下载下来是一个几百 MB 的安装包。Windows 用户直接双击 exe,Mac 用户拖到 Applications,Linux 用户解压后运行 studio.sh。

第一次启动会比较慢,因为它要下载 SDK、Gradle 之类的东西。建议挂个梯子,不然可能卡很久。

2.2 创建第一个项目
安装好之后,点 New Project,选择 Empty Activity(注意是 Compose 版本的,不是传统 View 版本)。

填几个信息:

Name: Journal(或者你喜欢的名字)
Package name: com.example.journal
Language: Kotlin(别选 Java,2024 年了)
Minimum SDK: API 26(Android 8.0)
点 Finish,等它 Sync 完成。第一次 Sync 会下载一堆依赖,可能要等几分钟。

2.3 跑起来看看
点击工具栏上的绿色三角形(Run),选择一个模拟器或者连接的真机。如果没有模拟器,去 Device Manager 创建一个。

看到屏幕上显示 “Hello Android!” 就说明环境没问题了。

小提示:真机调试比模拟器快很多。手机上打开「开发者选项」→「USB 调试」,用数据线连电脑就行。

三、项目结构:先搞清楚文件放哪里
打开项目,左边有一堆文件夹。别慌,常用的就这几个:

app/
├── src/main/
│ ├── java/com/example/journal/ # 写 Kotlin 代码的地方
│ ├── res/ # 资源文件(图片、字符串等)
│ └── AndroidManifest.xml # App 配置文件
├── build.gradle.kts # 这个模块的依赖配置
根目录还有个
build.gradle.kts
,是整个项目的配置。现在不用管它,后面加依赖的时候会用到。

四、Kotlin 速成:够用就行
Android 开发用的是 Kotlin 语言。如果你写过 Java、Python 或者 JavaScript,上手会很快。我挑几个最常用的语法讲一下。

4.1 变量
val name = “张三” // val 是常量,不能改
var age = 25 // var 是变量,可以改
age = 26 // OK
// name = “李四” // 报错!
4.2 函数
fun greet(name: String): String {
return “你好,KaTeX parse error: Expected 'EOF', got '}' at position 7: name" }̲ // 简写 fun gree…name”
4.3 数据类
这个特别好用,一行代码就能定义一个类,自动生成 equals、hashCode、toString:

data class Note(
val id: Long,
val content: String,
val timestamp: Long
)
4.4 空安全
Kotlin 最大的特点是变量默认不能为 null。如果可能为空,要加问号:

var title: String = “日记” // 不能为 null
var subtitle: String? = null // 可以为 null
// 访问可空变量
println(subtitle?.length) // 如果 subtitle 是 null,返回 null
println(subtitle ?: “无副标题”) // 如果 subtitle 是 null,返回默认值
4.5 Lambda
经常用来做回调:

button.setOnClickListener {
println(“按钮被点击了”)
}
// 带参数
list.filter { item -> item.length > 5 }
// 只有一个参数时可以用 it
list.filter { it.length > 5 }
Kotlin 的语法糖很多,但这些够应付大部分场景了。剩下的边写边查。

五、UI 开发:Jetpack Compose 入门
传统的 Android UI 用 XML 写布局,然后在 Java/Kotlin 里操作 View。现在 Google 推荐用 Jetpack Compose,直接用 Kotlin 代码写 UI,更简洁。

5.1 第一个 Composable 函数
@Composable
fun Greeting(name: String) {
Text(text = “你好,$name”)
}
@Composable 注解表示这是一个 UI 组件。Compose 用函数来描述界面,所以叫「声明式 UI」。

5.2 常用组件
// 文本
Text(“这是一段文字”)
// 按钮
Button(onClick = { /* 点击事件 */ }) {
Text(“点我”)
}
// 输入框
var text by remember { mutableStateOf(“”) }
TextField(
value = text,
onValueChange = { text = it },
placeholder = { Text(“请输入…”) }
)
// 图片
Image(
painter = painterResource(R.drawable.icon),
contentDescription = “图标”
)
5.3 布局
// 垂直排列
Column {
Text(“第一行”)
Text(“第二行”)
Text(“第三行”)
}
// 水平排列
Row {
Text(“左边”)
Text(“右边”)
}
// 层叠
Box {
Image(…)
Text(“覆盖在图片上的文字”)
}
5.4 列表
普通 Column 会一次性渲染所有内容,数据多了会卡。用 LazyColumn 可以实现懒加载:

LazyColumn {
items(noteList) { note ->
NoteCard(note)
}
}
5.5 状态管理
Compose 的核心概念:状态变了,UI 自动更新。

@Composable
fun Counter() {
var count by remember { mutableStateOf(0) }

Column {Text("当前计数:$count")Button(onClick = { count++ }) {Text("加一")}
}

}
remember 让状态在重组时保持不变,mutableStateOf 创建可观察的状态。当 count 变化时,用到它的 UI 会自动刷新。

六、做个能用的主页
理论讲完了,开始写实际代码。先做主页:显示今天的碎片想法,底部有个输入框可以添加新内容。

6.1 定义数据模型
在 data/local/database/entity 目录下创建
Note.kt

package com.example.journal.data.local.database.entity
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = “notes”)
data class Note(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val content: String,
val timestamp: Long = System.currentTimeMillis(),
val date: Long // 归属日期,用于按天分组
)
@Entity 告诉 Room 数据库这是一张表。@PrimaryKey(autoGenerate = true) 表示 id 自动生成。

6.2 创建 DAO(数据访问对象)
在 data/local/database/dao 目录下创建
NoteDao.kt

package com.example.journal.data.local.database.dao
import androidx.room.*
import com.example.journal.data.local.database.entity.Note
import kotlinx.coroutines.flow.Flow
@Dao
interface NoteDao {
@Insert
suspend fun insertNote(note: Note): Long
@Delete
suspend fun deleteNote(note: Note)
@Query(“SELECT * FROM notes WHERE date = :date ORDER BY timestamp DESC”)
fun getNotesByDate(date: Long): Flow<List>
@Query(“SELECT * FROM notes ORDER BY timestamp DESC”)
fun getAllNotes(): Flow<List>
}
几个要点:

@Insert、@Delete 是 Room 提供的注解,自动生成 SQL
@Query 手写 SQL
suspend 表示这是个协程函数,不会阻塞主线程
返回
Flow
是响应式的,数据变了会自动通知
6.3 创建数据库
在 data/local/database 目录下创建
AppDatabase.kt

package com.example.journal.data.local.database
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.journal.data.local.database.dao.NoteDao
import com.example.journal.data.local.database.entity.Note
@Database(entities = [Note::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
“journal_database”
).build().also { INSTANCE = it }
}
}
}
}
这是个典型的单例模式,保证整个 App 只有一个数据库实例。

6.4 添加依赖
打开
app/build.gradle.kts
,添加 Room 依赖:

dependencies {
// Room
val roomVersion = “2.6.1”
implementation(“androidx.room:room-runtime:roomVersion")implementation("androidx.room:room−ktx:roomVersion")implementation("androidx.room:room-ktx:roomVersion")implementation("androidx.room:roomktx:roomVersion”)
ksp(“androidx.room:room-compiler:$roomVersion”)
}
在 plugins 块添加 KSP:

plugins {
// … 其他插件
id(“com.google.devtools.ksp”) version “1.9.21-1.0.15”
}
点 Sync Now。

6.5 写主页 UI
创建
presentation/screen/main/MainScreen.kt

package com.example.journal.presentation.screen.main
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.example.journal.data.local.database.AppDatabase
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen() {
val context = LocalContext.current
val database = AppDatabase.getDatabase(context)
val noteDao = database.noteDao()
val scope = rememberCoroutineScope()
// 今天的日期(去掉时分秒)
val today = remember {
val cal = java.util.Calendar.getInstance()
cal.set(java.util.Calendar.HOUR_OF_DAY, 0)
cal.set(java.util.Calendar.MINUTE, 0)
cal.set(java.util.Calendar.SECOND, 0)
cal.set(java.util.Calendar.MILLISECOND, 0)
cal.timeInMillis
}
// 收集今天的笔记
val notes by noteDao.getNotesByDate(today).collectAsState(initial = emptyList())
// 输入框内容
var inputText by remember { mutableStateOf(“”) }
Scaffold(
topBar = {
TopAppBar(title = { Text(“今日想法”) })
},
bottomBar = {
// 底部输入栏
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
OutlinedTextField(
value = inputText,
onValueChange = { inputText = it },
modifier = Modifier.weight(1f),
placeholder = { Text(“记录一个想法…”) }
)
Spacer(modifier = Modifier.width(8.dp))
Button(
onClick = {
if (inputText.isNotBlank()) {
scope.launch {
noteDao.insertNote(
Note(content = inputText.trim(), date = today)
)
inputText = “”
}
}
}
) {
Text(“添加”)
}
}
}
) { padding ->
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(padding),
contentPadding = PaddingValues(16.dp)
) {
items(notes) { note ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp)
) {
Text(
text = note.content,
modifier = Modifier.padding(16.dp)
)
}
}
}
}
}
这段代码做了几件事:

获取数据库实例和 DAO
用 Flow.collectAsState() 订阅数据变化
底部有个输入框和按钮,点击后插入数据
用 LazyColumn 显示列表
6.6 跑起来看看

MainActivity.kt
改成:

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
MainScreen()
}
}
}
}
运行,应该能看到一个简单的笔记列表了。输入文字点添加,列表会自动更新。

七、架构重构:为什么代码要分层
上面的代码能跑,但有个问题:UI 里直接操作数据库,耦合太紧了。如果以后要换数据库、加缓存、写测试,改起来会很痛苦。

所以我们要做架构分层。

7.1 Clean Architecture 简介
这个架构把代码分成三层:

┌─────────────────────────────────────┐
│ Presentation (UI + ViewModel) │ ← 展示层:用户看到的界面
├─────────────────────────────────────┤
│ Domain (UseCase + Model) │ ← 领域层:业务逻辑
├─────────────────────────────────────┤
│ Data (Repository + DataSource) │ ← 数据层:数据来源
└─────────────────────────────────────┘
好处:

每层职责单一,改一个地方不会影响其他
方便单元测试
代码可读性高
7.2 添加 Repository
Repository 是数据层的门面,UI 不直接访问 DAO,而是通过 Repository。

创建
data/repository/NoteRepository.kt

package com.example.journal.data.repository
import com.example.journal.data.local.database.dao.NoteDao
import com.example.journal.data.local.database.entity.Note
import kotlinx.coroutines.flow.Flow
class NoteRepository(private val noteDao: NoteDao) {
fun getNotesByDate(date: Long): Flow<List> {
return noteDao.getNotesByDate(date)
}
fun getAllNotes(): Flow<List> {
return noteDao.getAllNotes()
}
suspend fun insertNote(note: Note): Long {
return noteDao.insertNote(note)
}
suspend fun deleteNote(note: Note) {
noteDao.deleteNote(note)
}
}
看起来只是包了一层?没错,简单场景下确实是。但当你需要加缓存、做数据转换、或者同时从本地和网络取数据时,Repository 的价值就体现出来了。

7.3 添加 ViewModel
ViewModel 负责持有 UI 状态,处理用户操作。它独立于 UI 生命周期,屏幕旋转时数据不会丢失。

创建
presentation/screen/main/MainViewModel.kt

package com.example.journal.presentation.screen.main
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.example.journal.data.local.database.entity.Note
import com.example.journal.data.repository.NoteRepository
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.util.Calendar
class MainViewModel(
private val noteRepository: NoteRepository
) : ViewModel() {
private val _inputText = MutableStateFlow(“”)
val inputText: StateFlow = _inputText.asStateFlow()
private val today: Long = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.timeInMillis
val todayNotes: StateFlow<List> = noteRepository
.getNotesByDate(today)
.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
fun updateInput(text: String) {
_inputText.value = text
}
fun addNote() {
val content = _inputText.value.trim()
if (content.isBlank()) return
viewModelScope.launch {
noteRepository.insertNote(
Note(content = content, date = today)
)
_inputText.value = “”
}
}
fun deleteNote(note: Note) {
viewModelScope.launch {
noteRepository.deleteNote(note)
}
}
class Factory(private val repository: NoteRepository) : ViewModelProvider.Factory {
@Suppress(“UNCHECKED_CAST”)
override fun create(modelClass: Class): T {
return MainViewModel(repository) as T
}
}
}
7.4 更新 UI
现在
MainScreen
变得很干净:

@Composable
fun MainScreen() {
val context = LocalContext.current
val database = AppDatabase.getDatabase(context)
val repository = NoteRepository(database.noteDao())
val viewModel: MainViewModel = viewModel(factory = MainViewModel.Factory(repository))
val notes by viewModel.todayNotes.collectAsState()
val inputText by viewModel.inputText.collectAsState()
Scaffold(
topBar = { TopAppBar(title = { Text(“今日想法”) }) },
bottomBar = {
Row(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
OutlinedTextField(
value = inputText,
onValueChange = { viewModel.updateInput(it) },
modifier = Modifier.weight(1f),
placeholder = { Text(“记录一个想法…”) }
)
Spacer(modifier = Modifier.width(8.dp))
Button(onClick = { viewModel.addNote() }) {
Text(“添加”)
}
}
}
) { padding ->
LazyColumn(
modifier = Modifier.fillMaxSize().padding(padding),
contentPadding = PaddingValues(16.dp)
) {
items(notes) { note ->
NoteCard(note = note, onDelete = { viewModel.deleteNote(note) })
}
}
}
}
UI 只负责展示和收集用户操作,业务逻辑都在 ViewModel 里。

八、接入 AI:让日记自己写
这是最有意思的部分。我们要调用 LLM API,把碎片想法整理成日记。

8.1 选择一个 LLM 服务
国内能用的 LLM API 很多:

DeepSeek:便宜好用,中文效果不错
通义千问:阿里的,有免费额度
智谱 GLM:清华背景,也不错
我用的是 DeepSeek,注册后充几块钱能用很久。

8.2 添加网络权限和依赖

AndroidManifest.xml
添加:

在 build.gradle.kts添加 OkHttp(网络请求库)和 Gson(JSON 解析):

implementation(“com.squareup.okhttp3:okhttp:4.12.0”)
implementation(“com.google.code.gson:gson:2.10.1”)
8.3 写 LLM 调用代码
创建 data/remote/LlmService.kt:

package com.example.journal.data.remote
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import java.util.concurrent.TimeUnit
object LlmService {
private val client = OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build()
private val gson = Gson()
private const val API_URL = “https://api.deepseek.com/v1/chat/completions”
suspend fun generateDiary(notes: List, apiKey: String): Result {
return withContext(Dispatchers.IO) {
try {
val notesText = notes.mapIndexed { i, n -> “${i + 1}. $n” }.joinToString(“\n”)

            val prompt = """请将以下碎片想法整理成一篇日记。要求:1. 保持原意,可以适当润色2. 按时间或主题组织3. 语气自然,像在和朋友聊天4. 结尾可以加一两句感悟碎片想法:$notesText""".trimIndent()val requestBody = mapOf("model" to "deepseek-chat","messages" to listOf(mapOf("role" to "user", "content" to prompt)))val request = Request.Builder().url(API_URL).addHeader("Authorization", "Bearer $apiKey").addHeader("Content-Type", "application/json").post(gson.toJson(requestBody).toRequestBody("application/json".toMediaType())).build()val response = client.newCall(request).execute()val body = response.body?.string() ?: throw Exception("Empty response")// 解析响应val json = gson.fromJson(body, Map::class.java)val choices = json["choices"] as? List<*>val message = (choices?.firstOrNull() as? Map<*, *>)?.get("message") as? Map<*, *>val content = message?.get("content") as? String ?: throw Exception("Invalid response")Result.success(content)} catch (e: Exception) {Result.failure(e)}}
}

}
8.4 添加生成按钮

MainScreen
添加一个「生成日记」按钮:

Button(
onClick = {
scope.launch {
val noteContents = notes.map { it.content }
val result = LlmService.generateDiary(noteContents, “your-api-key”)
result.onSuccess { diary ->
// 保存到数据库或显示出来
}.onFailure { e ->
// 显示错误提示
}
}
}
) {
Text(“生成日记”)
}
⚠️ 注意:不要把 API Key 硬编码在代码里!应该让用户在设置页面输入,然后存到 SharedPreferences。

九、添加更多功能
基础框架搭好后,加功能就快了。我简单列一下我后来加的东西:

9.1 日记列表页
新建一个页面,用 LazyColumn 显示所有日记。每个日记卡片显示日期、内容预览、情绪标签。

9.2 搜索功能
在 DAO 里加一个搜索方法:

@Query(“SELECT * FROM diaries WHERE content LIKE ‘%’ || :query || ‘%’”)
fun searchByContent(query: String): Flow<List>
UI 上加个搜索框,输入时调用这个查询。

9.3 导出功能
把日记导出成 Markdown 文件:

fun exportToMarkdown(diary: Diary): String {
return “”"
# ${formatDate(diary.date)} 的日记

    ${diary.content}---*情绪:${diary.moodLabel}*
""".trimIndent()

}
然后用 MediaStore API 保存到 Downloads 文件夹。

9.4 待办事项提取
让 AI 在生成日记的同时提取待办:

val prompt = “”"
请完成两件事:
1. 将以下想法整理成日记
2. 提取其中提到的待办事项

输出格式:
【日记】
...
【待办】
- 待办1
- 待办2

“”"
然后解析响应,分别保存日记和待办。

9.5 语音输入
Android 自带语音识别 API:

val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
putExtra(RecognizerIntent.EXTRA_LANGUAGE, “zh-CN”)
}
speechRecognizer.startListening(intent)
识别结果通过回调返回,直接添加到笔记列表。

十、调试和发布
10.1 常见问题
Q: 应用闪退了怎么办? 看 Logcat。在 Android Studio 底部找到 Logcat 标签,过滤 Error 级别,找红色的 Exception。

Q: 数据库结构改了,应用崩溃? 数据库版本号要加 1,并且添加 Migration 或者用 fallbackToDestructiveMigration()(开发阶段)。

Q: 网络请求没反应?

检查有没有加 INTERNET 权限
检查是不是主线程调的(要用协程)
看 Logcat 有没有报错
10.2 打包 APK
菜单栏 Build → Generate Signed Bundle / APK,选 APK,创建或选择签名文件,选 release 版本,点 Finish。

生成的 APK 在 app/release 目录下。

十一、总结
写到这里,你应该对 Android 开发有个基本概念了。回顾一下我们做了什么:

环境搭建:安装 Android Studio,创建 Compose 项目
Kotlin 基础:变量、函数、数据类、空安全、Lambda
Compose UI:组件、布局、状态管理、列表
Room 数据库:Entity、DAO、Database
架构设计:Repository、ViewModel、分层
网络请求:调用 LLM API
这些是开发任何 Android App 都会用到的基础。剩下的就是根据需求堆功能了。

我的建议是:别光看,动手写。遇到问题就去查文档、搜 Stack Overflow。踩坑是学习的必经之路。

最后附上项目地址:https://github.com/kai200407/AI-Diary-App-Android

有问题欢迎在评论区讨论。

这篇文章写于 2025 年 12 月,如果你看到时 API 变了,以官方文档为准。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1177891.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聊聊压缩空气检测资深企业,杭州华量检测技术实力和口碑咋样? - 工业品牌热点

问题1:压缩空气检测对企业来说有什么实际意义?为什么不能随便找家公司做? 压缩空气检测看似是幕后工作,实则是生产安全与产品质量的隐形防线。对于食品、医药、电子等行业而言,压缩空气中的油分、水分、微生物或固…

EtherCAT总线通信学习资料:STM32 MCU AX58100 ESC从站实现方案及一手资源

EtherCAT总线通信学习资料&#xff0c;一手资料。 提供基于stm32 mcuAX58100 ESC实现从站的具体方案&#xff0c;有完整的工程文件&#xff0c;提供源码以及工程配置、程序修改的视频&#xff0c;工程在开发板上已测。 提供不同版本工具从站工程。 支持主站下发固件程序&#x…

详细介绍:算法王冠上的明珠——动态规划之斐波那契数列问题(第二篇)

详细介绍:算法王冠上的明珠——动态规划之斐波那契数列问题(第二篇)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: &q…

韩秀云老师谈买黄金

网址&#xff1a;韩秀云老师谈买黄金

19.螺旋矩阵

54. 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 2:输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]] 输出:[1,2,3,4,8,12,11,10,9,5,6,7] 【思路】 首先设…

付费问答系统的设计与实现毕业论文+PPT(附源代码+演示视频)

文章目录付费问答系统的设计与实现一、项目简介&#xff08;源代码在文末&#xff09;1.运行视频2.&#x1f680; 项目技术栈3.✅ 环境要求说明4.包含的文件列表&#xff08;含论文&#xff09;数据库结构与测试用例系统功能结构前端运行截图后端运行截图项目部署源码下载付费问…

PostgreSQL实战:一文掌握 pg_hba.conf 配置,涵盖密码认证、IP限制与安全策略

文章目录一、pg_hba.conf 基础认知1.1 pg_hba.conf 概述1.2 文件位置与作用1.3 基本语法结构1.4 安全加固 checklist二、TYPE 字段详解&#xff1a;连接类型三、DATABASE 字段&#xff1a;目标数据库四、USER 字段&#xff1a;目标用户五、ADDRESS 字段&#xff1a;客户端地址限…

ACPI!ACPIBuildProcessGenericList函数中2次InterlockedCompareExchange函数作用是标记为WORK_DONE_PENDING下次直接略过

ACPI!ACPIBuildProcessGenericList函数中2次InterlockedCompareExchange函数作用是标记为WORK_DONE_PENDING下次直接略过//// Check to see if we have any work to do on the request//workDone InterlockedCompareExchange(&(buildRequest->WorkDone),WORK_DONE_PEND…

2025年市场上服务好的广告厂家有哪些,户外广告/地铁广告/航空广告/地铁站广告/电梯广告,广告设计找哪家 - 品牌推荐师

行业洞察:广告业服务升级背后的技术驱动与场景深耕 2025年,广告行业正经历从“流量争夺”向“场景价值挖掘”的深度转型。随着消费者触媒习惯的碎片化,广告主对精准投放、全域覆盖及效果可量化的需求日益迫切。据CT…

告别查重焦虑!虎贲等考 AI 降重降 AIGC:一次操作双重达标,论文合规不丢质

毕业季的论文定稿环节&#xff0c;无数学生陷入两难&#xff1a;重复率超标被打回&#xff0c;AI 辅助撰写的内容又因 “机器感” 过强被检测&#xff1b;手动降重改到语句不通&#xff0c;普通工具改写又丢了核心观点。当学术审核进入 “查重 AIGC 检测” 双门槛时代&#xf…

从Demo到上线:IndexTTS-2-LLM企业级部署步骤详解

从Demo到上线&#xff1a;IndexTTS-2-LLM企业级部署步骤详解 1. 引言 1.1 业务场景描述 随着智能语音技术的快速发展&#xff0c;企业对高质量、低成本、易集成的文本转语音&#xff08;Text-to-Speech, TTS&#xff09;系统需求日益增长。无论是客服机器人、有声内容生成&a…

AtCoder Beginner Contest竞赛题解 | AtCoder Beginner Contest 435

​欢迎大家订阅我的专栏:算法题解:C++与Python实现! 本专栏旨在帮助大家从基础到进阶 ,逐步提升编程能力,助力信息学竞赛备战! 专栏特色 1.经典算法练习:根据信息学竞赛大纲,精心挑选经典算法题目,提供清晰的…

2026学历提升攻略:口碑学校引领未来方向,国家开放大学招生/自考培训/学历提升/专升本报名,学历提升机构口碑推荐榜 - 品牌推荐师

在当今知识经济时代,学历不仅是个人知识储备的证明,更是职场晋升、职业转型、社会评价的核心凭证。对于广大在职人士而言,一个权威、便捷、高效的学历提升路径,能够有效打破职业天花板,为个人发展注入持续动能。然…

2026年市面上有名的河道护坡石笼网公司有哪些,柔韧抗压石笼网/镀锌低碳钢丝石笼网,河道护坡石笼网供应商口碑推荐 - 品牌推荐师

随着国家对水利基础设施建设的持续投入,河道护坡工程作为防洪减灾、生态修复的核心环节,其技术标准与材料质量要求日益严苛。石笼网因其柔性结构、透水性强、抗冲刷能力突出等特性,成为河道护坡领域的首选材料。然而…

一图胜千言!虎贲等考 AI 科研绘图功能让数据可视化秒变顶刊水准

还在为 Origin 调参调到崩溃&#xff1f;还在因 Excel 画不出高难度热图 emo&#xff1f;还在被导师吐槽 “图表不规范、配色辣眼睛”&#xff1f;在科研圈&#xff0c;一张精准、美观、规范的图表&#xff0c;是论文加分的硬核利器&#xff0c;更是学术成果展示的 “门面担当”…

课程论文不用熬大夜!虎贲等考 AI:一键解锁从选题到定稿的高效通关术

每到期末&#xff0c;课程论文就成了大学生的 “头号难题”。选题像开盲盒&#xff0c;要么太宽泛写不透&#xff0c;要么太冷门没资料&#xff1b;文献堆砌没逻辑&#xff0c;被导师批 “学术搬运工”&#xff1b;查重改到头晕&#xff0c;重复率还是居高不下…… 作为深耕论文…

DeepSeek-R1-Distill-Qwen-1.5B应用实战:智能写作助手开发

DeepSeek-R1-Distill-Qwen-1.5B应用实战&#xff1a;智能写作助手开发 1. 引言 1.1 业务场景描述 在内容创作、教育辅助和办公自动化等场景中&#xff0c;高质量的文本生成能力正成为AI落地的核心需求。传统大模型虽然具备强大的语言理解与生成能力&#xff0c;但其高资源消…

塑料管道制造商怎么选,四川都得利管业性价比高吗? - 工业品牌热点

问题1:什么是专业的塑料管道品牌制造商?选择时需要关注哪些核心能力? 专业的塑料管道品牌制造商,是指具备自主研发、标准化生产、全链路服务能力,且能针对不同场景提供定制化管道解决方案的企业,核心在于产品力+…

2026年学历提升评测:如何选择口碑好的学校?自考培训/国家开放大学招生/学历提升/专升本报名,学历提升机构推荐 - 品牌推荐师

在当今竞争激烈的职场环境中,学历不仅是个人知识储备的证明,更是职业晋升、资格评定、积分落户乃至拓宽人生选择的核心“通行证”。对于广大在职人士而言,选择一个专业、可靠、口碑好的学历提升机构,是保障学习效果…

年终盘点:2025年频谱仪品牌口碑榜,谁主沉浮?光通信测量仪表/通信干扰模拟器/光时域反射仪/电子对抗设备/以太网测试仪频谱仪公司找哪家 - 品牌推荐师

随着5G-A、6G预研、物联网及电子对抗等领域的快速发展,频谱仪作为信号分析、干扰排查与通信测试的核心工具,其市场需求与技术重要性日益凸显。面对市场上琳琅满目的品牌与产品,如何选择一款性能可靠、适配场景且服务…