Android应用实现:MainActivity、UML查看器、AI助手、图书管理功能

main
SLMS Development Team 5 months ago
parent 41ff9e485f
commit 75b2b093bb

@ -0,0 +1,9 @@
# 保留所有 Android 基础类
-keep class com.smartlibrary.** { *; }
# 保留 Retrofit
-keepattributes Signature
-keepattributes Exceptions
# 保留 Gson
-keep class com.google.gson.** { *; }

@ -0,0 +1,259 @@
package com.smartlibrary.android
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.TextView
import com.smartlibrary.android.ui.UMLViewerActivity
/**
* 智能图书管理系统 - Android 主界面
*/
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var emptyView: TextView
private lateinit var progressBar: ProgressBar
private lateinit var bookAdapter: BookAdapter
private val books = mutableListOf<Book>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupViews()
loadMockData()
}
private fun setupViews() {
recyclerView = findViewById(R.id.recyclerView)
emptyView = findViewById(R.id.emptyView)
progressBar = findViewById(R.id.progressBar)
bookAdapter = BookAdapter(books) { book ->
showBookDetail(book)
}
recyclerView.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
adapter = bookAdapter
}
findViewById<Button>(R.id.btnAddBook).setOnClickListener {
showAddBookDialog()
}
findViewById<Button>(R.id.btnAiAssistant).setOnClickListener {
showAiAssistant()
}
}
private fun loadMockData() {
progressBar.visibility = View.VISIBLE
// 模拟数据
books.clear()
books.addAll(listOf(
Book("1", "设计模式", "Gang of Four", "978-0-201-63361-0", "机械工业出版社", "计算机", true),
Book("2", "重构", "Martin Fowler", "978-0-13-475759-9", "人民邮电出版社", "计算机", true),
Book("3", "代码整洁之道", "Robert C. Martin", "978-0-13-235088-4", "人民邮电出版社", "计算机", false),
Book("4", "算法导论", "Thomas H. Cormen", "978-0-262-03384-8", "机械工业出版社", "计算机", true),
Book("5", "深入理解Java虚拟机", "周志明", "978-7-111-64124-1", "机械工业出版社", "计算机", true)
))
progressBar.visibility = View.GONE
updateUI()
}
private fun updateUI() {
if (books.isEmpty()) {
recyclerView.visibility = View.GONE
emptyView.visibility = View.VISIBLE
} else {
recyclerView.visibility = View.VISIBLE
emptyView.visibility = View.GONE
bookAdapter.notifyDataSetChanged()
}
}
private fun showBookDetail(book: Book) {
AlertDialog.Builder(this)
.setTitle(book.title)
.setMessage("""
作者: ${book.author}
ISBN: ${book.isbn}
出版社: ${book.publisher}
分类: ${book.category}
状态: ${if (book.available) "可借阅" else "已借出"}
""".trimIndent())
.setPositiveButton(if (book.available) "借阅" else "归还") { _, _ ->
book.available = !book.available
bookAdapter.notifyDataSetChanged()
Toast.makeText(this, if (book.available) "归还成功" else "借阅成功", Toast.LENGTH_SHORT).show()
}
.setNegativeButton("关闭", null)
.show()
}
private fun showAddBookDialog() {
val dialogView = layoutInflater.inflate(R.layout.dialog_add_book, null)
AlertDialog.Builder(this)
.setTitle("添加图书")
.setView(dialogView)
.setPositiveButton("添加") { _, _ ->
val title = dialogView.findViewById<EditText>(R.id.etTitle).text.toString()
val author = dialogView.findViewById<EditText>(R.id.etAuthor).text.toString()
val isbn = dialogView.findViewById<EditText>(R.id.etIsbn).text.toString()
if (title.isNotBlank() && author.isNotBlank()) {
val newBook = Book(
id = (books.size + 1).toString(),
title = title,
author = author,
isbn = isbn,
publisher = "未知",
category = "未分类",
available = true
)
books.add(0, newBook)
updateUI()
Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show()
}
}
.setNegativeButton("取消", null)
.show()
}
private fun showAiAssistant() {
val input = EditText(this).apply {
hint = "请输入您的问题..."
}
AlertDialog.Builder(this)
.setTitle("🤖 AI智能助手")
.setView(input)
.setPositiveButton("发送") { _, _ ->
val question = input.text.toString()
if (question.isNotBlank()) {
// 模拟AI回复
val response = when {
question.contains("推荐") -> "根据您的借阅历史,推荐您阅读《设计模式》和《重构》"
question.contains("搜索") || question.contains("查找") -> "已为您找到相关图书,请查看列表"
else -> "感谢您的提问!如需帮助,可以问我:推荐图书、搜索图书等"
}
AlertDialog.Builder(this)
.setTitle("AI回复")
.setMessage(response)
.setPositiveButton("确定", null)
.show()
}
}
.setNegativeButton("取消", null)
.show()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_uml -> {
startActivity(Intent(this, UMLViewerActivity::class.java))
true
}
R.id.action_web -> {
showSwitchToWebDialog()
true
}
R.id.action_about -> {
showAboutDialog()
true
}
else -> super.onOptionsItemSelected(item)
}
}
private fun showSwitchToWebDialog() {
AlertDialog.Builder(this)
.setTitle("切换到Web端")
.setMessage("Web服务地址:\nhttp://localhost:8082\n\n请确保后端服务已启动")
.setPositiveButton("打开浏览器") { _, _ ->
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("http://localhost:8082"))
startActivity(intent)
} catch (e: Exception) {
Toast.makeText(this, "无法打开浏览器", Toast.LENGTH_SHORT).show()
}
}
.setNegativeButton("取消", null)
.show()
}
private fun showAboutDialog() {
AlertDialog.Builder(this)
.setTitle("关于")
.setMessage("智能图书管理系统 (SLMS)\n版本: 1.0.0\n\n四端统一架构:\n• CLI 命令行\n• GUI 桌面应用\n• WUI Web应用\n• App 移动端")
.setPositiveButton("确定", null)
.show()
}
}
/**
* 图书数据类
*/
data class Book(
val id: String,
val title: String,
val author: String,
val isbn: String,
val publisher: String,
val category: String,
var available: Boolean
)
/**
* 图书列表适配器
*/
class BookAdapter(
private val books: List<Book>,
private val onClick: (Book) -> Unit
) : RecyclerView.Adapter<BookAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val tvTitle: TextView = view.findViewById(R.id.tvTitle)
val tvAuthor: TextView = view.findViewById(R.id.tvAuthor)
val tvStatus: TextView = view.findViewById(R.id.tvStatus)
}
override fun onCreateViewHolder(parent: android.view.ViewGroup, viewType: Int): ViewHolder {
val view = android.view.LayoutInflater.from(parent.context)
.inflate(R.layout.item_book, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val book = books[position]
holder.tvTitle.text = book.title
holder.tvAuthor.text = "作者: ${book.author}"
holder.tvStatus.text = if (book.available) "✅ 可借阅" else "❌ 已借出"
holder.itemView.setOnClickListener { onClick(book) }
}
override fun getItemCount() = books.size
}

