feat(chat): 添加语音识别功能并优化聊天界面
- 新增 RecognizeData 和 RecognizeModel 数据类用于语音识别 - 在 Service 中添加 recognize 接口用于意图识别 - 为 ChatItem 添加 id 字段并在 ViewModel 中初始化 - 添加加载状态指示器和进度条显示 - 优化聊天列表布局,添加分割线和提示文字 - 更新加载动画颜色为主题绿色 #ff40FF5E - 简化 ChatModel 数据结构并优化消息处理逻辑 - 添加 loading 状态管理来控制进度条显示
这个提交包含在:
父节点
4e9f609c5b
当前提交
877455a727
@ -2,5 +2,8 @@ package com.nova.brain.glass.model
|
|||||||
|
|
||||||
import com.xuqm.base.adapter.BaseItem
|
import com.xuqm.base.adapter.BaseItem
|
||||||
|
|
||||||
data class ChatItem(val title: String, val content: String): BaseItem() {
|
data class ChatItem(val id: Int, val title: String, var content: String) : BaseItem() {
|
||||||
}
|
init {
|
||||||
|
setS_id(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,44 +1,17 @@
|
|||||||
package com.nova.brain.glass.model
|
package com.nova.brain.glass.model
|
||||||
|
|
||||||
//{
|
|
||||||
// "id": 74216,
|
|
||||||
// "role": "assistant",
|
|
||||||
// "createTime": "2026-04-16T06:13:32.678Z",
|
|
||||||
// "type": "reason",
|
|
||||||
// "data": {
|
|
||||||
// "content": "数据。",
|
|
||||||
// "duration": 0.0
|
|
||||||
// },
|
|
||||||
// "metadata": {}
|
|
||||||
//}
|
|
||||||
//{
|
|
||||||
// "id": 74216,
|
|
||||||
// "role": "assistant",
|
|
||||||
// "createTime": "2026-04-16T06:13:32.678Z",
|
|
||||||
// "type": "string",
|
|
||||||
// "data": "最",
|
|
||||||
// "metadata": {}
|
|
||||||
//}
|
|
||||||
//{"date":"2026-04-16T06:49:19.790Z","msg":"当前话题存在进行中的请求,请稍后重试","code":409,"success":false,"uri":"/docqa/chat/qa03","status":409}
|
//{"date":"2026-04-16T06:49:19.790Z","msg":"当前话题存在进行中的请求,请稍后重试","code":409,"success":false,"uri":"/docqa/chat/qa03","status":409}
|
||||||
data class ChatModel(
|
data class ChatModel(
|
||||||
|
val role: String?,
|
||||||
val type: String?,
|
val type: String?,
|
||||||
val msg: String?,
|
val msg: String?,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// {"id":74316,"role":"assistant","createTime":"2026-04-16T08:28:06.428Z","type":"string","data":"建议使用","metadata":{}}
|
||||||
data class ChatModel1(
|
data class ChatModel1(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val role: String,
|
val role: String,
|
||||||
val createTime: String,
|
val createTime: String,
|
||||||
val type: String,
|
val type: String,
|
||||||
val data: String,
|
val data: String,
|
||||||
)
|
)
|
||||||
data class ChatModel2Data(
|
|
||||||
val content: String,
|
|
||||||
)
|
|
||||||
data class ChatModel2(
|
|
||||||
val id: Int,
|
|
||||||
val role: String,
|
|
||||||
val createTime: String,
|
|
||||||
val type: String,
|
|
||||||
val data: ChatModel2Data,
|
|
||||||
)
|
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package com.nova.brain.glass.model
|
||||||
|
|
||||||
|
|
||||||
|
//{
|
||||||
|
// "code": "0",
|
||||||
|
// "data": {
|
||||||
|
// "action": {
|
||||||
|
// "name": "goToDecisionCenter",
|
||||||
|
// "params": {
|
||||||
|
// "question": "C919第45架机的零部件采购情况"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "message": "home"
|
||||||
|
//}
|
||||||
|
data class RecognizeModel(
|
||||||
|
val code: String,
|
||||||
|
val data: RecognizeModelData,
|
||||||
|
val message: String
|
||||||
|
)
|
||||||
|
|
||||||
|
//{
|
||||||
|
// "action": {
|
||||||
|
// "name": "goToDecisionCenter",
|
||||||
|
// "params": {
|
||||||
|
// "question": "C919第45架机的零部件采购情况"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
data class RecognizeModelData(
|
||||||
|
val action: RecognizeAction,
|
||||||
|
)
|
||||||
|
|
||||||
|
//{
|
||||||
|
// "name": "goToDecisionCenter",
|
||||||
|
// "params": {
|
||||||
|
// "question": "C919第45架机的零部件采购情况"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
data class RecognizeAction(
|
||||||
|
val name: String,
|
||||||
|
val params: RecognizeParams,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class RecognizeParams(
|
||||||
|
val question: String,
|
||||||
|
)
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.nova.brain.glass.model.data
|
||||||
|
|
||||||
|
//{
|
||||||
|
// "text": "查看下C919第45架机的零部件采购情况",
|
||||||
|
// "scence": "home",
|
||||||
|
// "extra": [],
|
||||||
|
// "actions": [
|
||||||
|
// "goToTaskCenter","goToDecisionCenter"
|
||||||
|
// ]
|
||||||
|
//}
|
||||||
|
data class RecognizeData(
|
||||||
|
val text: String,
|
||||||
|
val scence: String = "home",
|
||||||
|
val extra: List<String> = emptyList(),
|
||||||
|
val actions: List<String> = emptyList()
|
||||||
|
)
|
||||||
@ -1,7 +1,9 @@
|
|||||||
package com.nova.brain.glass.repository
|
package com.nova.brain.glass.repository
|
||||||
|
|
||||||
import com.nova.brain.glass.model.ChatModel
|
import com.nova.brain.glass.model.ChatModel
|
||||||
|
import com.nova.brain.glass.model.RecognizeModel
|
||||||
import com.nova.brain.glass.model.data.ChatData
|
import com.nova.brain.glass.model.data.ChatData
|
||||||
|
import com.nova.brain.glass.model.data.RecognizeData
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
@ -19,6 +21,9 @@ interface Service {
|
|||||||
@POST("/cbrain-gateway/cbrain-task-server/cbrain-task/task/glassesSearch")
|
@POST("/cbrain-gateway/cbrain-task-server/cbrain-task/task/glassesSearch")
|
||||||
fun demoPost(@Body body: RequestBody): Observable<ResponseBody>
|
fun demoPost(@Body body: RequestBody): Observable<ResponseBody>
|
||||||
|
|
||||||
|
@POST("/api/intent/recognize")
|
||||||
|
fun recognize(@Body body: RecognizeData): Observable<RecognizeModel>
|
||||||
|
|
||||||
@Streaming
|
@Streaming
|
||||||
@POST("/cbrain-gateway/cbraindep/docqa/chat/qa03")
|
@POST("/cbrain-gateway/cbraindep/docqa/chat/qa03")
|
||||||
fun chat(@Body body: ChatData): Observable<ResponseBody>
|
fun chat(@Body body: ChatData): Observable<ResponseBody>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.nova.brain.glass.ui
|
package com.nova.brain.glass.ui
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.nova.brain.glass.R
|
import com.nova.brain.glass.R
|
||||||
import com.nova.brain.glass.databinding.ActivityChatBinding
|
import com.nova.brain.glass.databinding.ActivityChatBinding
|
||||||
@ -37,11 +38,17 @@ class ChatActivity : BaseListFormLayoutNormalActivity<ChatItem, ChatVM, Activity
|
|||||||
if (lastIndex >= 0) recyclerView.scrollToPosition(lastIndex)
|
if (lastIndex >= 0) recyclerView.scrollToPosition(lastIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.loading.observe(this) { loading ->
|
||||||
|
binding.pb.visibility = if (loading) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.demoPostSse()
|
viewModel.demoPostSse()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun adapter() = object : CommonPagedAdapter<ChatItem>(R.layout.item_chat) {
|
override fun adapter() = object : CommonPagedAdapter<ChatItem>(R.layout.item_chat) {
|
||||||
override fun convert(holder: ViewHolder, item: ChatItem, position: Int) {
|
override fun convert(holder: ViewHolder, item: ChatItem, position: Int) {
|
||||||
|
holder.setVisibility(R.id.line, position!=0)
|
||||||
val chatItems = viewModel.chatItems
|
val chatItems = viewModel.chatItems
|
||||||
val liveItem = if (position < chatItems.size) chatItems[position] else item
|
val liveItem = if (position < chatItems.size) chatItems[position] else item
|
||||||
holder.setText(R.id.title, liveItem.title)
|
holder.setText(R.id.title, liveItem.title)
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import com.nova.brain.glass.model.ChatItem
|
import com.nova.brain.glass.model.ChatItem
|
||||||
import com.nova.brain.glass.model.ChatModel
|
import com.nova.brain.glass.model.ChatModel
|
||||||
import com.nova.brain.glass.model.ChatModel1
|
import com.nova.brain.glass.model.ChatModel1
|
||||||
import com.nova.brain.glass.model.ChatModel2
|
|
||||||
import com.nova.brain.glass.model.data.ChatData
|
import com.nova.brain.glass.model.data.ChatData
|
||||||
import com.nova.brain.glass.repository.Service
|
import com.nova.brain.glass.repository.Service
|
||||||
import com.xuqm.base.common.GsonImplHelp
|
import com.xuqm.base.common.GsonImplHelp
|
||||||
@ -18,6 +17,7 @@ import io.reactivex.schedulers.Schedulers
|
|||||||
|
|
||||||
class ChatVM : BaseListViewModel<ChatItem>() {
|
class ChatVM : BaseListViewModel<ChatItem>() {
|
||||||
val result = MutableLiveData<String>()
|
val result = MutableLiveData<String>()
|
||||||
|
val loading = MutableLiveData<Boolean>()
|
||||||
val chatItems: MutableList<ChatItem> = mutableListOf()
|
val chatItems: MutableList<ChatItem> = mutableListOf()
|
||||||
|
|
||||||
private var currentTask: Disposable? = null
|
private var currentTask: Disposable? = null
|
||||||
@ -52,16 +52,17 @@ class ChatVM : BaseListViewModel<ChatItem>() {
|
|||||||
currentTask = null
|
currentTask = null
|
||||||
|
|
||||||
val question = questions[questionIndex % questions.size]
|
val question = questions[questionIndex % questions.size]
|
||||||
|
val itemId = questionIndex
|
||||||
questionIndex++
|
questionIndex++
|
||||||
|
|
||||||
chatItems.add(ChatItem(question, ""))
|
chatItems.add(ChatItem(itemId, question, ""))
|
||||||
if (dataSourceReady) invalidate()
|
if (dataSourceReady) invalidate()
|
||||||
|
loading.postValue(true)
|
||||||
|
|
||||||
currentTask = HttpManager.getApi(Service::class.java).chat(ChatData(question))
|
currentTask = HttpManager.getApi(Service::class.java).chat(ChatData(question))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe({ body ->
|
.subscribe({ body ->
|
||||||
var content = ""
|
var content = ""
|
||||||
var type = ""
|
|
||||||
body.charStream().buffered().use { reader ->
|
body.charStream().buffered().use { reader ->
|
||||||
try {
|
try {
|
||||||
var line: String?
|
var line: String?
|
||||||
@ -75,38 +76,47 @@ class ChatVM : BaseListViewModel<ChatItem>() {
|
|||||||
if (chatItems.isNotEmpty()) chatItems.removeAt(chatItems.size - 1)
|
if (chatItems.isNotEmpty()) chatItems.removeAt(chatItems.size - 1)
|
||||||
demoPostSse()
|
demoPostSse()
|
||||||
}
|
}
|
||||||
|
loading.postValue(false)
|
||||||
return@use
|
return@use
|
||||||
}
|
}
|
||||||
val json = if (l.startsWith("data:")) l.removePrefix("data:").trim() else l
|
val json = if (l.startsWith("data:")) l.removePrefix("data:").trim() else l
|
||||||
val model = GsonImplHelp.get().toObject(json, ChatModel::class.java)
|
val model = GsonImplHelp.get().toObject(json, ChatModel::class.java)
|
||||||
if (model.type == null) {
|
if (model.type == null) {
|
||||||
result.postValue(model.msg ?: json)
|
loading.postValue(false)
|
||||||
|
val msg = model.msg ?: json
|
||||||
|
val lastIndex = chatItems.size - 1
|
||||||
|
if (lastIndex >= 0) {
|
||||||
|
chatItems[lastIndex].content = msg
|
||||||
|
notifyItem(lastIndex)
|
||||||
|
}
|
||||||
|
result.postValue(msg)
|
||||||
return@use
|
return@use
|
||||||
}
|
}
|
||||||
if (type != model.type) {
|
if (model.role != "assistant" || model.type != "string") continue
|
||||||
content = ""
|
val model1 = GsonImplHelp.get().toObject(json, ChatModel1::class.java)
|
||||||
}
|
content += model1.data
|
||||||
type = model.type
|
|
||||||
if (model.type == "string") {
|
|
||||||
val model1 = GsonImplHelp.get().toObject(json, ChatModel1::class.java)
|
|
||||||
content += model1.data
|
|
||||||
} else {
|
|
||||||
val model2 = GsonImplHelp.get().toObject(json, ChatModel2::class.java)
|
|
||||||
content += model2.data.content
|
|
||||||
}
|
|
||||||
val lastIndex = chatItems.size - 1
|
val lastIndex = chatItems.size - 1
|
||||||
if (lastIndex >= 0) {
|
if (lastIndex >= 0) {
|
||||||
chatItems[lastIndex] = chatItems[lastIndex].copy(content = content)
|
chatItems[lastIndex].content = content
|
||||||
notifyItem(lastIndex)
|
notifyItem(lastIndex)
|
||||||
}
|
}
|
||||||
result.postValue(content)
|
result.postValue(content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
result.postValue("AI反馈异常: ${e.message}")
|
loading.postValue(false)
|
||||||
|
val errMsg = "AI反馈异常: ${e.message}"
|
||||||
|
val lastIndex = chatItems.size - 1
|
||||||
|
if (lastIndex >= 0) {
|
||||||
|
chatItems[lastIndex].content = errMsg
|
||||||
|
notifyItem(lastIndex)
|
||||||
|
}
|
||||||
|
result.postValue(errMsg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loading.postValue(false)
|
||||||
}, { e ->
|
}, { e ->
|
||||||
|
loading.postValue(false)
|
||||||
result.postValue("AI反馈异常: ${e.message}")
|
result.postValue("AI反馈异常: ${e.message}")
|
||||||
})
|
})
|
||||||
currentTask?.also { add(it) }
|
currentTask?.also { add(it) }
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<stroke
|
||||||
|
android:width="2dp"
|
||||||
|
android:color="#ff40FF5E" />
|
||||||
|
<corners android:radius="4dp" />
|
||||||
|
<padding
|
||||||
|
android:bottom="5dp"
|
||||||
|
android:left="10dp"
|
||||||
|
android:right="10dp"
|
||||||
|
android:top="5dp" />
|
||||||
|
</shape>
|
||||||
@ -1,15 +1,52 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layout>
|
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/app_color_black">
|
android:background="@color/app_color_black">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/baseRecyclerView"
|
android:id="@+id/baseRecyclerView"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="400dp"
|
||||||
|
android:background="@drawable/bg_chat"
|
||||||
android:overScrollMode="never" />
|
android:overScrollMode="never" />
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/pb"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/baseRecyclerView"
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:indeterminateDrawable="@drawable/load_progress" />
|
||||||
|
|
||||||
</FrameLayout>
|
<TextView
|
||||||
|
android:id="@+id/hint1"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text='滚动翻页'
|
||||||
|
android:textColor="#ff40FF5E"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/hint2"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/hint2"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text='双击退出'
|
||||||
|
android:textColor="#ff40FF5E"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/hint1"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/baseRecyclerView" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</layout>
|
</layout>
|
||||||
@ -2,19 +2,25 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="30dp"
|
android:layout_marginBottom="15dp"
|
||||||
android:id="@+id/root"
|
android:id="@+id/root"
|
||||||
android:paddingHorizontal="29dp"
|
android:paddingHorizontal="29dp"
|
||||||
android:paddingVertical="10dp"
|
android:paddingVertical="10dp"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
<View
|
||||||
|
android:id="@+id/line"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#ff40FF5E"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="驳回"
|
android:text="驳回"
|
||||||
android:textColor="#2EB242"
|
android:textColor="#2EB242"
|
||||||
android:textSize="10sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/content"
|
android:id="@+id/content"
|
||||||
|
|||||||
@ -6,39 +6,39 @@
|
|||||||
|
|
||||||
<!--android:fillColor="#409CFA"-->
|
<!--android:fillColor="#409CFA"-->
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M523.09,101.85m-101.85,0a101.85,101.85 0,1 0,203.7 0,101.85 101.85,0 1,0 -203.7,0Z"/>
|
android:pathData="M523.09,101.85m-101.85,0a101.85,101.85 0,1 0,203.7 0,101.85 101.85,0 1,0 -203.7,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M769.84,187.51m-96.03,0a96.03,96.03 0,1 0,192.06 0,96.03 96.03,0 1,0 -192.06,0Z"/>
|
android:pathData="M769.84,187.51m-96.03,0a96.03,96.03 0,1 0,192.06 0,96.03 96.03,0 1,0 -192.06,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M903.29,381.4m-90.21,0a90.21,90.21 0,1 0,180.42 0,90.21 90.21,0 1,0 -180.42,0Z"/>
|
android:pathData="M903.29,381.4m-90.21,0a90.21,90.21 0,1 0,180.42 0,90.21 90.21,0 1,0 -180.42,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M905.95,609.72m-84.39,0a84.39,84.39 0,1 0,168.78 0,84.39 84.39,0 1,0 -168.78,0Z"/>
|
android:pathData="M905.95,609.72m-84.39,0a84.39,84.39 0,1 0,168.78 0,84.39 84.39,0 1,0 -168.78,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M800,786.13m-78.57,0a78.57,78.57 0,1 0,157.14 0,78.57 78.57,0 1,0 -157.14,0Z"/>
|
android:pathData="M800,786.13m-78.57,0a78.57,78.57 0,1 0,157.14 0,78.57 78.57,0 1,0 -157.14,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M605.2,889.71m-72.75,0a72.75,72.75 0,1 0,145.5 0,72.75 72.75,0 1,0 -145.5,0Z"/>
|
android:pathData="M605.2,889.71m-72.75,0a72.75,72.75 0,1 0,145.5 0,72.75 72.75,0 1,0 -145.5,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M397.15,877.86m-66.93,0a66.93,66.93 0,1 0,133.86 0,66.93 66.93,0 1,0 -133.86,0Z"/>
|
android:pathData="M397.15,877.86m-66.93,0a66.93,66.93 0,1 0,133.86 0,66.93 66.93,0 1,0 -133.86,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M223.67,762.48m-61.11,0a61.11,61.11 0,1 0,122.22 0,61.11 61.11,0 1,0 -122.22,0Z"/>
|
android:pathData="M223.67,762.48m-61.11,0a61.11,61.11 0,1 0,122.22 0,61.11 61.11,0 1,0 -122.22,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M134.48,587.15m-55.29,0a55.29,55.29 0,1 0,110.58 0,55.29 55.29,0 1,0 -110.58,0Z"/>
|
android:pathData="M134.48,587.15m-55.29,0a55.29,55.29 0,1 0,110.58 0,55.29 55.29,0 1,0 -110.58,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M135.4,408.9m-49.47,0a49.47,49.47 0,1 0,98.94 0,49.47 49.47,0 1,0 -98.94,0Z"/>
|
android:pathData="M135.4,408.9m-49.47,0a49.47,49.47 0,1 0,98.94 0,49.47 49.47,0 1,0 -98.94,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M205.34,260.05m-43.65,0a43.65,43.65 0,1 0,87.3 0,43.65 43.65,0 1,0 -87.3,0Z"/>
|
android:pathData="M205.34,260.05m-43.65,0a43.65,43.65 0,1 0,87.3 0,43.65 43.65,0 1,0 -87.3,0Z"/>
|
||||||
<path
|
<path
|
||||||
android:fillColor="@color/text_black"
|
android:fillColor="#ff40FF5E"
|
||||||
android:pathData="M315.82,159.99m-37.83,0a37.83,37.83 0,1 0,75.66 0,37.83 37.83,0 1,0 -75.66,0Z"/>
|
android:pathData="M315.82,159.99m-37.83,0a37.83,37.83 0,1 0,75.66 0,37.83 37.83,0 1,0 -75.66,0Z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户