feat(chat): 添加聊天功能和Markwon富文本支持
- 集成io.noties.markwon库用于Markdown渲染 - 新增ChatItem数据模型类 - 创建ChatActivity实现聊天界面和离线命令监听 - 添加ChatVM视图模型提供聊天数据 - 设计activity_chat.xml和item_chat.xml布局文件 - 在WelcomeActivity中添加决策中心入口按钮 - 配置AndroidManifest.xml注册ChatActivity - 移除base模块中的Maven发布配置
这个提交包含在:
父节点
c77b59cee4
当前提交
aba8c69a0c
@ -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", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
正在加载...
在新工单中引用
屏蔽一个用户