@ -0,0 +1,15 @@
package com.smartlibrary.android.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
/**
* 广播接收器
*/
class LibraryBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
// 处理系统广播
}
}

@ -0,0 +1,17 @@
package com.smartlibrary.android.service
import android.app.Service
import android.content.Intent
import android.os.IBinder
/**
* 图书馆后台服务
*/
class LibraryService : Service() {
override fun onBind(intent: Intent?): IBinder? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return START_STICKY
}
}

@ -0,0 +1,109 @@
package com.smartlibrary.android.ui
import android.os.Bundle
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import com.smartlibrary.android.R
/**
* UML图查看器
*/
class UMLViewerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_uml_viewer)
supportActionBar?.apply {
title = "UML图查看器"
setDisplayHomeAsUpEnabled(true)
}
val webView = findViewById<WebView>(R.id.webView)
webView.apply {
settings.javaScriptEnabled = true
settings.builtInZoomControls = true
settings.displayZoomControls = false
webViewClient = WebViewClient()
// 加载 PlantUML 在线渲染
loadData(getUmlHtml(), "text/html", "UTF-8")
}
}
private fun getUmlHtml(): String {
return """
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { font-family: sans-serif; padding: 16px; background: #f5f5f5; }
h2 { color: #1976D2; }
pre { background: #fff; padding: 12px; border-radius: 8px; overflow-x: auto; font-size: 12px; }
.card { background: #fff; margin: 16px 0; padding: 16px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
</style>
</head>
<body>
<h2>📊 系统类图</h2>
<div class="card">
<pre>
@startuml
class Book {
-id: String
-title: String
-author: String
-available: boolean
+borrow(): void
+returnBook(): void
}
class Loan {
-id: String
-bookId: String
-userId: String
-borrowDate: Date
}
class BookService {
+addBook(): boolean
+borrowBook(): boolean
+returnBook(): boolean
}
BookService --> Book
BookService --> Loan
@enduml
</pre>
</div>
<h2>🔄 借阅流程时序图</h2>
<div class="card">
<pre>
@startuml
actor 用户
participant "App界面" as App
participant "BookService" as Service
participant "Database" as DB
用户 -> App: 点击借阅
App -> Service: borrowBook()
Service -> DB: 查询图书
DB --> Service: 返回图书
Service -> DB: 更新状态
Service --> App: 借阅成功
App --> 用户: 显示结果
@enduml
</pre>
</div>
</body>
</html>
""".trimIndent()
}
override fun onSupportNavigateUp(): Boolean {
finish()
return true
}
}

