feat(chat): 添加聊天功能和Markwon富文本支持

- 集成io.noties.markwon库用于Markdown渲染
- 新增ChatItem数据模型类
- 创建ChatActivity实现聊天界面和离线命令监听
- 添加ChatVM视图模型提供聊天数据
- 设计activity_chat.xml和item_chat.xml布局文件
- 在WelcomeActivity中添加决策中心入口按钮
- 配置AndroidManifest.xml注册ChatActivity
- 移除base模块中的Maven发布配置
这个提交包含在:
徐勤民 2026-04-16 10:48:19 +08:00
父节点 c77b59cee4
当前提交 aba8c69a0c
共有 10 个文件被更改,包括 196 次插入50 次删除

查看文件

@ -78,6 +78,7 @@ dependencies {
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation "io.noties.markwon:core:4.6.2"
implementation ('com.rokid.security:glass3.open.sdk:2.1.5-E') {
exclude group: "org.slf4j"

查看文件

@ -75,6 +75,9 @@
<activity
android:name=".ui.TaskListActivity"
android:exported="false" />
<activity
android:name=".ui.ChatActivity"
android:exported="false" />
<activity
android:name=".ui.InspectionActivity"
android:exported="false" />

查看文件

@ -0,0 +1,6 @@
package com.nova.brain.glass.model
import com.xuqm.base.adapter.BaseItem
data class ChatItem(val title: String, val content: String): BaseItem() {
}

查看文件

@ -0,0 +1,54 @@
package com.nova.brain.glass.ui
import android.widget.TextView
import com.nova.brain.glass.R
import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.model.ChatItem
import com.nova.brain.glass.viewmodel.ChatVM
import com.xuqm.base.adapter.BasePagedAdapter
import com.xuqm.base.adapter.CommonPagedAdapter
import com.xuqm.base.adapter.ViewHolder
import com.xuqm.base.ui.BaseListActivity
import io.noties.markwon.Markwon
class ChatActivity : BaseListActivity<ChatItem, ChatVM>() {
private val listener = object : OfflineCmdListener {
override fun onOfflineCmd(cmd: String) {
runOnUiThread {
when (cmd) {
"退出", "返回", "退回" -> {
finish()
}
}
}
}
}
private lateinit var markwon: Markwon
override fun initData() {
super.initData()
markwon = Markwon.create(this);
}
override fun onResume() {
super.onResume()
OfflineCmdServiceHelper.addOnLineListener(listener)
}
override fun onPause() {
super.onPause()
OfflineCmdServiceHelper.removeOnLineListener(listener)
}
private val adapter = object : CommonPagedAdapter<ChatItem>(R.layout.item_chat) {
override fun convert(holder: ViewHolder, item: ChatItem, position: Int) {
holder.setText(R.id.title, item.title)
val tv = holder.getView<TextView>(R.id.content)
markwon.setMarkdown(tv, item.content);
}
}
override fun adapter(): BasePagedAdapter<ChatItem> = adapter
}

查看文件

@ -9,6 +9,7 @@ import com.nova.brain.glass.helper.OfflineCmdListener
import com.nova.brain.glass.helper.OfflineCmdServiceHelper
import com.nova.brain.glass.viewmodel.WelcomeVM
import com.xuqm.base.ui.BaseActivity
import kotlin.jvm.java
class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
@ -27,6 +28,7 @@ class WelcomeActivity : BaseActivity<ActivityWelcomeBinding>() {
binding.btnGet.setOnClickListener { vm.demoGet() }
binding.btnPost.setOnClickListener { vm.demoPost() }
binding.btnSse.setOnClickListener { vm.demoPostSse() }
binding.md.setOnClickListener { startActivity(Intent(this@WelcomeActivity, ChatActivity::class.java)) }
}
override fun initData() {

查看文件

@ -0,0 +1,46 @@
package com.nova.brain.glass.viewmodel
import com.nova.brain.glass.model.ChatItem
import com.xuqm.base.viewmodel.BaseListViewModel
import com.xuqm.base.viewmodel.callback.Response
class ChatVM : BaseListViewModel<ChatItem>() {
override fun loadData(
page: Int,
onResponse: Response<ChatItem>
) {
onResponse.onResponse(arrayListOf<ChatItem>().apply {
add(
ChatItem(
"本周周报", """
## 统计数据截止到2026年3月19日 1:36
### 纪检Agent3期产品设计明日到达计划完成时间
#### *重点关注*张三测试运维部负责的C大脑-脑实例- V2.24-测试方案设计
* 当前状态已延期13天严重程度为严重延期
* 参谋建议建议高优处理
""".trimIndent()
)
)
add(
ChatItem(
"我最紧急的任务是哪个", """
# 标题
这是 **加粗***斜体*~~删除线~~
- 列表1
- 列表2
[点击跳转](https://openai.com)
""".trimIndent()
)
)
})
}
}

查看文件

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<layout>
<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"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/app_color_black">
<TextView
android:id="@+id/tvTaskHeader"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="130工序要求如下"
android:textColor="#ff40FF5E"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<WebView
android:id="@+id/content"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tvTaskHeader" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

查看文件

@ -64,13 +64,38 @@
android:textSize="14sp"
android:text="SSE演示" />
</LinearLayout>
<LinearLayout
android:id="@+id/btnRow2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginHorizontal="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/btnRow">
<TextView
android:id="@+id/md"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:gravity="center"
android:background="#33FFFFFF"
android:textColor="#ff3FFF5F"
android:textSize="14sp"
android:text="决策中心" />
</LinearLayout>
<ScrollView
android:id="@+id/scrollResult"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@id/btnRow"
app:layout_constraintTop_toBottomOf="@id/btnRow2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">

查看文件

@ -0,0 +1,26 @@
<?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:layout_marginBottom="20dp"
android:paddingHorizontal="29dp"
android:paddingVertical="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="驳回"
android:textColor="#2EB242"
android:textSize="10sp" />
<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="驳回"
android:textColor="#ff40FF5E"
android:textSize="14sp" />
</LinearLayout>

查看文件

@ -1,10 +1,5 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'maven-publish'
// aar包的版本号
def aarVersion = "0.0.1.101"
android {
compileSdkVersion versions.compileSdk
@ -54,47 +49,3 @@ task sourceJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
}
afterEvaluate {
publishing {
publications {
// debug名字是自己起的
release(MavenPublication) {
groupId = 'cn.org.bjca.trust.android'
artifactId = 'base'
version = aarVersion
// debug release
from components.release
//
artifact sourceJar
}
}
//
repositories {
//
// mavenLocal()
//
// maven {
// allowInsecureProtocol true
// url("http://nexus.51trust.net/repository/android-hosted/")
// credentials {
// username = "deployment"
// password = "deployment123"
// }
// }
maven {
allowInsecureProtocol true
url("http://xuqinmin.com.cn:8081/repository/android-releases/")
credentials {
// local.properties
def props = new Properties()
def localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localPropertiesFile.withInputStream { props.load(it) }
}
username = props.getProperty("nexus.username", "")
password = props.getProperty("nexus.password", "")
}
}
}
}
}