@ -1,52 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
tools:context=".MainActivity">
android:orientation="vertical"
android:background="#F5F5F5">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar_layout"
<!-- 按钮区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_constraintTop_toTopOf="parent">
android:orientation="horizontal"
android:padding="8dp"
android:background="#FFFFFF">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
app:title="@string/app_name"
app:titleTextColor="@color/text_on_primary"
style="@style/Widget.SmartLibrary.Toolbar" />
<Button
android:id="@+id/btnAddBook"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="添加图书"
android:layout_marginEnd="4dp" />
</com.google.android.material.appbar.AppBarLayout>
<Button
android:id="@+id/btnAiAssistant"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="AI助手"
android:layout_marginStart="4dp" />
</LinearLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/app_bar_layout"
app:navGraph="@navigation/nav_graph" />
<!-- 加载进度 -->
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="0dp"
<!-- 空状态提示 -->
<TextView
android:id="@+id/emptyView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_nav_menu"
style="@style/Widget.SmartLibrary.BottomNavigationView" />
android:text="暂无图书数据"
android:textSize="16sp"
android:textColor="#999999"
android:gravity="center"
android:padding="32dp"
android:visibility="gone" />
<!-- 图书列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="8dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/etTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="书名"
android:inputType="text" />
<EditText
android:id="@+id/etAuthor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="作者"
android:inputType="text"
android:layout_marginTop="8dp" />
<EditText
android:id="@+id/etIsbn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="ISBN"
android:inputType="text"
android:layout_marginTop="8dp" />
</LinearLayout>

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#333333" />
<TextView
android:id="@+id/tvAuthor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="#666666"
android:layout_marginTop="4dp" />
<TextView
android:id="@+id/tvStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="8dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_uml"
android:title="UML图"
app:showAsAction="never" />
<item
android:id="@+id/action_web"
android:title="切换到Web"
app:showAsAction="never" />
<item
android:id="@+id/action_about"
android:title="关于"
app:showAsAction="never" />
</menu>
Loading…
Cancel
Save