Compare commits

..
17 Commits
Author SHA1 Message Date
zhanglei b06a08b029 feat(home): 首页智慧体重/健康档案入口接入H5并切换生产环境
- 智慧体重、健康档案及AI随访banner由占位页改为跳转对应H5页面,
  携带加密参数并增加登录校验
- UrlConfig新增体重管理、健康档案H5地址,baseUrlType切换为PRODUCT
- 版本号升级至1.0.15(1015)
2026-09-04 11:35:40 +08:00
zhanglei 3c90d9f1d3 refactor(emergency): 重构应急就医群聊入口并切换测试环境
- EmergencyFragment: 抽取 startParamedicChat() 公共方法,用 when 表达式
  替代嵌套 if-else,消除单工单与多工单选择两路径的重复代码
- IMInputActionSettingUtils: createEmergencySetting 新增 firstAid 参数,
  支持区分急救员/非急救员的 IM 输入态配置
- UrlConfig: 切换测试环境 API 与 H5 地址(xjxc-api → xj-api.yixiong-tech.com,
  H5 → 10.10.10.228:23006),baseUrlType 由 PRODUCT 切回 TEST 以便联调
2026-08-04 20:03:28 +08:00
zhanglei 5a2963ce32 refactor(web): 优化WebView配置和页面刷新逻辑
- 移除重复的RecyclerView相关导入语句
- 使用SPUtils和CHAT_IS_LIAISON_USER常量替代原有导入
- 将ToastUtil替换为showToast方法
- 设置WebView缓存模式为不缓存
- 在返回事件处理中添加stopLoading调用
- 移除motionClock页面的刷新标志位和相关逻辑
2026-08-04 17:25:46 +08:00
zhangxiao 7a591579a8 feat(chat): 添加联络员用户标识功能
- 引入 CHAT_IS_LIAISON_USER 常量用于标识联络员用户
- 在 EmergencyFragment 中存储联络员状态到 SharedPreferences
- 在 TUIBaseChatActivity 中读取联络员标识并控制布局显示逻辑
- 添加 SPUtils 工具类用于本地数据持久化
- 仅对联络员用户显示带导航栏的聊天界面布局
2026-07-27 18:48:55 +08:00
zhangxiao 41fadb7b75 feat(chat): 添加群成员职位显示和更新功能
- 在 AddMemberActivity 中为 ExpertBean 和 EmployeeBean 添加职位获取方法
- 扩展 AddMemberAdapter 以显示成员职位信息
- 添加 ExpertBean 的 post_dictText 字段用于职位文本显示
- 更新群组聊天界面布局以显示成员职位
- 添加更新群成员按钮和相关功能实现
- 优化群组提示监听器的时序问题处理
- 修改提案页面布局中的占位文本为实际数据绑定
- 添加应急工单对话框的新样式和相关资源文件
2026-07-22 17:14:44 +08:00
zhangxiao c504f23052 feat(chat): 优化群聊功能和界面组件
- 添加群成员头像基地址配置和统一管理
- 重构群成员列表布局和样式调整
- 添加群成员加入提示消息监听和处理机制
- 优化群聊头像加载和默认图标显示
- 重构群聊页面导航和界面元素
- 添加急救订单选择对话框功能
- 优化通话和定位分享功能实现
- 新增文件基地址辅助类和接口定义
- 重构群聊输入组件和布局配置
2026-07-21 18:49:19 +08:00
zhangxiao aee280cf86 refactor(tuichat): 重构添加成员页面UI和交互逻辑
- 将顶部标题栏改为白底黑字风格,调整返回按钮颜色
- 移除原有的Tab标签页,改为搜索框配合分段Tab布局
- 添加搜索框右侧"搜索"文字按钮功能
- 重新设计底部确认按钮为全宽度样式
- 调整导航面板宽度从220dp增加到280dp
- 新增多个颜色值和图形资源用于支持新UI样式
- 更新通话图标和分隔线样式
- 修改应急救援相关API接口和数据模型
- 调整患者信息展示逻辑和界面元素可见性控制
2026-07-21 08:56:38 +08:00
zhangxiao c044b8cbdc feat(chat): 添加群组成员管理功能
- 新增 AddMemberActivity 页面实现选择联系人界面
- 实现双标签页切换(邀请专家/邀请员工)功能
- 添加搜索框支持实时过滤联系人列表
- 集成 RecyclerView 列表展示与多选功能
- 实现底部确认按钮回传选中用户ID列表
- 添加 GroupMemberNavAdapter 群成员导航适配器
- 扩展 GroupMemberInfo 类添加业务字段支持
- 更新聊天导航头部布局优化界面结构
- 新增电话拨打对话框组件支持一键拨号
- 完善群组信息成员详情泛型定义增强类型安全
2026-07-17 17:59:55 +08:00
zhangxiao 14f7542037 feat(chat): 添加群组管理功能和微信分享支持
- 新增 EmployeeBean、ExpertBean 和 GroupMemberBean 数据模型
- 实现群组成员管理接口和操作辅助类
- 添加微信 SDK 依赖并集成位置信息分享功能
- 在聊天界面中实现群成员列表显示和动态更新
- 增加急救员群组创建和管理的相关 API 接口
- 实现群组成员搜索、添加和移除功能
- 添加位置消息长按分享到微信的功能
2026-07-16 18:47:03 +08:00
zhangxiao 7cca7e0b79 feat(chat): 添加群聊右侧导航抽屉和健康档案功能
- 集成 androidx.drawerlayout:drawerlayout:1.2.0 依赖
- 新增 chat_activity_with_navigation.xml 布局文件实现抽屉布局
- 新增 chat_navigation_header.xml 头部布局显示群成员信息
- 在 TUIBaseChatActivity 中实现抽屉打开关闭功能
- 修改 InputView 中的群视频通话逻辑,针对特定包名使用新方案
- 添加 ProposalBean 数据模型用于健康档案信息
- 实现 ProposalActivity 页面展示患者健康档案详情
- 添加 EmergencyApi 接口获取健康档案数据
- 在 HomeFragment 中增加登录验证跳转健康档案页面
- 完善群聊界面右滑抽屉显示群成员列表功能
2026-07-15 17:50:27 +08:00
zhangxiao b29c46b906 feat(chat): 为健康客户端添加位置消息长按功能和应急就医相关功能
- 在LocationMessageHolder中为健康客户端添加位置消息长按监听器
- 优化TUIGroupChatFragment中的代码格式和空格调整
- 在TUIGroupChatFragment中添加对健康客户端的特殊处理逻辑
- 注册ProposalActivity到AndroidManifest.xml
- 添加健康档案页面相关的颜色定义
- 在EmergencyFragment中添加急救人员相关功能和界面元素
- 更新HomeFragment中的导航逻辑以跳转到健康档案页面
- 创建ProposalActivity和ProposalViewModel用于健康档案功能
- 添加应急就医群的相关字符串资源
2026-07-14 19:15:11 +08:00
zhangleiandClaude Opus 4.7 4b5da9269d feat(home): 健康资讯模块增加登录校验及未登录态UI处理
所有健康资讯H5跳转入口(文章详情、健康知识、健康咨询、搜索)增加
登录状态校验,未登录时提示"请先登录"并引导至登录页;健康知识模块
未登录时隐藏Tab栏显示"暂未登录"空态。版本号升至 1.0.14。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 18:22:04 +08:00
zhangleiandClaude Opus 4.7 7a830c3272 fix(home): 修复搜索框自动弹起键盘及H5搜索参数名错误
onResume 时清除搜索框焦点避免页面返回后键盘自动弹出,清除方法
封装为公共方法避免外部直接访问内部 View;修正 H5 搜索页参数名
searchVal → secrchVal 对齐服务端约定。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 15:56:07 +08:00
zhangleiandClaude Opus 4.7 b609f07240 fix(home): 修复健康知识列表项标签过长时与日期重叠
标签文本新增单行省略号处理及右边距限制,移除图片固定居左居中对齐属性,
避免标签文字过长时撑破布局或与右侧日期重叠。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 09:40:49 +08:00
zhangleiandClaude Opus 4.7 c33c76f732 fix(home): 修复健康资讯搜索功能及咨询栏目加载逻辑
搜索框从 TextView 改为 EditText 以支持键盘输入和搜索键触发,
搜索回调携带关键字参数透传到 H5 搜索页。健康咨询栏目从硬编码
categoryId=2 改为从栏目列表动态读取第二个栏目 ID。新增新疆项目
H5 基础地址方法修正生产环境 URL,健康知识 H5 路径回归使用
getHealthNewsH5BaseUrl 避免丢失 healthnewsweb 路径层级。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-30 09:22:07 +08:00
zhangleiandClaude Opus 4.7 bb23c00e9c fix(home): 修正搜索栏布局及Tab样式细节
搜索框从EditText改为TextView入口,搜索按钮改为主题色圆角按钮,
Tab文字颜色统一引用子Tab专用选择器,drawable颜色引用修正为主题色。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-29 16:48:26 +08:00
zhangleiandClaude Opus 4.7 f5be575491 feat(home): 新增健康资讯模块(健康知识 + 健康咨询)
采用 HMAC-SHA256 签名认证获取 Token,通过栏目/文章 API 获取数据,
详情/更多/搜索均跳转 H5 页面。同时新增带下划线指示器的 Tab 样式。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-29 16:47:46 +08:00
87 changed files with 4979 additions and 59 deletions
+1 -1
View File
@@ -137,5 +137,5 @@ dependencies {
//JSoup //JSoup
api 'org.jsoup:jsoup:1.12.1' api 'org.jsoup:jsoup:1.12.1'
implementation 'com.tencent.mm.opensdk:wechat-sdk-android:+'
} }
+2 -2
View File
@@ -199,7 +199,7 @@
android:screenOrientation="portrait"/> android:screenOrientation="portrait"/>
<activity android:name=".ui.activity.EmptyActivity" <activity android:name=".ui.activity.EmptyActivity"
android:screenOrientation="portrait"/> android:screenOrientation="portrait"/>
<activity android:name=".ui.activity.ProposalActivity"
android:screenOrientation="portrait"/>
</application> </application>
</manifest> </manifest>
@@ -6,6 +6,7 @@ import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Message import android.os.Message
import android.util.Log
import android.view.Gravity import android.view.Gravity
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
@@ -19,9 +20,18 @@ import com.permissionx.guolindev.PermissionX
import com.sw.healthyclients.data.local.DataStoreManager import com.sw.healthyclients.data.local.DataStoreManager
import com.sw.healthyclients.utils.CustomActivityManager import com.sw.healthyclients.utils.CustomActivityManager
import com.sw.healthyclients.view.CustomToast import com.sw.healthyclients.view.CustomToast
import com.tencent.mm.opensdk.modelmsg.SendMessageToWX
import com.tencent.mm.opensdk.modelmsg.WXMediaMessage
import com.tencent.mm.opensdk.modelmsg.WXWebpageObject
import com.tencent.mm.opensdk.openapi.IWXAPI
import com.tencent.mm.opensdk.openapi.WXAPIFactory
import com.tencent.qcloud.tuicore.TUICore import com.tencent.qcloud.tuicore.TUICore
import com.tencent.qcloud.tuikit.tuichat.TUIChatService import com.tencent.qcloud.tuikit.tuichat.TUIChatService
import com.tencent.qcloud.tuikit.tuichat.classicui.event.IMChatEvent import com.tencent.qcloud.tuikit.tuichat.classicui.event.IMChatEvent
import com.tencent.qcloud.tuikit.tuichat.interfaces.FileBaseUrlListener
import com.tencent.qcloud.tuikit.tuichat.interfaces.ShareToWeChatListener
import com.tencent.qcloud.tuikit.tuichat.presenter.FileBaseUrlHelper
import com.tencent.qcloud.tuikit.tuichat.presenter.WeChatShareHelper
import com.xjjk.healthyclients.base.BaseVMBActivity import com.xjjk.healthyclients.base.BaseVMBActivity
import com.xjjk.healthyclients.bean.CardInfoBean import com.xjjk.healthyclients.bean.CardInfoBean
import com.xjjk.healthyclients.bottomtab.HomeBottomTabLayout import com.xjjk.healthyclients.bottomtab.HomeBottomTabLayout
@@ -32,6 +42,7 @@ import com.xjjk.healthyclients.fragment.EmergencyFragment
import com.xjjk.healthyclients.fragment.GuidanceFragment import com.xjjk.healthyclients.fragment.GuidanceFragment
import com.xjjk.healthyclients.fragment.HomeFragment import com.xjjk.healthyclients.fragment.HomeFragment
import com.xjjk.healthyclients.fragment.MonitorFragment import com.xjjk.healthyclients.fragment.MonitorFragment
import com.xjjk.healthyclients.retrofit.UrlConfig
import com.xjjk.healthyclients.superfuntion.loginIm import com.xjjk.healthyclients.superfuntion.loginIm
import com.xjjk.healthyclients.superfuntion.startAllDoctorActivity import com.xjjk.healthyclients.superfuntion.startAllDoctorActivity
import com.xjjk.healthyclients.superfuntion.startLoginActivity import com.xjjk.healthyclients.superfuntion.startLoginActivity
@@ -68,6 +79,42 @@ class MainActivity : BaseVMBActivity<MainViewModel, ActivityMainBinding>(R.layou
Manifest.permission.POST_NOTIFICATIONS Manifest.permission.POST_NOTIFICATIONS
) )
val APP_ID: String = "wxb33cd60beda0a212"
private var api: IWXAPI? = null
private val shareToWeChatListener = ShareToWeChatListener { lat, lon, desc ->
val url = ("https://ditu.amap.com/regeo?lng=" + lon
+ "&lat=" + lat + "&name=" + desc + "&src=uriapi&innersrc=uriapi")
Log.i("TAGG", url)
val webpage = WXWebpageObject()
webpage.webpageUrl = url
val msg = WXMediaMessage(webpage)
msg.title = desc
msg.description = desc
val req = SendMessageToWX.Req()
req.transaction = System.currentTimeMillis().toString()
req.message = msg
req.scene = SendMessageToWX.Req.WXSceneSession
api?.sendReq(req)
}
private val fileBaseUrlListener = FileBaseUrlListener { UrlConfig.IMAGE_BASE_URL }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
regToWx()
WeChatShareHelper.getInstance().setListener(shareToWeChatListener)
FileBaseUrlHelper.getInstance().setListener(fileBaseUrlListener)
}
private fun regToWx() {
// 通过 WXAPIFactory 工厂,获取 IWXAPI 的实例
api = WXAPIFactory.createWXAPI(this, APP_ID, false);
// 将应用的 appId 注册到微信
api?.registerApp(APP_ID);
}
override fun initView(savedInstanceState: Bundle?) { override fun initView(savedInstanceState: Bundle?) {
UpdateBuilder.create().check()// 启动更新任务 UpdateBuilder.create().check()// 启动更新任务
@@ -81,9 +128,9 @@ class MainActivity : BaseVMBActivity<MainViewModel, ActivityMainBinding>(R.layou
// main_tab_layout.setUnreadTip(TAG_INDEX, "99+") // main_tab_layout.setUnreadTip(TAG_INDEX, "99+")
// main_tab_layout.setUnreadTip(TAG_COLLECT, null, false) // main_tab_layout.setUnreadTip(TAG_COLLECT, null, false)
} }
} }
override fun initData() { override fun initData() {
// if(DataStoreManager.isLogin()){ // if(DataStoreManager.isLogin()){
// getAppViewModel().getIMSig(successCall = { // getAppViewModel().getIMSig(successCall = {
@@ -0,0 +1,27 @@
package com.xjjk.healthyclients.adapter
import android.widget.ImageView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.xjjk.healthyclients.R
import com.xjjk.healthyclients.bean.home.ArticleBean
import com.xjjk.healthyclients.superfuntion.loadRoundedImage
import com.xjjk.healthyclients.superfuntion.orEmptyDefault
/**
* 健康咨询列表 Adapter
*/
class HealthConsultationAdapter :
BaseQuickAdapter<ArticleBean, BaseViewHolder>(R.layout.item_health_consultation) {
override fun convert(holder: BaseViewHolder, item: ArticleBean) {
// 标题
holder.setText(R.id.tv_title, item.articleTitle.orEmptyDefault())
// 收藏和分享数
holder.setText(R.id.tv_meta, "收藏 ${item.favoriteCount} 分享 ${item.likeCount}")
// 封面图片 80x60 圆角8
holder.getView<ImageView>(R.id.iv_cover)?.loadRoundedImage(
item.articleHeaderimage, 8f,R.mipmap.ic_placeholder_rectangle
)
}
}
@@ -0,0 +1,32 @@
package com.xjjk.healthyclients.adapter
import android.widget.ImageView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.sw.healthyclients.utils.DateUtil
import com.xjjk.healthyclients.R
import com.xjjk.healthyclients.bean.home.ArticleBean
import com.xjjk.healthyclients.superfuntion.loadRoundedImage
import com.xjjk.healthyclients.superfuntion.orEmptyDefault
/**
* 健康知识列表 Adapter
*/
class HealthKnowledgeAdapter :
BaseQuickAdapter<ArticleBean, BaseViewHolder>(R.layout.item_health_knowledge) {
override fun convert(holder: BaseViewHolder, item: ArticleBean) {
// 封面图片 100x100 圆角15
holder.getView<ImageView>(R.id.iv_cover)?.loadRoundedImage(
item.articleHeaderimage, 15f, R.mipmap.ic_placeholder_square,
)
// 标题
holder.setText(R.id.tv_title, item.articleTitle.orEmptyDefault())
// 摘要
holder.setText(R.id.tv_detail, item.articleSubtitle.orEmptyDefault(""))
// 标签文本
holder.setText(R.id.tv_tag, item.articleTag.orEmptyDefault())
// 日期
holder.setText(R.id.tv_date, DateUtil.long2ShortDateStr(item.createTime))
}
}
@@ -0,0 +1,182 @@
package com.xjjk.healthyclients.bankRequest
import com.sw.healthyclients.data.local.DataStoreManager
import com.xjjk.healthyclients.bean.home.ArticleBean
import com.xjjk.healthyclients.bean.home.ArticleListBean
import com.xjjk.healthyclients.bean.home.CategoryBean
import com.xjjk.healthyclients.data.api.CategoryListResponse
import com.xjjk.healthyclients.data.api.HealthInfoApi
import com.xjjk.healthyclients.data.api.TokenResponse
import com.xjjk.healthyclients.retrofit.UrlConfig
import com.xjjk.healthyclients.retrofit.getBankRetrofit
import com.xjjk.healthyclients.superfuntion.toJson
import com.xjjk.healthyclients.utils.SignatureUtils
import okhttp3.RequestBody.Companion.toRequestBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
/**
* 健康资讯网络请求封装类
* 负责 Token 获取(签名认证)、栏目列表、文章列表的 API 调用
*/
class HealthInfoRequest {
private val api: HealthInfoApi = getBankRetrofit()
.create(HealthInfoApi::class.java)
companion object {
/** 缓存的 Token,避免重复请求 */
private var cachedToken: String? = null
}
/**
* 获取 Token(带 HMAC-SHA256 签名)
*/
fun fetchToken(
onSuccess: (String) -> Unit,
onFailure: (Throwable) -> Unit
) {
// 如果已有缓存 Token,直接返回
cachedToken?.let {
onSuccess(it)
return
}
try {
val timestamp = System.currentTimeMillis() / 1000
val userId = DataStoreManager.getUserId() ?: ""
val workNo = DataStoreManager.getUserInfo()?.workNo ?: ""
val bodyString = """{"userId":"$userId","workNo":"$workNo"}"""
val sign = SignatureUtils.generateSignature(timestamp, bodyString, UrlConfig.SECRET_KEY)
val headers = mapOf(
"Content-Type" to "application/json; charset=utf-8",
"X-Timestamp" to timestamp.toString(),
"X-Sign" to sign
)
val body = mapOf("userId" to userId, "workNo" to workNo)
api.getToken(headers, body.toJson().toRequestBody())
.enqueue(object : Callback<TokenResponse> {
override fun onResponse(
call: Call<TokenResponse>,
response: Response<TokenResponse>
) {
if (response.code() == 200) {
val token = response.body()?.data?.token
if (!token.isNullOrEmpty()) {
cachedToken = token
onSuccess(token)
} else {
onFailure(Exception("Token 为空"))
}
} else {
onFailure(Exception("HTTP ${response.code()}: ${response.message()}"))
}
}
override fun onFailure(
call: Call<TokenResponse>,
t: Throwable
) {
onFailure(t)
}
})
} catch (e: Exception) {
onFailure(e)
}
}
/**
* 获取栏目列表
*/
fun fetchCategoryList(
token: String,
onSuccess: (MutableList<CategoryBean>) -> Unit,
onFailure: (Throwable) -> Unit
) {
try {
val headers = mapOf("token" to token)
api.getCategoryList(headers)
.enqueue(object : Callback<CategoryListResponse> {
override fun onResponse(
call: Call<CategoryListResponse>,
response: Response<CategoryListResponse>
) {
if (response.code() == 200) {
val data = response.body()?.data ?: mutableListOf()
onSuccess(data)
} else {
onFailure(Exception("HTTP ${response.code()}: ${response.message()}"))
}
}
override fun onFailure(
call: Call<CategoryListResponse>,
t: Throwable
) {
onFailure(t)
}
})
} catch (e: Exception) {
onFailure(e)
}
}
/**
* 分页查询文章列表
*
* @param token 认证 Token
* @param categoryId 栏目 ID
* @param pageNum 页码
* @param pageSize 每页数量
* @param articleType 文章类型,"0"-图文,"1"-视频,不传则全部
*/
fun fetchArticleList(
token: String,
categoryId: Int,
pageNum: Int = 1,
pageSize: Int = 3,
onSuccess: (MutableList<ArticleBean>?) -> Unit,
onFailure: (Throwable) -> Unit
) {
try {
val headers = mapOf("token" to token)
val params = mapOf(
"categoryId" to categoryId.toString(),
"pageNum" to pageNum.toString(),
"pageSize" to pageSize.toString(),
"showAppHomepage" to "Y"
)
api.getArticleList(headers, params)
.enqueue(object : Callback<ArticleListBean> {
override fun onResponse(
call: Call<ArticleListBean>,
response: Response<ArticleListBean>
) {
if (response.code() == 200) {
val body = response.body()
onSuccess(body?.rows)
} else {
onFailure(Exception("HTTP ${response.code()}: ${response.message()}"))
}
}
override fun onFailure(call: Call<ArticleListBean>, t: Throwable) {
onFailure(t)
}
})
} catch (e: Exception) {
onFailure(e)
}
}
/** 清除缓存的 Token(登录态变化时调用) */
fun clearToken() {
cachedToken = null
}
}
@@ -0,0 +1,15 @@
package com.xjjk.healthyclients.bean.emergency
data class GroupInfo(
val orderId: String,
val sessionId: String,
val salvageUserName: String,
val salvageUserSex: String,
val salvageUserAvatar: String,
val salvageUserAge: Int,
val salvageUserMobile: String,
val orgName: String,
val deptName: String,
val orderStatus: String,
val initTime: String
)
@@ -0,0 +1,53 @@
package com.xjjk.healthyclients.bean.home
import com.google.gson.annotations.SerializedName
/**
* 获取 token 响应
*/
data class TokenBean(
@SerializedName("token") val token: String? = null
)
/**
* 栏目分类
*/
data class CategoryBean(
@SerializedName("categoryId") val categoryId: Int = 0,
@SerializedName("categoryName") val categoryName: String? = null,
@SerializedName("categoryStatus") val categoryStatus: String? = null,
@SerializedName("children") val children: MutableList<CategoryBean>? = null,
@SerializedName("parentId") val parentId: Int = 0,
@SerializedName("sortOrder") val sortOrder: Int = 0
)
/**
* 文章
*/
data class ArticleBean(
@SerializedName("articleId") val articleId: Int = 0,
@SerializedName("articleTitle") val articleTitle: String? = null,
@SerializedName("articleSubtitle") val articleSubtitle: String? = null,
@SerializedName("articleTag") val articleTag: String? = null,
@SerializedName("articleHeaderimage") val articleHeaderimage: String? = null,
@SerializedName("articleType") val articleType: String? = null,
@SerializedName("articleExcerpt") val articleExcerpt: String? = null,
@SerializedName("articleContent") val articleContent: String? = null,
@SerializedName("articleVideo") val articleVideo: String? = null,
@SerializedName("favoriteCount") val favoriteCount: Int = 0,
@SerializedName("likeCount") val likeCount: Int = 0,
@SerializedName("viewCount") val viewCount: Int = 0,
@SerializedName("createTime") val createTime: String? = null,
@SerializedName("categoryId") val categoryId: Int = 0,
@SerializedName("articleScore") val articleScore: Double = 0.0,
@SerializedName("articleStatus") val articleStatus: String? = null,
@SerializedName("showAppHomepage") val showAppHomepage: String? = null
)
/**
* 文章列表分页响应
*/
data class ArticleListBean(
@SerializedName("rows") val rows: MutableList<ArticleBean>? = null,
@SerializedName("total") val total: Int = 0
)
@@ -58,3 +58,73 @@ data class HomeBankBean(
val totalPoints: String? val totalPoints: String?
) )
data class ProposalBean(
val id: String,
val empId: String,
val name: String,
val age: Int,
val sexCode: String?,
val workUnit: String?,
val careLiaisonName: String?,
val idNo: String?,
val phone: String?,
val careStatus: String,
val dataLevel: Int,
val negativeList: String,
val caseInfo: String,
val riskLevel: String,
val year: String,
val flagFat: Int,
val bmi: String,
val height: String,
val weight: String,
val targetWeight: String,
val targetBmi: String,
val bmiCurrent: String,
val waistNew: String,
val bodyFatPercentNew: String,
val weightRiskType: String,
val hypertension: Int,
val systolicPressureAvg: String?,
val systolicPressureTarget: String?,
val systolicPressureCurrent: String?,
val diastolicPressureAvg: String?,
val diastolicPressureTarget: String?,
val diastolicPressureCurrent: String?,
val diabetes: Int,
val glu: String,
val bloodSugarTarget: String?,
val bloodSugarCurrent: String?,
val ldl: String,
val ldlTarget: String,
val tc: String,
val tcTarget: String,
val tg: String,
val tgTarget: String,
val uricAcid: String,
val uricAcidTarget: String,
val homocysteine: String,
val homocysteineTarget: String,
val bloodK: String,
val chd: String,
val cvd: String,
val af: String,
val ca: String,
val indicatorListStr: String,
val indicatorListStrOrigin: String,
val screeningProjects: String,
val treatPlan: String,
val treatPlanResponse: String,
val dietSuggestion: String,
val dietSuggestionResponse: String,
val sportGuide: String,
val sportGuideResponse: String,
val lifeManage: String,
val lifeManageResponse: String,
val cabinOpinion: String?,
val cabinOpinionTime: String,
val cabinOpinionUserName: String,
val expertOpinion: String?,
val expertOpinionTime: String,
val expertOpinionUserName: String
)
@@ -1,14 +1,20 @@
package com.xjjk.healthyclients.data.api package com.xjjk.healthyclients.data.api
import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean
import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean
import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean
import com.xjjk.healthyclients.bean.emergency.BigDiseaseBean import com.xjjk.healthyclients.bean.emergency.BigDiseaseBean
import com.xjjk.healthyclients.bean.emergency.BigDiseaseDetailsBean import com.xjjk.healthyclients.bean.emergency.BigDiseaseDetailsBean
import com.xjjk.healthyclients.bean.emergency.EmergencyGroupInfo import com.xjjk.healthyclients.bean.emergency.EmergencyGroupInfo
import com.xjjk.healthyclients.bean.emergency.GetOrderBySessionIdBean import com.xjjk.healthyclients.bean.emergency.GetOrderBySessionIdBean
import com.xjjk.healthyclients.bean.emergency.GroupInfo
import com.xjjk.healthyclients.bean.emergency.HospitalBean import com.xjjk.healthyclients.bean.emergency.HospitalBean
import com.xjjk.healthyclients.bean.emergency.LocationResourceBean import com.xjjk.healthyclients.bean.emergency.LocationResourceBean
import com.xjjk.healthyclients.bean.emergency.OrderThroughBean import com.xjjk.healthyclients.bean.emergency.OrderThroughBean
import com.xjjk.healthyclients.bean.emergency.initUserOrderPageBean import com.xjjk.healthyclients.bean.emergency.initUserOrderPageBean
import com.xjjk.healthyclients.bean.home.ProposalBean
import com.xjjk.healthyclients.data.bean.ApiResponse import com.xjjk.healthyclients.data.bean.ApiResponse
import com.xjjk.healthyclients.data.bean.PageBean
import okhttp3.RequestBody import okhttp3.RequestBody
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET import retrofit2.http.GET
@@ -82,5 +88,51 @@ interface EmergencyApi {
*/ */
@GET("/health-emergency/api/emergency/createGroupMag") @GET("/health-emergency/api/emergency/createGroupMag")
suspend fun getIMGroupInfo(@QueryMap params: MutableMap<String, Any?>): ApiResponse<EmergencyGroupInfo> suspend fun getIMGroupInfo(@QueryMap params: MutableMap<String, Any?>): ApiResponse<EmergencyGroupInfo>
/**
* 获取急救员群组信息
*/
@GET("/health-emergency/api/emergency/createGroupMagFirstAider")
suspend fun getParamedicGroupInfo(@QueryMap params: MutableMap<String, Any?>): ApiResponse<EmergencyGroupInfo>
/**
* 搜索专家(专业人员)
*/
@GET("/health-emergency/api/emergency/order/searchExpert")
suspend fun searchExpert(@QueryMap params: MutableMap<String, Any?>): ApiResponse<PageBean<ExpertBean>>
/**
* 搜索员工
*/
@GET("/health-emergency/api/emergency/order/searchEmployee")
suspend fun searchEmployee(@QueryMap params: MutableMap<String, Any?>): ApiResponse<PageBean<EmployeeBean>>
/**
* 实际群成员列表
*/
@GET("/health-emergency/api/emergency/order/getActualGroupMemberList")
suspend fun getActualGroupMemberList(@QueryMap params: MutableMap<String, Any?>): ApiResponse<List<GroupMemberBean>>
/**
* 邀请进群
*/
@POST("/health-emergency/api/emergency/addGroupUser")
suspend fun addGroupUser(@Body requestBody: RequestBody): ApiResponse<Boolean>
/**
* 移除群成员
*/
@POST("/health-emergency/api/emergency/removeGroupUser")
suspend fun removeGroupUser(@Body requestBody: RequestBody): ApiResponse<Boolean>
/**
* 获取一人一案
*/
@GET("/health-emergency/emergency/LargeScreenNew/onePersonCase")
suspend fun getProposalInfo(): ApiResponse<ProposalBean>
/**
* 关爱联络员身份判断
*/
@GET("/health-emergency/emergency/LargeScreenNew/isLiaisonUser")
suspend fun isLiaisonUser(): ApiResponse<Boolean>
/**
* 当前登录人参与的应急工单列表
*/
@GET("/health-emergency/api/emergency/order/myParticipatedOrders")
suspend fun getParticipatedOrders (): ApiResponse<PageBean<GroupInfo>>
} }
@@ -0,0 +1,63 @@
package com.xjjk.healthyclients.data.api
import com.xjjk.healthyclients.bean.home.ArticleListBean
import com.xjjk.healthyclients.bean.home.CategoryBean
import com.xjjk.healthyclients.bean.home.TokenBean
import com.xjjk.healthyclients.retrofit.UrlConfig
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.HeaderMap
import retrofit2.http.POST
import retrofit2.http.QueryMap
/**
* 健康资讯 API 接口(使用银行 Retrofit 实例,baseUrl 为 getDefaultBankBaseUrl()
*/
interface HealthInfoApi {
/**
* 获取 Token(带签名认证)
*/
@POST("${UrlConfig.middleCheck}pe/frontend/init")
fun getToken(
@HeaderMap headers: Map<String, String>,
@Body requestBody: RequestBody
): Call<TokenResponse>
/**
* 获取栏目列表
*/
@GET("${UrlConfig.middleCheck}cms/frontend/category/list")
fun getCategoryList(
@HeaderMap headers: Map<String, String>
): Call<CategoryListResponse>
/**
* 分页查询文章列表
*/
@GET("${UrlConfig.middleCheck}cms/frontend/articleList")
fun getArticleList(
@HeaderMap headers: Map<String, String>,
@QueryMap params: Map<String, String>
): Call<ArticleListBean>
}
/**
* Token 接口响应外层
*/
data class TokenResponse(
val msg: String? = null,
val code: Int = 0,
val data: TokenBean? = null
)
/**
* 栏目列表接口响应外层
*/
data class CategoryListResponse(
val msg: String? = null,
val code: Int = 0,
val data: MutableList<CategoryBean>? = null
)
@@ -0,0 +1,21 @@
package com.xjjk.healthyclients.data.bean
/**
* 通用分页数据包装类
*
* 用于后端返回 MyBatis-Plus 风格的分页结构,实际列表数据位于 [records] 字段中。
*
* @param T 列表元素类型
*/
data class PageBean<T>(
/** 数据列表 */
val records: List<T>?,
/** 总记录数 */
val total: Int = 0,
/** 每页大小 */
val size: Int = 0,
/** 当前页码 */
val current: Int = 0,
/** 总页数 */
val pages: Int = 0
)
@@ -1,5 +1,8 @@
package com.xjjk.healthyclients.data.repository package com.xjjk.healthyclients.data.repository
import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean
import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean
import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean
import com.xjjk.healthyclients.base.repository.BaseRepository import com.xjjk.healthyclients.base.repository.BaseRepository
import com.xjjk.healthyclients.bean.CommonSettingMenuBean import com.xjjk.healthyclients.bean.CommonSettingMenuBean
import com.xjjk.healthyclients.bean.emergency.AddBigDiseaseSubmitBean import com.xjjk.healthyclients.bean.emergency.AddBigDiseaseSubmitBean
@@ -7,12 +10,15 @@ import com.xjjk.healthyclients.bean.emergency.BigDiseaseBean
import com.xjjk.healthyclients.bean.emergency.BigDiseaseDetailsBean import com.xjjk.healthyclients.bean.emergency.BigDiseaseDetailsBean
import com.xjjk.healthyclients.bean.emergency.EmergencyGroupInfo import com.xjjk.healthyclients.bean.emergency.EmergencyGroupInfo
import com.xjjk.healthyclients.bean.emergency.GetOrderBySessionIdBean import com.xjjk.healthyclients.bean.emergency.GetOrderBySessionIdBean
import com.xjjk.healthyclients.bean.emergency.GroupInfo
import com.xjjk.healthyclients.bean.emergency.HospitalBean import com.xjjk.healthyclients.bean.emergency.HospitalBean
import com.xjjk.healthyclients.bean.emergency.LocationResourceBean import com.xjjk.healthyclients.bean.emergency.LocationResourceBean
import com.xjjk.healthyclients.bean.emergency.OrderThroughBean import com.xjjk.healthyclients.bean.emergency.OrderThroughBean
import com.xjjk.healthyclients.bean.emergency.initUserOrderPageBean import com.xjjk.healthyclients.bean.emergency.initUserOrderPageBean
import com.xjjk.healthyclients.bean.home.ProposalBean
import com.xjjk.healthyclients.data.api.EmergencyApi import com.xjjk.healthyclients.data.api.EmergencyApi
import com.xjjk.healthyclients.data.bean.ApiResponse import com.xjjk.healthyclients.data.bean.ApiResponse
import com.xjjk.healthyclients.data.bean.PageBean
import com.xjjk.healthyclients.retrofit.RetrofitManager import com.xjjk.healthyclients.retrofit.RetrofitManager
import com.xjjk.healthyclients.retrofit.RetrofitManager.toRequestBody import com.xjjk.healthyclients.retrofit.RetrofitManager.toRequestBody
import com.xjjk.healthyclients.superfuntion.toJson import com.xjjk.healthyclients.superfuntion.toJson
@@ -107,8 +113,6 @@ object EmergencyRepository : BaseRepository() {
return CommonRepository.getCommonSettingMenuList("category") return CommonRepository.getCommonSettingMenuList("category")
} }
suspend fun getIMGroupInfo(groupName: String, longitude: Double, suspend fun getIMGroupInfo(groupName: String, longitude: Double,
latitude: Double): ApiResponse<EmergencyGroupInfo> { latitude: Double): ApiResponse<EmergencyGroupInfo> {
var map = mutableMapOf<String, Any?>() var map = mutableMapOf<String, Any?>()
@@ -118,4 +122,68 @@ object EmergencyRepository : BaseRepository() {
return apiCall { service.getIMGroupInfo(map) } return apiCall { service.getIMGroupInfo(map) }
} }
suspend fun getParamedicGroupInfo(groupName: String, longitude: Double,
latitude: Double): ApiResponse<EmergencyGroupInfo> {
var map = mutableMapOf<String, Any?>()
map["longitude"] = longitude
map["latitude"] = latitude
map["name"] = groupName //群聊名称改为后台生成
return apiCall { service.getParamedicGroupInfo(map) }
}
suspend fun searchExpert(realname: String, centerId: String, excludeSessionId: String, pageNo: Int, pageSize: Int): ApiResponse<PageBean<ExpertBean>> {
val map = mutableMapOf<String, Any?>()
map["realname"] = realname
map["centerId"] = centerId
map["excludeSessionId"] = excludeSessionId
map["pageNo"] = pageNo
map["pageSize"] = pageSize
return apiCall { service.searchExpert(map) }
}
suspend fun searchEmployee(realname: String, orgCode: String, workNo: String, phone: String, excludeSessionId: String, pageNo: Int, pageSize: Int): ApiResponse<PageBean<EmployeeBean>> {
val map = mutableMapOf<String, Any?>()
map["realname"] = realname
map["orgCode"] = orgCode
map["workNo"] = workNo
map["phone"] = phone
map["excludeSessionId"] = excludeSessionId
map["pageNo"] = pageNo
map["pageSize"] = pageSize
return apiCall { service.searchEmployee(map) }
}
suspend fun getActualGroupMemberList(sessionId: String): ApiResponse<List<GroupMemberBean>> {
val map = mutableMapOf<String, Any?>()
map["sessionId"] = sessionId
return apiCall { service.getActualGroupMemberList(map) }
}
suspend fun addGroupUser(groupId: String, memberList: List<String>,
memberType: Int): ApiResponse<Boolean> {
val map = mutableMapOf<String, Any?>()
map["groupId"] = groupId
map["memberList"] = memberList
map["memberType"] = memberType
return apiCall { service.addGroupUser(map.toJson().toRequestBody()) }
}
suspend fun removeGroupUser(groupId: String, memberList: List<String>): ApiResponse<Boolean> {
val map = mutableMapOf<String, Any?>()
map["groupId"] = groupId
map["memberList"] = memberList
return apiCall { service.removeGroupUser(map.toJson().toRequestBody()) }
}
suspend fun getProposalInfo(): ApiResponse<ProposalBean> {
return apiCall { service.getProposalInfo() }
}
suspend fun isLiaisonUser(): ApiResponse<Boolean> {
return apiCall { service.isLiaisonUser() }
}
suspend fun getParticipatedOrders(): ApiResponse<PageBean<GroupInfo>> {
return apiCall { service.getParticipatedOrders() }
}
} }
@@ -1,19 +1,26 @@
package com.xjjk.healthyclients.fragment package com.xjjk.healthyclients.fragment
import android.Manifest import android.Manifest
import android.app.Dialog
import android.content.Intent import android.content.Intent
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.graphics.Color import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.ColorDrawable
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.view.WindowManager
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.util.Consumer
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.amap.api.location.AMapLocation import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption import com.amap.api.location.AMapLocationClientOption
@@ -30,12 +37,23 @@ import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.MyLocationStyle import com.amap.api.maps.model.MyLocationStyle
import com.permissionx.guolindev.PermissionX import com.permissionx.guolindev.PermissionX
import com.tencent.qcloud.tuicore.util.SPUtils
import com.tencent.qcloud.tuikit.tuichat.TUIChatConstants.CHAT_IS_LIAISON_USER
import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean
import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean
import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean
import com.tencent.qcloud.tuikit.tuichat.bean.WorkBean import com.tencent.qcloud.tuikit.tuichat.bean.WorkBean
import com.tencent.qcloud.tuikit.tuichat.classicui.interfaces.OnParamedicOperateListener
import com.tencent.qcloud.tuikit.tuichat.presenter.ParamedicOperateHelper
import com.xjjk.healthyclients.R import com.xjjk.healthyclients.R
import com.xjjk.healthyclients.base.BaseVMBFragment import com.xjjk.healthyclients.base.BaseVMBFragment
import com.xjjk.healthyclients.bean.emergency.EmergencyDictBean import com.xjjk.healthyclients.bean.emergency.EmergencyDictBean
import com.xjjk.healthyclients.bean.emergency.GroupInfo
import com.xjjk.healthyclients.bean.emergency.LocationResourceBean import com.xjjk.healthyclients.bean.emergency.LocationResourceBean
import com.xjjk.healthyclients.data.repository.EmergencyRepository
import com.xjjk.healthyclients.databinding.DialogGroupInfoListBinding
import com.xjjk.healthyclients.databinding.FragmentEmergencyBinding import com.xjjk.healthyclients.databinding.FragmentEmergencyBinding
import com.xjjk.healthyclients.fragment.adapter.GroupInfoAdapter
import com.xjjk.healthyclients.superfuntion.getMarkerInfo import com.xjjk.healthyclients.superfuntion.getMarkerInfo
import com.xjjk.healthyclients.superfuntion.startGroupChat import com.xjjk.healthyclients.superfuntion.startGroupChat
import com.xjjk.healthyclients.ui.viewmodel.EmergencyViewModel import com.xjjk.healthyclients.ui.viewmodel.EmergencyViewModel
@@ -43,8 +61,12 @@ import com.xjjk.healthyclients.utils.IMInputActionSettingUtils
import com.xjjk.healthyclients.utils.MapUtils import com.xjjk.healthyclients.utils.MapUtils
import com.xjjk.healthyclients.utils.SystemFuntion.goNavigation import com.xjjk.healthyclients.utils.SystemFuntion.goNavigation
import com.xjjk.healthyclients.utils.TUIUtils import com.xjjk.healthyclients.utils.TUIUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeoutOrNull
/** /**
@@ -76,6 +98,100 @@ class EmergencyFragment :
) )
var mListener: LocationSource.OnLocationChangedListener? = null var mListener: LocationSource.OnLocationChangedListener? = null
private val paramedicOperateListener = object : OnParamedicOperateListener {
override fun addGroupUser(
groupId: String,
memberList: List<String>,
memberType: Int,
callback: Consumer<Boolean>
) {
// 通过 successCall 把 ViewModel 的操作结果回传给 tuichat 模块
mViewModel.addGroupUser(groupId, memberList, memberType) { success ->
callback.accept(success)
}
}
override fun removeGroupUser(groupId: String, memberList: List<String>) {
mViewModel.removeGroupUser(groupId, memberList)
}
override fun searchEmployee(
realname: String?,
orgCode: String?,
workNo: String?,
phone: String?,
excludeSessionId: String?,
pageNo: Int,
pageSize: Int
): List<EmployeeBean?>? {
return runBlocking(Dispatchers.IO) {
try {
val deferred = async {
EmergencyRepository.searchEmployee(
realname ?: "",
orgCode ?: "",
workNo ?: "",
phone ?: "",
excludeSessionId ?: "",
pageNo,
pageSize
)
}
val response = withTimeoutOrNull(10000L) { deferred.await() }
?: return@runBlocking emptyList<EmployeeBean>()
response.takeIf { it.success }?.result?.records ?: emptyList()
} catch (e: Exception) {
emptyList()
}
}
}
override fun searchExpert(
realname: String?,
centerId: String?,
excludeSessionId: String?,
pageNo: Int,
pageSize: Int
): List<ExpertBean?>? {
return runBlocking(Dispatchers.IO) {
try {
val deferred = async {
EmergencyRepository.searchExpert(
realname ?: "",
centerId ?: "",
excludeSessionId ?: "",
pageNo,
pageSize
)
}
val response = withTimeoutOrNull(10000L) { deferred.await() }
?: return@runBlocking emptyList<ExpertBean>()
response.takeIf { it.success }?.result?.records ?: emptyList()
} catch (e: Exception) {
emptyList()
}
}
}
override fun getActualGroupMemberList(sessionId: String): List<GroupMemberBean?>? {
return runBlocking(Dispatchers.IO) {
try {
val deferred = async {
EmergencyRepository.getActualGroupMemberList(sessionId)
}
val response = withTimeoutOrNull(10000L) { deferred.await() }
?: return@runBlocking emptyList<GroupMemberBean>()
response.takeIf { it.success }?.result ?: emptyList()
} catch (e: Exception) {
emptyList()
}
}
}
}
override fun initView(root: View?, savedInstanceState: Bundle?) { override fun initView(root: View?, savedInstanceState: Bundle?) {
// fitTransparentStatusBar(mBinding.tvTitle) // fitTransparentStatusBar(mBinding.tvTitle)
MapsInitializer.updatePrivacyShow(context, true, true) MapsInitializer.updatePrivacyShow(context, true, true)
@@ -88,6 +204,15 @@ class EmergencyFragment :
PermissionX.init(this@EmergencyFragment) PermissionX.init(this@EmergencyFragment)
.permissions(mPermissionList) .permissions(mPermissionList)
.request { allGranted, grantedList, deniedList -> setUpMap() } .request { allGranted, grantedList, deniedList -> setUpMap() }
ParamedicOperateHelper.getInstance().setListener(paramedicOperateListener)
mViewModel.isLiaisonUser { result ->
if (!result) {
mBinding.fragmentEmergencyParamedic.visibility = View.GONE
}
SPUtils.getInstance().put(CHAT_IS_LIAISON_USER, result)
}
} }
override fun initData() { override fun initData() {
@@ -97,13 +222,13 @@ class EmergencyFragment :
// 0.0, // 0.0,
// 0.0 // 0.0
// ) // )
var mHeadType= mutableListOf<EmergencyDictBean>() var mHeadType = mutableListOf<EmergencyDictBean>()
// mHeadType.add(EmergencyDictBean("全部","全部","全部","0",true)) // mHeadType.add(EmergencyDictBean("全部","全部","全部","0",true))
mHeadType.add(EmergencyDictBean("油田医院","油田医院","油田医院","1",true)) mHeadType.add(EmergencyDictBean("油田医院", "油田医院", "油田医院", "1", true))
// mHeadType.add(EmergencyDictBean("合作医院","合作医院","合作医院","2",false)) // mHeadType.add(EmergencyDictBean("合作医院","合作医院","合作医院","2",false))
mHeadType.add(EmergencyDictBean("健康小屋","健康小屋","健康小屋","3",false)) mHeadType.add(EmergencyDictBean("健康小屋", "健康小屋", "健康小屋", "3", false))
mHeadType.add(EmergencyDictBean("AED","AED","AED","4",false)) mHeadType.add(EmergencyDictBean("AED", "AED", "AED", "4", false))
mHeadType.add(EmergencyDictBean("救护车","救护车","救护车","5",false)) mHeadType.add(EmergencyDictBean("救护车", "救护车", "救护车", "5", false))
mBinding.fragmentEmergencyHeadRv.setHeadData(mHeadType) { titleBean -> mBinding.fragmentEmergencyHeadRv.setHeadData(mHeadType) { titleBean ->
// if (titleBean.value.equals("3")) { // if (titleBean.value.equals("3")) {
@@ -119,6 +244,8 @@ class EmergencyFragment :
// } // }
} }
titleId = mHeadType[0].value
mViewModel.getEmergencyData(mHeadType[0].value, mCurrentLat, mCurrentLon)
} }
override fun createObserve() { override fun createObserve() {
@@ -168,6 +295,7 @@ class EmergencyFragment :
super.onResume() super.onResume()
mMapView?.onResume() mMapView?.onResume()
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
mMapView?.onPause() mMapView?.onPause()
@@ -227,6 +355,7 @@ class EmergencyFragment :
fragmentEmergencyPhone.setOnClickListener(this@EmergencyFragment) fragmentEmergencyPhone.setOnClickListener(this@EmergencyFragment)
fragmentEmergencyCardNavigation.setOnClickListener(this@EmergencyFragment) fragmentEmergencyCardNavigation.setOnClickListener(this@EmergencyFragment)
fragmentEmergencyMarkerInfo.setOnClickListener(this@EmergencyFragment) fragmentEmergencyMarkerInfo.setOnClickListener(this@EmergencyFragment)
fragmentEmergencyParamedic.setOnClickListener(this@EmergencyFragment)
} }
} }
@@ -284,6 +413,25 @@ class EmergencyFragment :
) )
}) })
} }
R.id.fragment_emergency_paramedic -> {
mViewModel.getParticipatedOrders { result ->
when {
result.records.isNullOrEmpty() -> {
showToast("暂无参与的应急就医工单")
}
result.records.size == 1 -> {
startParamedicChat(result.records[0])
}
else -> {
showChatListDialog(result.records) { groupInfo ->
startParamedicChat(groupInfo)
}
}
}
}
}
R.id.fragment_emergency_marker_info -> { R.id.fragment_emergency_marker_info -> {
} }
@@ -317,6 +465,90 @@ class EmergencyFragment :
} }
} }
/**
* 启动 medic 应急就医群聊:拉取群成员 → 配置 IM 输入态 → 进入群聊界面
*/
private fun startParamedicChat(groupInfo: GroupInfo) {
mViewModel.getActualGroupMemberList(groupInfo.sessionId, successCall = { groupMemberBeans ->
IMInputActionSettingUtils.createEmergencySetting(true)
activity?.startGroupChat(
groupInfo.sessionId,
getString(R.string.title_paramedic_group),
false,
groupMemberBeans.map { it.userId }.toList() as ArrayList<String>?,
workBean = WorkBean(groupInfo.orderId, TUIUtils.WORK_TYPE_EMERGENCY)
)
})
}
/**
* 展示急救工单选择Dialog(Figma设计稿)
*/
private fun showChatListDialog(
records: List<GroupInfo>,
onChatSelected: (GroupInfo) -> Unit
) {
context?.let { ctx ->
val dialog = Dialog(ctx, com.xjjk.healthyclients.R.style.EmergencyDialogTheme)
val binding = DialogGroupInfoListBinding.inflate(layoutInflater)
val adapter = GroupInfoAdapter(records) { selectedPos ->
// 选中变化时更新确认按钮状态
val hasSelection = selectedPos >= 0
binding.tvConfirm.isEnabled = hasSelection
binding.tvConfirm.alpha = if (hasSelection) 1.0f else 0.4f
}
binding.rvGroupList.layoutManager = LinearLayoutManager(ctx)
binding.rvGroupList.adapter = adapter.apply {
// 初始禁用确认按钮
binding.tvConfirm.isEnabled = false
binding.tvConfirm.alpha = 0.4f
}
// 列表项间距
val spacing = ctx.resources.getDimensionPixelSize(com.xjjk.healthyclients.R.dimen.dp_12)
binding.rvGroupList.addItemDecoration(object : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
outRect.bottom = spacing
}
})
// 确认按钮点击
binding.tvConfirm.setOnClickListener {
adapter.selectedItem?.let { item ->
onChatSelected(item)
dialog.dismiss()
}
}
// 右上角X关闭
binding.ivClose.setOnClickListener { dialog.dismiss() }
// 点击卡片外部区域关闭
binding.flRoot.setOnClickListener { dialog.dismiss() }
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(true)
dialog.setCancelable(true)
dialog.window?.let { window ->
window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
window.decorView.setBackgroundColor(Color.TRANSPARENT)
window.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
}
dialog.show()
}
}
fun setMarker(markerList: MutableList<LocationResourceBean>) { fun setMarker(markerList: MutableList<LocationResourceBean>) {
mAMap?.clear() //清除点位 mAMap?.clear() //清除点位
if (markerList.isNullOrEmpty()) { if (markerList.isNullOrEmpty()) {
@@ -350,7 +582,11 @@ class EmergencyFragment :
} }
if (markerList.size == 1) { if (markerList.size == 1) {
MapUtils.setMapZoonloAndZoom(mAMap, LatLng(markerList.get(0).latitude, markerList.get(0).longitude),11) MapUtils.setMapZoonloAndZoom(
mAMap,
LatLng(markerList.get(0).latitude, markerList.get(0).longitude),
11
)
} else { } else {
MapUtils.setMapZoonlo(mAMap, 200, ArrayList(newlist)) MapUtils.setMapZoonlo(mAMap, 200, ArrayList(newlist))
} }
@@ -15,8 +15,10 @@ import com.tencent.qcloud.tuikit.tuichat.bean.WorkBean
import com.xjjk.healthyclients.R import com.xjjk.healthyclients.R
import com.xjjk.healthyclients.adapter.common.MultiItemTypeAdapter import com.xjjk.healthyclients.adapter.common.MultiItemTypeAdapter
import com.xjjk.healthyclients.bankRequest.BankPointRequest import com.xjjk.healthyclients.bankRequest.BankPointRequest
import com.xjjk.healthyclients.bankRequest.HealthInfoRequest
import com.xjjk.healthyclients.base.BaseVMBFragment import com.xjjk.healthyclients.base.BaseVMBFragment
import com.xjjk.healthyclients.bean.guidance.GuidanceListBean import com.xjjk.healthyclients.bean.guidance.GuidanceListBean
import com.xjjk.healthyclients.bean.home.CategoryBean
import com.xjjk.healthyclients.bean.home.WatchInfoBean import com.xjjk.healthyclients.bean.home.WatchInfoBean
import com.xjjk.healthyclients.data.api.HomeApi import com.xjjk.healthyclients.data.api.HomeApi
import com.xjjk.healthyclients.databinding.FragmentHomeBinding import com.xjjk.healthyclients.databinding.FragmentHomeBinding
@@ -34,6 +36,7 @@ import com.xjjk.healthyclients.superfuntion.startWebActivity
import com.xjjk.healthyclients.superfuntion.toZeroDefault import com.xjjk.healthyclients.superfuntion.toZeroDefault
import com.xjjk.healthyclients.ui.activity.EmptyActivity import com.xjjk.healthyclients.ui.activity.EmptyActivity
import com.xjjk.healthyclients.ui.activity.LoginActivity import com.xjjk.healthyclients.ui.activity.LoginActivity
import com.xjjk.healthyclients.ui.activity.ProposalActivity
import com.xjjk.healthyclients.ui.activity.guidance.adapter.GuidanceFragmentDoctorAdapter import com.xjjk.healthyclients.ui.activity.guidance.adapter.GuidanceFragmentDoctorAdapter
import com.xjjk.healthyclients.ui.activity.home.HomeBannerDetailActivity import com.xjjk.healthyclients.ui.activity.home.HomeBannerDetailActivity
import com.xjjk.healthyclients.ui.activity.home.HomeNoticeListActivity import com.xjjk.healthyclients.ui.activity.home.HomeNoticeListActivity
@@ -57,7 +60,7 @@ class HomeFragment :
private var mApi = getBankRetrofit().create(HomeApi::class.java) private var mApi = getBankRetrofit().create(HomeApi::class.java)
var watchBindDialog: WatchBindDialog ?=null var watchBindDialog: WatchBindDialog? = null
var stringList: MutableList<String> = mutableListOf() var stringList: MutableList<String> = mutableListOf()
var mDoctorList = arrayListOf<GuidanceListBean>() var mDoctorList = arrayListOf<GuidanceListBean>()
@@ -67,6 +70,15 @@ class HomeFragment :
var noticeTime = REQUEST_DURATION var noticeTime = REQUEST_DURATION
var watchInfo: WatchInfoBean? = null var watchInfo: WatchInfoBean? = null
/** 健康资讯请求 */
private var mHealthInfoRequest: HealthInfoRequest? = null
/** 健康资讯 Token */
private var mHealthToken: String? = null
/** 健康知识子栏目列表 */
private var mKnowledgeCategories: MutableList<CategoryBean> = mutableListOf()
/** 通知轮播协程 Job,重新启动前先取消旧任务,防止多协程并发叠加 */ /** 通知轮播协程 Job,重新启动前先取消旧任务,防止多协程并发叠加 */
private var noticeJob: Job? = null private var noticeJob: Job? = null
@@ -140,6 +152,7 @@ class HomeFragment :
}) })
mBinding.layoutItem3.fragmentGuidanceRvDoctor.adapter = mGuidanceFragmentDoctorAdapter mBinding.layoutItem3.fragmentGuidanceRvDoctor.adapter = mGuidanceFragmentDoctorAdapter
mBinding.watchView.init(this@HomeFragment) mBinding.watchView.init(this@HomeFragment)
setupHealthViews()
} }
override fun bindEvent() { override fun bindEvent() {
@@ -158,9 +171,9 @@ class HomeFragment :
} }
mBinding.watchView.mBinding.imgWatchMore.setOnClickListener { mBinding.watchView.mBinding.imgWatchMore.setOnClickListener {
if (DataStoreManager.isLogin()) { if (DataStoreManager.isLogin()) {
if (watchInfo?.hasWatch==true){ if (watchInfo?.hasWatch == true) {
EventBus.getDefault().post(HomeTabChangeEvent().apply { index = 3 }) EventBus.getDefault().post(HomeTabChangeEvent().apply { index = 3 })
}else { } else {
showWatchBindDialog() showWatchBindDialog()
} }
} else { } else {
@@ -169,9 +182,9 @@ class HomeFragment :
} }
mBinding.watchView.mBinding.watchName.setOnClickListener { mBinding.watchView.mBinding.watchName.setOnClickListener {
if (DataStoreManager.isLogin()) { if (DataStoreManager.isLogin()) {
if (watchInfo?.hasWatch==true){ // if (watchInfo?.hasWatch==true){
showWatchBindDialog(watchInfo?.watchNo) // showWatchBindDialog(watchInfo?.watchNo)
} // }
} else { } else {
toActivity(LoginActivity::class.java) toActivity(LoginActivity::class.java)
} }
@@ -190,21 +203,51 @@ class HomeFragment :
override fun onClick(v: View?) { override fun onClick(v: View?) {
when (v?.id) { when (v?.id) {
R.id.img_left -> { R.id.img_left -> {
val bundle = Bundle() if (DataStoreManager.isLogin()) {
bundle.putString("title", "智慧体重") val value = mViewModel.enCryptInfoUrl.value
toActivity(EmptyActivity::class.java, bundle) if (TextUtils.isEmpty(value)) {
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
showToast("网络错误")
return
}
requireContext().startWebActivity(
UrlConfig.getWeightManagementH5Url() + "?param=" + value,
isFull = true,
myTitle = "",
hideStatus = true
)
} else {
startLoginActivity(requireContext())
}
} }
R.id.img_right -> { R.id.img_right -> {
if (DataStoreManager.isLogin()) {
val bundle = Bundle() val bundle = Bundle()
bundle.putString("title", "一人一案") bundle.putString("title", "一人一案")
toActivity(EmptyActivity::class.java, bundle) toActivity(ProposalActivity::class.java, bundle)
} else {
startLoginActivity(requireContext())
}
} }
R.id.home_head_tab1 -> { R.id.home_head_tab1 -> {
val bundle = Bundle() if (DataStoreManager.isLogin()) {
bundle.putString("title", "健康档案") val value = mViewModel.enCryptInfoUrl.value
toActivity(EmptyActivity::class.java, bundle) if (TextUtils.isEmpty(value)) {
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
showToast("网络错误")
return
}
requireContext().startWebActivity(
UrlConfig.getHealthFileH5Url() + "?param=" + value,
isFull = true,
myTitle = "",
hideStatus = true
)
} else {
startLoginActivity(requireContext())
}
} }
R.id.home_head_tab2 -> { R.id.home_head_tab2 -> {
@@ -274,6 +317,7 @@ class HomeFragment :
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
mBinding.healthKnowledgeView.clearSearchFocus()
if (DataStoreManager.isLogin()) { if (DataStoreManager.isLogin()) {
mBinding.tvHi.visibility = View.VISIBLE mBinding.tvHi.visibility = View.VISIBLE
// mBinding.layoutNotice.visibility = View.VISIBLE // mBinding.layoutNotice.visibility = View.VISIBLE
@@ -314,7 +358,7 @@ class HomeFragment :
if (TextUtils.isEmpty(value)) { if (TextUtils.isEmpty(value)) {
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url()) mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
showToast("网络错误") showToast("网络错误")
}else { } else {
requireContext().startWebActivity( requireContext().startWebActivity(
UrlConfig.getHealthCheckH5Url() + "?param=" + value, UrlConfig.getHealthCheckH5Url() + "?param=" + value,
isFull = true, isFull = true,
@@ -338,10 +382,27 @@ class HomeFragment :
startLoginActivity(requireContext()) startLoginActivity(requireContext())
} }
} }
showBanner(mBinding.banner4, bannerList4) { showBanner(mBinding.banner4, bannerList4) {banner->
val bundle = Bundle() if (DataStoreManager.isLogin()) {
bundle.putString("title", "AI随访") if (banner.jumpUrl.isEmpty()) {
toActivity(EmptyActivity::class.java, bundle) toActivity(EmptyActivity::class.java, Bundle())
} else {
val value = mViewModel.enCryptInfoUrl.value
if (TextUtils.isEmpty(value)) {
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
showToast("网络错误")
} else {
requireContext().startWebActivity(
banner.jumpUrl + "?param=" + value,
isFull = true,
myTitle = "健康体检",
hideStatus = true
)
}
}
} else {
startLoginActivity(requireContext())
}
} }
@@ -457,6 +518,12 @@ class HomeFragment :
mViewModel.getHomeWatchInfo(DataStoreManager.getUserId()) mViewModel.getHomeWatchInfo(DataStoreManager.getUserId())
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url()) mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
getBankPointDetail() getBankPointDetail()
loadHealthInfoData()
} else {
mBinding.healthKnowledgeView.mBinding.tabLayout.visibility = View.GONE
mBinding.healthKnowledgeView.mBinding.tvEmpty.visibility = View.VISIBLE
mBinding.healthKnowledgeView.mBinding.tvEmpty.text = "暂未登录"
} }
} }
@@ -484,6 +551,202 @@ class HomeFragment :
mViewModel.getHomeWatchInfo(DataStoreManager.getUserId()) mViewModel.getHomeWatchInfo(DataStoreManager.getUserId())
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url()) mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
getBankPointDetail() getBankPointDetail()
loadHealthInfoData()
}
}
// ==================== 健康资讯相关 ====================
/** 初始化健康资讯两个 View 的事件回调 */
private fun setupHealthViews() {
mHealthInfoRequest = HealthInfoRequest()
// 健康知识 - Tab 切换加载对应栏目文章
mBinding.healthKnowledgeView.setOnTabSelectedListener { category ->
loadKnowledgeArticles(category.categoryId)
}
// 健康知识 - 列表项点击 → 跳转文章详情 H5
mBinding.healthKnowledgeView.setOnItemClickListener { article ->
navigateToArticleDetail(article.articleId)
}
// 健康知识 - 更多按钮 → 跳转健康知识 H5 页面
mBinding.healthKnowledgeView.setOnMoreClickListener {
navigateToHealthKnowledgeMore()
}
// 健康知识 - 搜索
mBinding.healthKnowledgeView.setOnSearchClickListener {
navigateToHealthKnowledgeSearch(it)
}
// 健康咨询 - 列表项点击 → 跳转文章详情 H5
mBinding.healthConsultationView.setOnItemClickListener { article ->
navigateToArticleDetail(article.articleId)
}
// 健康咨询 - 更多按钮 → 跳转健康咨询 H5 页面
mBinding.healthConsultationView.setOnMoreClickListener {
navigateToHealthConsultationMore()
}
}
/** 加载健康资讯数据(Token → 栏目 → 文章) */
private fun loadHealthInfoData() {
mBinding.healthKnowledgeView.mBinding.tabLayout.visibility = View.VISIBLE
mBinding.healthKnowledgeView.mBinding.tvEmpty.visibility = View.GONE
mBinding.healthKnowledgeView.mBinding.tvEmpty.text = "暂无健康知识"
mHealthInfoRequest?.fetchToken(
onSuccess = { token ->
mHealthToken = token
loadCategories(token)
},
onFailure = { /* Token 获取失败,静默处理 */ }
)
}
/** 加载栏目列表并设置健康知识 Tab */
private fun loadCategories(token: String) {
mHealthInfoRequest?.fetchCategoryList(
token,
onSuccess = { categories ->
// 查找健康知识栏目(categoryId=1)的子栏目
val knowledgeCategory = categories.find { it.categoryId == 1 }
mKnowledgeCategories.clear()
knowledgeCategory?.children?.let { mKnowledgeCategories.addAll(it) }
mBinding.healthKnowledgeView.setupTabs(mKnowledgeCategories)
// 默认加载第一个子栏目文章
if (mKnowledgeCategories.isNotEmpty()) {
loadKnowledgeArticles(mKnowledgeCategories[0].categoryId)
}
if (categories.isNotEmpty() && categories.size >= 2) {
loadConsultationArticles(categories[1].categoryId)
}
},
onFailure = { /* 栏目加载失败,静默处理 */ }
)
}
/** 加载健康知识指定栏目下的文章列表 */
private fun loadKnowledgeArticles(categoryId: Int) {
mHealthToken?.let { token ->
mHealthInfoRequest?.fetchArticleList(
token, categoryId,
onSuccess = { articles ->
mBinding.healthKnowledgeView.setArticles(articles)
},
onFailure = { /* 文章加载失败,静默处理 */ }
)
}
}
/** 加载健康咨询文章列表(categoryId */
private fun loadConsultationArticles(categoryId: Int) {
mHealthToken?.let { token ->
mHealthInfoRequest?.fetchArticleList(
token, categoryId,
onSuccess = { articles ->
mBinding.healthConsultationView.setArticles(articles)
},
onFailure = { /* 文章加载失败,静默处理 */ }
)
}
}
/** 跳转文章详情 H5 */
private fun navigateToArticleDetail(articleId: Int) {
if (DataStoreManager.isLogin()) {
val param = mViewModel.enCryptInfoUrl.value
if (param.isNullOrEmpty()) {
showToast("网络错误")
return
}
val url = "${UrlConfig.getHealthNewsDetailH5Url()}?param=$param&articleId=$articleId"
requireContext().startWebActivity(
url,
isFull = true,
myTitle = "文章详情",
hideStatus = true
)
} else {
showToast("请先登录")
toActivity(LoginActivity::class.java)
}
}
/** 跳转健康知识更多 H5 */
private fun navigateToHealthKnowledgeMore() {
if (DataStoreManager.isLogin()) {
val param = mViewModel.enCryptInfoUrl.value
if (param.isNullOrEmpty()) {
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
showToast("网络错误")
return
}
val url = "${UrlConfig.getHealthKnowledgeH5Url()}?param=$param"
requireContext().startWebActivity(
url,
isFull = true,
myTitle = "健康知识",
hideStatus = true
)
} else {
showToast("请先登录")
toActivity(LoginActivity::class.java)
}
}
/** 跳转健康知识 搜索 */
private fun navigateToHealthKnowledgeSearch(key: String) {
if (DataStoreManager.isLogin()) {
val param = mViewModel.enCryptInfoUrl.value
if (param.isNullOrEmpty()) {
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
showToast("网络错误")
return
}
val url = "${UrlConfig.getHealthNewsSearchH5Url()}?param=$param&secrchVal=$key"
requireContext().startWebActivity(
url,
isFull = true,
myTitle = "搜索",
hideStatus = true
)
} else {
showToast("请先登录")
toActivity(LoginActivity::class.java)
}
}
/** 跳转健康咨询更多 H5 */
private fun navigateToHealthConsultationMore() {
if (DataStoreManager.isLogin()) {
val param = mViewModel.enCryptInfoUrl.value
if (param.isNullOrEmpty()) {
mViewModel.getSysEnCryptInfo(UrlConfig.getHomeBankH5Url())
showToast("网络错误")
return
}
val url = "${UrlConfig.getHealthConsultationH5Url()}?param=$param"
requireContext().startWebActivity(
url,
isFull = true,
myTitle = "健康咨询",
hideStatus = true
)
} else {
showToast("请先登录")
toActivity(LoginActivity::class.java)
} }
} }
@@ -0,0 +1,118 @@
package com.xjjk.healthyclients.fragment.adapter
import android.content.res.ColorStateList
import android.graphics.Color
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.xjjk.healthyclients.bean.emergency.GroupInfo
import com.xjjk.healthyclients.databinding.ItemGroupInfoBinding
/**
* 急救工单选择适配器,支持单选
*/
class GroupInfoAdapter(
private val items: List<GroupInfo>,
private val onSelectionChanged: (Int) -> Unit
) : RecyclerView.Adapter<GroupInfoAdapter.ViewHolder>() {
/** 当前选中位置,-1 表示无选中 */
var selectedPosition = -1
private set
/** 获取当前选中的工单 */
val selectedItem: GroupInfo?
get() = if (selectedPosition in items.indices) items[selectedPosition] else null
/** 选中主色 */
private var colorPrimary = 0
/** 未选中灰色 */
private var colorGray = 0
private var colorDark = 0
private var colorBody = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemGroupInfoBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
// 初始化颜色值
if (colorPrimary == 0) {
colorPrimary = ContextCompat.getColor(parent.context, com.xjjk.healthyclients.R.color.emergency_primary)
colorGray = ContextCompat.getColor(parent.context, com.xjjk.healthyclients.R.color.emergency_text_gray)
colorDark = ContextCompat.getColor(parent.context, com.xjjk.healthyclients.R.color.emergency_text_dark)
colorBody = ContextCompat.getColor(parent.context, com.xjjk.healthyclients.R.color.emergency_text_body)
}
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position], position == selectedPosition)
}
override fun getItemCount(): Int = items.size
inner class ViewHolder(private val binding: ItemGroupInfoBinding) :
RecyclerView.ViewHolder(binding.root) {
private var currentPosition = -1
init {
binding.rootItem.setOnClickListener {
val oldPos = selectedPosition
if (oldPos == currentPosition) {
// 取消选中
selectedPosition = -1
notifyItemChanged(currentPosition)
onSelectionChanged(-1)
} else {
selectedPosition = currentPosition
notifyItemChanged(oldPos)
notifyItemChanged(currentPosition)
onSelectionChanged(currentPosition)
}
}
}
fun bind(groupInfo: GroupInfo, isSelected: Boolean) {
currentPosition = adapterPosition
val ctx = binding.root.context
// 姓名
binding.tvUserName.text = groupInfo.salvageUserName
// 部门标签
binding.tvDeptName.text = groupInfo.deptName
// 地址
binding.tvOrgName.text = groupInfo.orgName
// 时间
binding.tvInitTime.text = "求助时间:${groupInfo.initTime}"
if (isSelected) {
// 选中态
binding.rootItem.setBackgroundResource(com.xjjk.healthyclients.R.drawable.bg_emergency_item_selected)
binding.ivRadio.setImageResource(com.xjjk.healthyclients.R.drawable.ic_emergency_radio_selected)
binding.tvDeptName.setTextColor(colorPrimary)
binding.tvDeptName.setBackgroundResource(com.xjjk.healthyclients.R.drawable.bg_dept_badge_selected)
binding.tvInitTime.setTextColor(colorPrimary)
binding.ivLocation.imageTintList = ColorStateList.valueOf(colorPrimary)
binding.ivClock.imageTintList = ColorStateList.valueOf(colorPrimary)
} else {
// 未选中态
binding.rootItem.setBackgroundResource(com.xjjk.healthyclients.R.drawable.bg_emergency_item_unselected)
binding.ivRadio.setImageResource(com.xjjk.healthyclients.R.drawable.ic_emergency_radio_unselected)
binding.tvDeptName.setTextColor(colorGray)
binding.tvDeptName.setBackgroundResource(com.xjjk.healthyclients.R.drawable.bg_dept_badge_unselected)
binding.tvInitTime.setTextColor(colorGray)
binding.ivLocation.imageTintList = ColorStateList.valueOf(colorGray)
binding.ivClock.imageTintList = ColorStateList.valueOf(colorGray)
}
}
}
}
@@ -15,12 +15,12 @@ object UrlConfig {
private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://192.168.1.47" // 开发环境 private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://192.168.1.47" // 开发环境
// private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://api-xj.tri.dt.io/" // 开发环境 // private const val DEBUG_DEFAULT_IP_ADDRESS_REMOTE = "http://api-xj.tri.dt.io/" // 开发环境
// private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xj-api.mcrm.vip:8888" // 测试环境 // private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xj-api.mcrm.vip:8888" // 测试环境
private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xjxc-api.mcrm.vip:8888" // 测试环境 private const val TEST_DEFAULT_IP_ADDRESS_REMOTE = "https://xj-api.yixiong-tech.com:8081" // 测试环境
// private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api.xjygjk.com" // 正式环境 // private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api.xjygjk.com" // 正式环境
private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api-jkglpt.iosp.ydpt.tech" // 正式环境 private const val PRODUCT_DEFAULT_IP_ADDRESS_REMOTE = "https://api-jkglpt.iosp.ydpt.tech" // 正式环境
private const val DEBUG_H5_ADDRESS_REMOTE = "http://console-xj.tri.dt.io" // 开发环境 private const val DEBUG_H5_ADDRESS_REMOTE = "http://console-xj.tri.dt.io" // 开发环境
private const val TEST_H5_ADDRESS_REMOTE = "https://xj-admin.mcrm.vip:8888" // 测试环境 private const val TEST_H5_ADDRESS_REMOTE = "http://10.10.10.228:23006" // 测试环境
// private const val PRODUCT_H5_ADDRESS_REMOTE = "https://console.xjygjk.com" // 正式环境 // private const val PRODUCT_H5_ADDRESS_REMOTE = "https://console.xjygjk.com" // 正式环境
private const val PRODUCT_H5_ADDRESS_REMOTE = "https://console-jkglpt.iosp.ydpt.tech" // 正式环境 private const val PRODUCT_H5_ADDRESS_REMOTE = "https://console-jkglpt.iosp.ydpt.tech" // 正式环境
//2025年10月23日 14:37 冯普说改为阿里云的地址,给油田部署的正式地址还没有启用 //2025年10月23日 14:37 冯普说改为阿里云的地址,给油田部署的正式地址还没有启用
@@ -37,17 +37,23 @@ object UrlConfig {
private const val PRODUCT_HOME_HEALTH_CHECK_H5 = "https://console-jkglpt.iosp.ydpt.tech/hb/healthcheckweb/index.html" private const val PRODUCT_HOME_HEALTH_CHECK_H5 = "https://console-jkglpt.iosp.ydpt.tech/hb/healthcheckweb/index.html"
private const val TEST_HOME_HEALTH_CHECK_H5 = "https://gstest.superwx.cn/healthcheckweb/index.html" private const val TEST_HOME_HEALTH_CHECK_H5 = "https://gstest.superwx.cn/healthcheckweb/index.html"
//体重智能管理
private const val PRODUCT_HOME_WEIGHT_MANAGEMENT_H5 = "https://console-jkglpt.iosp.ydpt.tech/hb/healthweightweb/index.html"
//健康档案
private const val PRODUCT_HOME_HEALTH_FILE_H5 = "https://console-jkglpt.iosp.ydpt.tech/hb/healthfileweb/index.html"
//手机银行 //手机银行
const val SECRET_KEY = "XJp3EHpcnwReXc1A" const val SECRET_KEY = "XJp3EHpcnwReXc1A"
private const val TEST_HOME_BANK_IP = "https://gstest.superwx.cn/" private const val TEST_HOME_BANK_IP = "https://gstest.superwx.cn/"
private const val PRODUCT_HOME_BANK_IP = "https://api-jkglpt.iosp.ydpt.tech/"
val baseUrlType: BaseUrlType = BaseUrlType.PRODUCT val baseUrlType: BaseUrlType = BaseUrlType.PRODUCT
// const val middle = "xj_health/" //test // const val middle = "xj_health/" //test
// const val middleCheck = "healthcheck/" //test
const val middle = "hb/" //product const val middle = "hb/" //product
const val middleCheck = "hb/" //product
var isOpenIm: Boolean = true var isOpenIm: Boolean = true
@@ -80,7 +86,7 @@ object UrlConfig {
} }
BaseUrlType.PRODUCT -> { BaseUrlType.PRODUCT -> {
PRODUCT_HOME_BANK_IP PRODUCT_DEFAULT_IP_ADDRESS_REMOTE
} }
} }
} }
@@ -101,6 +107,18 @@ object UrlConfig {
} }
} }
fun getH5BaseXjUrl(baseUrlType: BaseUrlType = BaseUrlType.PRODUCT): String {
return when (baseUrlType) {
BaseUrlType.DEBUG, BaseUrlType.TEST -> {
TEST_HOME_BANK_IP
}
BaseUrlType.PRODUCT -> {
"$PRODUCT_H5_ADDRESS_REMOTE/hb/"
}
}
}
fun getBankH5Url(baseUrlType: BaseUrlType = BaseUrlType.PRODUCT): String { fun getBankH5Url(baseUrlType: BaseUrlType = BaseUrlType.PRODUCT): String {
return when (baseUrlType) { return when (baseUrlType) {
BaseUrlType.DEBUG, BaseUrlType.TEST-> { BaseUrlType.DEBUG, BaseUrlType.TEST-> {
@@ -122,6 +140,63 @@ object UrlConfig {
} }
} }
} }
fun getWeightManagementH5Url(baseUrlType: BaseUrlType = BaseUrlType.PRODUCT): String {
return when (baseUrlType) {
BaseUrlType.DEBUG, BaseUrlType.TEST-> {
PRODUCT_HOME_WEIGHT_MANAGEMENT_H5
}
BaseUrlType.PRODUCT -> {
PRODUCT_HOME_WEIGHT_MANAGEMENT_H5
}
}
}
fun getHealthFileH5Url(baseUrlType: BaseUrlType = BaseUrlType.PRODUCT): String {
return when (baseUrlType) {
BaseUrlType.DEBUG, BaseUrlType.TEST-> {
PRODUCT_HOME_HEALTH_FILE_H5
}
BaseUrlType.PRODUCT -> {
PRODUCT_HOME_HEALTH_FILE_H5
}
}
}
/**
* 健康资讯 H5 页面基础地址
*/
fun getHealthNewsH5BaseUrl(): String {
return getH5BaseXjUrl() + "healthnewsweb/"
}
/**
* 健康知识 H5 页面地址
*/
fun getHealthKnowledgeH5Url(): String {
return getHealthNewsH5BaseUrl() + "healthKnow.html"
}
/**
* 健康咨询 H5 页面地址
*/
fun getHealthConsultationH5Url(): String {
return getHealthNewsH5BaseUrl() + "healthNews.html"
}
/**
* 健康资讯详情 H5 页面地址
*/
fun getHealthNewsDetailH5Url(): String {
return getHealthNewsH5BaseUrl() + "healthNewsDetail.html"
}
/**
* 健康资讯搜索 H5 页面地址
*/
fun getHealthNewsSearchH5Url(): String {
return getHealthNewsH5BaseUrl() + "healthSecrch.html"
}
/** /**
* 方便后续加一些其他逻辑 * 方便后续加一些其他逻辑
*/ */
@@ -590,6 +590,7 @@ fun TabLayout.attachViewPager(
fun getTabStyle(i: Int): Int { fun getTabStyle(i: Int): Int {
return when (i) { return when (i) {
1 -> R.layout.item_tablayout_group_title 1 -> R.layout.item_tablayout_group_title
2 -> R.layout.item_tablayout_group_index_theme//有下标线的绿色
else -> R.layout.item_tablayout_group_title else -> R.layout.item_tablayout_group_title
} }
} }
@@ -0,0 +1,169 @@
package com.xjjk.healthyclients.ui.activity
import android.graphics.Color
import android.os.Bundle
import android.view.View
import androidx.core.text.isDigitsOnly
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.xjjk.healthyclients.R
import com.xjjk.healthyclients.base.BaseVMBActivity
import com.xjjk.healthyclients.bean.home.ProposalBean
import com.xjjk.healthyclients.databinding.ActivityProposalBinding
import com.xjjk.healthyclients.ui.viewmodel.ProposalViewModel
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
/**
* 一人一案(健康档案)页面
*/
class ProposalActivity :
BaseVMBActivity<ProposalViewModel, ActivityProposalBinding>(R.layout.activity_proposal) {
override fun initView(savedInstanceState: Bundle?) {
val stringExtra = intent.getStringExtra("title")
mBinding.toolbarLay.title = stringExtra ?: "一人一案"
}
override fun initData() {
// 加载健康档案数据
}
override fun createObserve() {
super.createObserve()
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
mViewModel.proposalInfo.collectLatest {
setProposalInfo(it)
}
}
}
}
/**
* 手机号中间4位脱敏
*/
fun String?.maskPhone(): String {
val phone = this ?: return "--"
// 判断是否标准11位
return if (phone.length == 11) {
phone.replaceRange(3, 7, "****")
} else {
phone
}
}
private fun setProposalInfo(proposalBean: ProposalBean?) {
proposalBean?.let {
mBinding.llDocumentBuild.visibility = View.VISIBLE
mBinding.llMostCare.visibility = View.VISIBLE
// 患者信息
mBinding.tvPatientName.text = it.name
mBinding.tvPatientGenderAge.text = formatNullString(it.sexCode) + " · " + it.age + ""
//mBinding.tvDocumentStatus.text = it.careStatus
mBinding.tvPatientCompany.text = formatNullString(it.workUnit)
mBinding.tvIdNumber.text = formatNullString(it.idNo)
mBinding.tvPhone.text = formatNullString(it.phone).maskPhone()
// 关爱管理信息
//mBinding.tvLevel.text = it.dataLevel.toString()
mBinding.tvLiaisonName.text = formatNullString(it.careLiaisonName)
mBinding.tvNegativeList.text = formatNullString(it.negativeList)
// 档案与标签
if (it.flagFat == 1) {
mBinding.llFatTag.visibility = View.VISIBLE
}
val weight = formatNullString(it.weight)
val formatWeight = weight.toDoubleOrNull()?.let {
String.format("%.2f", it)
} ?: weight
val standardWeight = formatNullString(it.targetWeight)
val targetWeight = standardWeight.toDoubleOrNull()?.let {
String.format("%.2f", it)
} ?: standardWeight
mBinding.tvWeight.text = formatWeight
mBinding.tvHeight.text = formatNullString(it.height)
mBinding.tvBmi.text = formatNullString(it.bmiCurrent)
mBinding.tvStandardWeight.text = targetWeight
// 心血管健康
if (it.hypertension == 1) {
mBinding.llHighPressureTag.visibility = View.VISIBLE
}
mBinding.tvSystolicAvg.text = formatNullString(it.systolicPressureAvg)
mBinding.tvSystolicTarget.text = formatNullString(it.systolicPressureTarget)
mBinding.tvSystolic.text = formatNullString(it.systolicPressureCurrent)
if (it.systolicPressureTarget?.toDoubleOrNull() !=null && it.systolicPressureCurrent?.toDoubleOrNull() !=null
&& it.systolicPressureTarget.toDouble() < it.systolicPressureCurrent.toDouble()
) {
mBinding.tvSystolic.setTextColor(getColor(R.color.red_f2))
}
mBinding.tvDiastolicAvg.text = formatNullString(it.diastolicPressureAvg)
mBinding.tvDiastolicTarget.text = formatNullString(it.diastolicPressureTarget)
mBinding.tvDiastolic.text = formatNullString(it.diastolicPressureCurrent)
// 代谢指标
// 心血管健康
if (it.diabetes == 1) {
mBinding.llDiabetesTag.visibility = View.VISIBLE
}
mBinding.tvFbsValue.text = formatNullString(it.glu)
mBinding.tvFbsTarget.text = formatNullString(it.bloodSugarTarget)
mBinding.tvFbsCurrent.text = formatNullString(it.bloodSugarCurrent)
// 血脂四项
mBinding.tvTcValue.text = it.tc
mBinding.tvTcTarget.text = it.tcTarget
mBinding.tvTcCurrent.text = it.tc
mBinding.tvTgValue.text = it.tg
mBinding.tvTgTarget.text = it.tgTarget
mBinding.tvTgCurrent.text = it.tg
mBinding.tvLdlValue.text = it.ldl
mBinding.tvLdlTarget.text = it.ldlTarget
mBinding.tvLdlCurrent.text = it.ldl
// 肾脏与骨骼代谢
mBinding.tvUaValue.text = it.uricAcid
mBinding.tvUaTarget.text = it.uricAcidTarget
mBinding.tvUaCurrent.text = it.uricAcid
// 特殊代谢指标
mBinding.tvHcyValue.text = it.homocysteine
mBinding.tvHcyTarget.text = it.homocysteineTarget
mBinding.tvHcyCurrent.text = it.homocysteine
// 医疗意见与记录
mBinding.tvCabinOpinion.text = it.cabinOpinion ?: "暂无小屋意见"
mBinding.tvCabinTime.text = it.cabinOpinionTime
mBinding.tvCabinReporter.text = it.cabinOpinionUserName
mBinding.tvExpertOpinion.text = it.expertOpinion ?: "暂无专家医生意见"
mBinding.tvExpertOpinionTime.text = it.expertOpinionTime
mBinding.tvExpertOpinionUserName.text = it.expertOpinionUserName
}
}
fun formatNullString(input: String?): String {
return input?.ifEmpty {
"--"
} ?: "--"
}
override fun bindEvent() {
// 绑定事件
}
override fun processClick(paramView: View?) {
// 处理点击事件
}
override fun transparentStatusBar(): Boolean {
return false
}
override fun statusBarDarkFont(): Boolean {
return true
}
}
@@ -14,6 +14,11 @@ import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.MyLocationStyle import com.amap.api.maps.model.MyLocationStyle
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.geocoder.GeocodeResult
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.RegeocodeQuery
import com.amap.api.services.geocoder.RegeocodeResult
import com.google.gson.Gson import com.google.gson.Gson
import com.permissionx.guolindev.PermissionX import com.permissionx.guolindev.PermissionX
import com.tencent.qcloud.tuicore.util.ToastUtil import com.tencent.qcloud.tuicore.util.ToastUtil
@@ -38,6 +43,7 @@ class SelectLocationActivity : BaseVMBActivity<TestViewModel, ActivitySelectLoca
var aMap: AMap? = null var aMap: AMap? = null
var mCurrentLat: Double = 0.0 var mCurrentLat: Double = 0.0
var mCurrentLon: Double = 0.0 var mCurrentLon: Double = 0.0
var desc: String = ""
var mPermissionList= arrayListOf( var mPermissionList= arrayListOf(
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION) Manifest.permission.ACCESS_FINE_LOCATION)
@@ -72,6 +78,34 @@ class SelectLocationActivity : BaseVMBActivity<TestViewModel, ActivitySelectLoca
override fun initData() { override fun initData() {
} }
private fun initGeocoderSearch() {
val geocodeSearch = GeocodeSearch(this@SelectLocationActivity)
val query = RegeocodeQuery(LatLonPoint(mCurrentLat, mCurrentLon), 200f, GeocodeSearch.AMAP)
geocodeSearch.getFromLocationAsyn(query)
geocodeSearch.setOnGeocodeSearchListener(object : GeocodeSearch.OnGeocodeSearchListener {
override fun onRegeocodeSearched(
regeocodeResult: RegeocodeResult?,
resultID: Int
) {
if (regeocodeResult != null) {
val regeocodeAddress = regeocodeResult.regeocodeAddress
desc = regeocodeAddress.getFormatAddress()
}
}
override fun onGeocodeSearched(
geocodeResult: GeocodeResult?,
resultID: Int
) {
if (geocodeResult != null) {
val geocodeAddressList = geocodeResult.geocodeAddressList
}
}
})
}
private fun setUpMap() { private fun setUpMap() {
// 自定义系统定位小蓝点 // 自定义系统定位小蓝点
val myLocationStyle = MyLocationStyle() val myLocationStyle = MyLocationStyle()
@@ -91,6 +125,9 @@ class SelectLocationActivity : BaseVMBActivity<TestViewModel, ActivitySelectLoca
aMap?.setOnMyLocationChangeListener { aMap?.setOnMyLocationChangeListener {
mCurrentLat = it.latitude mCurrentLat = it.latitude
mCurrentLon = it.longitude mCurrentLon = it.longitude
initGeocoderSearch()
val markerOption = MarkerOptions() val markerOption = MarkerOptions()
markerOption.position(LatLng(mCurrentLat, mCurrentLon)) markerOption.position(LatLng(mCurrentLat, mCurrentLon))
aMap?.moveCamera(CameraUpdateFactory.newLatLng(LatLng(mCurrentLat, mCurrentLon))) aMap?.moveCamera(CameraUpdateFactory.newLatLng(LatLng(mCurrentLat, mCurrentLon)))
@@ -108,6 +145,8 @@ class SelectLocationActivity : BaseVMBActivity<TestViewModel, ActivitySelectLoca
marker?.position = cameraPosition.target marker?.position = cameraPosition.target
mCurrentLat = cameraPosition.target.latitude mCurrentLat = cameraPosition.target.latitude
mCurrentLon = cameraPosition.target.longitude mCurrentLon = cameraPosition.target.longitude
initGeocoderSearch()
} }
} }
@@ -144,6 +183,7 @@ class SelectLocationActivity : BaseVMBActivity<TestViewModel, ActivitySelectLoca
var locationMessageBean = LocationMessageBean() var locationMessageBean = LocationMessageBean()
locationMessageBean.longitude = mCurrentLon locationMessageBean.longitude = mCurrentLon
locationMessageBean.latitude = mCurrentLat locationMessageBean.latitude = mCurrentLat
locationMessageBean.desc = desc
intent.putExtra(ChatLayoutSetting.KEY_CUSTOM_MESSAGE, locationMessageBean.toJson()) intent.putExtra(ChatLayoutSetting.KEY_CUSTOM_MESSAGE, locationMessageBean.toJson())
setResult(ChatLayoutSetting.RESULT_CODE_LOCATION, intent) setResult(ChatLayoutSetting.RESULT_CODE_LOCATION, intent)
finish() finish()
@@ -65,6 +65,7 @@ class WebActivity : BaseVMBActivity<WebViewModel, ActivityWebBinding>(R.layout.a
.ready() .ready()
.go(getUrl()) .go(getUrl())
mAgentWeb.agentWebSettings.webSettings.javaScriptEnabled = true mAgentWeb.agentWebSettings.webSettings.javaScriptEnabled = true
mAgentWeb.agentWebSettings.webSettings.cacheMode = WebSettings.LOAD_NO_CACHE
mAgentWeb.jsInterfaceHolder.addJavaObject("android", androidInterface) mAgentWeb.jsInterfaceHolder.addJavaObject("android", androidInterface)
} }
@@ -109,11 +110,13 @@ class WebActivity : BaseVMBActivity<WebViewModel, ActivityWebBinding>(R.layout.a
override fun onBackEvent() { override fun onBackEvent() {
if (!mAgentWeb.back()) { if (!mAgentWeb.back()) {
if (jsAffirmBack.isNullOrEmpty()) { if (jsAffirmBack.isNullOrEmpty()) {
mAgentWeb.webCreator.webView?.stopLoading()
super.onBackEvent() super.onBackEvent()
} else { } else {
mAgentWeb.jsAccessEntrace.quickCallJs("interceptBack", mAgentWeb.jsAccessEntrace.quickCallJs("interceptBack",
{ value -> { value ->
if ("1" != value) { if ("1" != value) {
mAgentWeb.webCreator.webView?.stopLoading()
finish() finish()
} }
}) })
@@ -272,14 +275,10 @@ class WebActivity : BaseVMBActivity<WebViewModel, ActivityWebBinding>(R.layout.a
} }
} }
} }
var isRefresh = false
override fun onResume() { override fun onResume() {
mAgentWeb.webLifeCycle.onResume() mAgentWeb.webLifeCycle.onResume()
if (getUrl().contains("motionClock")&&isRefresh) {//动打卡链接,同步微信步数再次刷新界面
mAgentWeb.urlLoader.reload()
}
super.onResume() super.onResume()
} }
@@ -292,7 +291,6 @@ class WebActivity : BaseVMBActivity<WebViewModel, ActivityWebBinding>(R.layout.a
override fun onPause() { override fun onPause() {
mAgentWeb.webLifeCycle.onPause() mAgentWeb.webLifeCycle.onPause()
isRefresh = true
super.onPause() super.onPause()
} }
@@ -1,8 +1,13 @@
package com.xjjk.healthyclients.ui.viewmodel package com.xjjk.healthyclients.ui.viewmodel
import com.tencent.qcloud.tuikit.tuichat.bean.EmployeeBean
import com.tencent.qcloud.tuikit.tuichat.bean.ExpertBean
import com.tencent.qcloud.tuikit.tuichat.bean.GroupMemberBean
import com.xjjk.healthyclients.base.viewmodel.BaseViewModel import com.xjjk.healthyclients.base.viewmodel.BaseViewModel
import com.xjjk.healthyclients.bean.emergency.EmergencyGroupInfo import com.xjjk.healthyclients.bean.emergency.EmergencyGroupInfo
import com.xjjk.healthyclients.bean.emergency.GroupInfo
import com.xjjk.healthyclients.bean.emergency.LocationResourceBean import com.xjjk.healthyclients.bean.emergency.LocationResourceBean
import com.xjjk.healthyclients.data.bean.PageBean
import com.xjjk.healthyclients.data.repository.EmergencyRepository import com.xjjk.healthyclients.data.repository.EmergencyRepository
import com.xjjk.healthyclients.superfuntion.handleRequest import com.xjjk.healthyclients.superfuntion.handleRequest
import com.xjjk.healthyclients.superfuntion.launch import com.xjjk.healthyclients.superfuntion.launch
@@ -42,6 +47,35 @@ class EmergencyViewModel : BaseViewModel() {
) )
} }
fun isLiaisonUser(successCall: (Boolean) -> Unit = {}){
launch(
{
handleRequest(
EmergencyRepository.isLiaisonUser(),
successBlock = {
it.result?.let { it1 ->
successCall.invoke(it1)
}
})
}
)
}
fun getParticipatedOrders(successCall: (PageBean<GroupInfo>) -> Unit = {}){
launch(
{
handleRequest(
EmergencyRepository.getParticipatedOrders(),
successBlock = {
it.result?.let { it1 ->
successCall.invoke(it1)
}
})
}
)
}
fun getEmergencyCall( fun getEmergencyCall(
callType: String, callType: String,
resourceId: String, resourceId: String,
@@ -99,6 +133,101 @@ class EmergencyViewModel : BaseViewModel() {
}) })
}) })
} }
fun getParamedicGroupInfo(
groupName: String, longitude: Double,
latitude: Double, successCall: (EmergencyGroupInfo) -> Unit = {}
) {
launch({
handleRequest(
EmergencyRepository.getParamedicGroupInfo(groupName, longitude, latitude),
successBlock = {
it.result?.let { it1 ->
successCall.invoke(it1)
}
})
})
}
fun searchExpert(
realname: String, centerId: String, excludeSessionId: String, pageNo: Int, pageSize: Int, successCall: (List<ExpertBean>) -> Unit = {}
) {
launch({
handleRequest(
EmergencyRepository.searchExpert(realname, centerId, excludeSessionId, pageNo, pageSize),
successBlock = {
it.result?.records?.let { it1 ->
successCall.invoke(it1)
}
})
})
}
fun searchEmployee(
realname: String, orgCode: String, workNo: String, phone: String, excludeSessionId: String, pageNo: Int, pageSize: Int,
successCall: (List<EmployeeBean>) -> Unit = {}) {
launch({
handleRequest(
EmergencyRepository.searchEmployee(realname, orgCode, workNo, phone, excludeSessionId, pageNo, pageSize),
successBlock = {
it.result?.records?.let { it1 ->
successCall.invoke(it1)
}
})
})
}
fun getActualGroupMemberList(sessionId: String, successCall: (List<GroupMemberBean>) -> Unit = {}
) {
launch({
handleRequest(
EmergencyRepository.getActualGroupMemberList(sessionId),
successBlock = {
it.result?.let { it1 ->
successCall.invoke(it1)
}
})
})
}
/**
* 邀请成员加入群组。
*
* @param groupId 群组 ID
* @param memberList 成员 userId 列表
* @param memberType 成员类型
* @param successCall 结果回调:true 表示服务器写入成功,false 表示失败(网络异常、业务错误、result 为空或 false
* 回调在协程上下文触发,调用方需自行切回主线程
*/
fun addGroupUser(groupId: String, memberList: List<String>,
memberType: Int, successCall: (Boolean) -> Unit = {}
) {
launch({
handleRequest(
EmergencyRepository.addGroupUser(groupId, memberList, memberType),
successBlock = {
// result 为空或 false 都视为失败,便于调用方串行后续动作(如刷新列表)
successCall.invoke(it.result == true)
},
errorBlock = {
successCall.invoke(false)
false
})
})
}
fun removeGroupUser(groupId: String, memberList: List<String>, successCall: (Boolean) -> Unit = {}
) {
launch({
handleRequest(
EmergencyRepository.removeGroupUser(groupId, memberList),
successBlock = {
it.result?.let { it1 ->
successCall.invoke(it1)
}
})
})
}
// //
// /** // /**
// * 附近医疗点 // * 附近医疗点
@@ -0,0 +1,32 @@
package com.xjjk.healthyclients.ui.viewmodel
import com.xjjk.healthyclients.base.viewmodel.BaseViewModel
import com.xjjk.healthyclients.bean.home.ProposalBean
import com.xjjk.healthyclients.data.repository.EmergencyRepository
import com.xjjk.healthyclients.superfuntion.handleRequest
import com.xjjk.healthyclients.superfuntion.launch
import kotlinx.coroutines.flow.MutableStateFlow
/**
* 一人一案(健康档案)ViewModel
*/
class ProposalViewModel : BaseViewModel() {
var proposalInfo = MutableStateFlow<ProposalBean?>(null)
override fun init() {
// 初始化逻辑
getProposalInfo()
}
fun getProposalInfo() {
launch({
handleRequest(
EmergencyRepository.getProposalInfo(),
successBlock = {
it.result?.let { it1 ->
proposalInfo.emit(it1)
}
})
})
}
}
@@ -11,6 +11,8 @@ object ConstantUtils {
var mCurrentLon = 87.627704 var mCurrentLon = 87.627704
var mNutritionMonitor = false var mNutritionMonitor = false
var mIsCloseDialog = false var mIsCloseDialog = false
val APP_ID: String = "wxb33cd60beda0a212"
var mPrivacy = "本平台由西安联链科技有限公司开发和运维,平台深知个人信息对您的重要性,并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任,恪守以下原则,保护您的个人信息:权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公开透明原则等。同时,我们承诺将采取相应的安全保护措施来保护您的个人信息。请在使用平台服务前,仔细阅读并了解本隐私权政策,我们将按照本政策收集、处理及披露您的信息。\n" + var mPrivacy = "本平台由西安联链科技有限公司开发和运维,平台深知个人信息对您的重要性,并会尽全力保护您的个人信息安全可靠。我们致力于维持您对我们的信任,恪守以下原则,保护您的个人信息:权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公开透明原则等。同时,我们承诺将采取相应的安全保护措施来保护您的个人信息。请在使用平台服务前,仔细阅读并了解本隐私权政策,我们将按照本政策收集、处理及披露您的信息。\n" +
"本政策将帮助您了解以下内容:\n" + "本政策将帮助您了解以下内容:\n" +
"1、定义\n" + "1、定义\n" +
@@ -8,7 +8,7 @@ object IMInputActionSettingUtils {
/** /**
* 应急就医IM功能配置 * 应急就医IM功能配置
*/ */
fun createEmergencySetting(){ fun createEmergencySetting(firstAid: Boolean = false){//是否为急救员
var inputActionSetting = InputActionSetting.createInstance() var inputActionSetting = InputActionSetting.createInstance()
inputActionSetting.packageName = BuildConfig.APPLICATION_ID inputActionSetting.packageName = BuildConfig.APPLICATION_ID
inputActionSetting.CurrentResourceHost = UrlConfig.IMAGE_BASE_URL inputActionSetting.CurrentResourceHost = UrlConfig.IMAGE_BASE_URL
@@ -20,6 +20,7 @@ object IMInputActionSettingUtils {
inputActionSetting.isDisableMedicalExaminationReport = true inputActionSetting.isDisableMedicalExaminationReport = true
inputActionSetting.isDisableSendMessage = false inputActionSetting.isDisableSendMessage = false
inputActionSetting.isDisableFinishSession = false inputActionSetting.isDisableFinishSession = false
inputActionSetting.isFirstAid = firstAid
} }
/** /**
* 图文咨询IM功能配置 * 图文咨询IM功能配置
@@ -0,0 +1,73 @@
package com.xjjk.healthyclients.view
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.RelativeLayout
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.LinearLayoutManager
import com.xjjk.healthyclients.R
import com.xjjk.healthyclients.adapter.HealthConsultationAdapter
import com.xjjk.healthyclients.bean.home.ArticleBean
import com.xjjk.healthyclients.databinding.LayoutHealthConsultationBinding
/**
* 健康咨询 View 组件
* 头部标题 + 列表(左侧标题+收藏分享信息 / 右侧图片)
*/
class HealthConsultationView(context: Context?, attrs: AttributeSet?) :
RelativeLayout(context, attrs, 0) {
var mContext: Context? = context
var mBinding: LayoutHealthConsultationBinding = DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.layout_health_consultation, this, true
)
private val mAdapter = HealthConsultationAdapter()
private var mOnItemClickListener: ((ArticleBean) -> Unit)? = null
private var mOnMoreClickListener: (() -> Unit)? = null
init {
mBinding.rvList.layoutManager = LinearLayoutManager(mContext)
mBinding.rvList.adapter = mAdapter
// 列表项点击
mAdapter.setOnItemClickListener { _, _, position ->
mAdapter.getItem(position)?.let { mOnItemClickListener?.invoke(it) }
}
// 头部更多按钮点击
mBinding.ivMore.setOnClickListener {
mOnMoreClickListener?.invoke()
}
}
/** 设置文章列表数据(替换),最多取前 2 条 */
fun setArticles(articles: List<ArticleBean>?) {
if (articles.isNullOrEmpty()) {
mBinding.rvList.visibility = GONE
mBinding.tvEmpty.visibility = VISIBLE
return
} else {
mBinding.rvList.visibility = VISIBLE
mBinding.tvEmpty.visibility = GONE
}
val topTwo = articles.take(2).toMutableList()
mAdapter.setNewInstance(topTwo)
}
/** 追加文章列表数据(分页加载) */
fun addArticles(articles: List<ArticleBean>) {
mAdapter.addData(articles)
}
fun setOnItemClickListener(listener: (ArticleBean) -> Unit) {
mOnItemClickListener = listener
}
fun setOnMoreClickListener(listener: () -> Unit) {
mOnMoreClickListener = listener
}
}
@@ -0,0 +1,151 @@
package com.xjjk.healthyclients.view
import android.content.Context
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.RelativeLayout
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.LinearLayoutManager
import com.sw.healthyclients.view.CustomToast
import com.xjjk.healthyclients.R
import com.xjjk.healthyclients.adapter.HealthKnowledgeAdapter
import com.xjjk.healthyclients.bean.home.ArticleBean
import com.xjjk.healthyclients.bean.home.CategoryBean
import com.xjjk.healthyclients.databinding.LayoutHealthKnowledgeBinding
import com.xjjk.healthyclients.superfuntion.onCreateTab
/**
* 健康知识 View 组件
* 头部标题 + 搜索栏 + TabLayout(医生说/体检/保健/药品/疾病) + 列表
*/
class HealthKnowledgeView(context: Context?, attrs: AttributeSet?) :
RelativeLayout(context, attrs, 0) {
var mContext: Context? = context
var mBinding: LayoutHealthKnowledgeBinding = DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.layout_health_knowledge, this, true
)
private val mAdapter = HealthKnowledgeAdapter()
private var mCategoryList: MutableList<CategoryBean> = mutableListOf()
private var mOnTabSelectedListener: ((CategoryBean) -> Unit)? = null
private var mOnItemClickListener: ((ArticleBean) -> Unit)? = null
private var mOnMoreClickListener: (() -> Unit)? = null
private var mOnSearchClickListener: ((String) -> Unit)? = null
init {
mBinding.rvList.layoutManager = LinearLayoutManager(mContext)
mBinding.rvList.adapter = mAdapter
// 列表项点击
mAdapter.setOnItemClickListener { _, _, position ->
mAdapter.getItem(position)?.let { mOnItemClickListener?.invoke(it) }
}
// 头部更多按钮点击
mBinding.ivMore.setOnClickListener {
mOnMoreClickListener?.invoke()
}
// 健康知识 - 搜索
mBinding.searchView.customSearchTv.setOnClickListener {
val toString = mBinding.searchView.customSearchEt.text.toString()
if (toString.isEmpty()) {
CustomToast.makeText(context, "请输入搜索内容", CustomToast.LENGTH_SHORT).show()
return@setOnClickListener
}
mOnSearchClickListener?.invoke(toString)
}
// 键盘搜索键监听
mBinding.searchView.customSearchEt.setOnEditorActionListener { _, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_SEARCH
|| (event != null && event.keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN)
) {
val keyword = mBinding.searchView.customSearchEt.text.toString()
if (keyword.isEmpty()) {
CustomToast.makeText(context, "请输入搜索内容", CustomToast.LENGTH_SHORT).show()
return@setOnEditorActionListener true
}
// 隐藏键盘
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.hideSoftInputFromWindow(mBinding.searchView.customSearchEt.windowToken, 0)
mOnSearchClickListener?.invoke(keyword)
true
} else {
false
}
}
}
/**
* 根据栏目列表设置 TabLayout
* @param categories 子栏目列表(健康知识 categoryId=1 的 children
*/
fun setupTabs(categories: MutableList<CategoryBean>) {
mCategoryList.clear()
mCategoryList.addAll(categories)
if (categories.isEmpty()) {
mBinding.tabLayout.visibility = GONE
mBinding.tvEmpty.visibility = VISIBLE
return
}
mBinding.tabLayout.visibility = VISIBLE
mBinding.tvEmpty.visibility = GONE
mBinding.tabLayout.removeAllTabs()
val array = Array<String>(categories.size) {
categories[it].categoryName?:""
}
mBinding.tabLayout.onCreateTab(array,2){index->
mOnTabSelectedListener?.invoke(categories[index!!.position]) ?: return@onCreateTab
}
}
/** 设置文章列表数据(替换) */
fun setArticles(articles: MutableList<ArticleBean>?) {
if (articles.isNullOrEmpty()) {
mBinding.rvList.visibility = GONE
mBinding.tvEmpty.visibility = VISIBLE
return
}
mBinding.rvList.visibility = VISIBLE
mBinding.tvEmpty.visibility = GONE
articles.take(3).let {
mAdapter.setNewInstance(it.toMutableList()) }
}
/** 追加文章列表数据(分页加载) */
fun addArticles(articles: List<ArticleBean>) {
mAdapter.addData(articles)
}
fun setOnTabSelectedListener(listener: (CategoryBean) -> Unit) {
mOnTabSelectedListener = listener
}
fun setOnItemClickListener(listener: (ArticleBean) -> Unit) {
mOnItemClickListener = listener
}
fun setOnMoreClickListener(listener: () -> Unit) {
mOnMoreClickListener = listener
}
fun setOnSearchClickListener(listener: (keyword: String) -> Unit) {
mOnSearchClickListener = listener
}
// 清除搜索框焦点,防止onResume时自动弹出键盘
fun clearSearchFocus() {
mBinding.searchView.customSearchEt.clearFocus()
}
}
@@ -62,7 +62,7 @@ class WatchBindDialog(context: Context, var listener: (String,Int) -> Unit) : Al
if (TextUtils.isEmpty(watchId)) { if (TextUtils.isEmpty(watchId)) {
binding.etWatchid.isEnabled = true binding.etWatchid.isEnabled = true
binding.confirm.setText("绑定") binding.confirm.setText("绑定")
type = 0 // type = 0
} else { } else {
binding.etWatchid.isEnabled = false binding.etWatchid.isEnabled = false
binding.confirm.isEnabled = false binding.confirm.isEnabled = false
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/theme_color" android:state_selected="true" />
<item android:color="@color/text_black_60" />
</selector>
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 选中状态-->
<item android:drawable="@drawable/bg_white_background_shap" android:state_checked="true"/>
<item android:drawable="@drawable/bg_white_background_shap" android:state_selected="true"/>
<!-- 默认状态-->
<item android:drawable="@drawable/bg_action_grey_radius5"/>
</selector>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 选中状态-->
<item android:drawable="@color/theme_color" android:state_checked="true"/>
<item android:drawable="@color/theme_color" android:state_selected="true"/>
<!-- 默认状态-->
<item android:drawable="@color/text_black_60"/>
</selector>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 选中状态-->
<item android:drawable="@drawable/bg_theme_background_shape3" android:state_checked="true"/>
<item android:drawable="@drawable/bg_theme_background_shape3" android:state_selected="true"/>
<!-- 默认状态-->
<item android:drawable="@color/colorWhite"/>
</selector>
@@ -0,0 +1,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1A2EB8B2" />
<corners android:radius="4dp" />
</shape>
@@ -0,0 +1,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1A77859E" />
<corners android:radius="4dp" />
</shape>
@@ -0,0 +1,4 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/emergency_close_bg" />
</shape>
@@ -0,0 +1,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/emergency_primary" />
<corners android:radius="12dp" />
</shape>
@@ -0,0 +1,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white" />
<corners android:radius="12dp" />
</shape>
@@ -0,0 +1,8 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/emergency_card_selected_bg" />
<stroke
android:width="1dp"
android:color="@color/emergency_card_selected_border" />
<corners android:radius="8dp" />
</shape>
@@ -0,0 +1,8 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white" />
<stroke
android:width="1dp"
android:color="@color/emergency_card_unselected_border" />
<corners android:radius="8dp" />
</shape>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 渐变下划线装饰:白色 → 主题青色,用于医疗意见章节标题下方 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#FFFFFF"
android:endColor="#2EB8B2"
android:angle="0" />
<size android:height="2dp" />
</shape>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 渐变下划线装饰:白色 → 主题青色,用于医疗意见章节标题下方 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#2EB8B2"
android:endColor="#FFFFFF"
android:angle="0" />
<size android:height="2dp" />
</shape>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 渐变下划线装饰:白色 → 主题青色,用于医疗意见章节标题下方 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#FFFFFF"
android:endColor="#5ABDBA"
android:centerColor="#FFFFFF"
android:centerY="0.5"
android:angle="270" />
<size android:height="2dp" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 灰色圆角背景 #F5F7FB radius 12dp -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#F5F7FB" />
<corners android:radius="12dp" />
</shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#F5F7FB" />
<corners android:radius="8dp" />
</shape>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 患者信息卡片浅绿渐变头部 #DEFFFC → #FFFFFF -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#DEFFFC"
android:endColor="#FFFFFF"
android:angle="270" />
<corners
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />
</shape>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#F24439" />
<size
android:width="6dp"
android:height="6dp" />
</shape>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 表格数据单元格:白色背景 + 浅灰边框 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF" />
<stroke
android:width="1dp"
android:color="#E6E6EA" />
</shape>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 表格表头单元格:灰色背景 + 浅灰边框 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#F5F7FB" />
<stroke
android:width="1dp"
android:color="#E6E6EA" />
</shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1A2EB8B2" />
<corners android:radius="12dp" />
</shape>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#DEFFFC"
android:endColor="#FFFFFF"
android:angle="270" />
<!--<corners
android:topLeftRadius="12dp"
android:topRightRadius="12dp" />-->
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 青色标签背景 #2EB8B2 radius 12dp,用于"重点关爱"等标签 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#2EB8B2" />
<corners android:radius="12dp" />
</shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/theme_color" />
<corners android:radius="4dp" />
</shape>
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 卡片顶部青色细条,配合患者信息卡片使用 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#2EB8B2" />
<corners
android:topLeftRadius="8dp"
android:topRightRadius="8dp" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 青色标签背景 #2EB8B2 radius 4dp -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#2EB8B2" />
<corners android:radius="4dp" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 小号青色标签背景 #2EB8B2 radius 2dp,用于BMI"标准"标签 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#2EB8B2" />
<corners android:radius="2dp" />
</shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/theme_color" />
<corners android:radius="3dp" />
</shape>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 卡片顶部青色细条,配合患者信息卡片使用 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#2EB8B2" />
<corners
android:topLeftRadius="8dp"
android:topRightRadius="8dp"
android:bottomRightRadius="8dp"
android:bottomLeftRadius="8dp"/>
</shape>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white" />
<corners android:radius="12dp" />
</shape>
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:fillColor="@android:color/transparent"
android:pathData="M8,14C11.31,14 14,11.31 14,8C14,4.69 11.31,2 8,2C4.69,2 2,4.69 2,8C2,11.31 4.69,14 8,14Z"
android:strokeWidth="1.2"
android:strokeColor="@color/emergency_primary"
android:strokeLineCap="round" />
<path
android:fillColor="@android:color/transparent"
android:pathData="M8,5L8,8.5L10.5,10"
android:strokeWidth="1.2"
android:strokeColor="@color/emergency_primary"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</vector>
@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="14dp"
android:viewportWidth="14"
android:viewportHeight="14">
<path
android:fillColor="@android:color/transparent"
android:pathData="M1,1L13,13M13,1L1,13"
android:strokeWidth="1.5"
android:strokeColor="@color/emergency_text_gray"
android:strokeLineCap="round" />
</vector>
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:fillColor="@android:color/transparent"
android:pathData="M8,14C8,14 14,9.5 14,6C14,2.69 11.31,0 8,0C4.69,0 2,2.69 2,6C2,9.5 8,14 8,14Z"
android:strokeWidth="1"
android:strokeColor="@color/emergency_primary"
android:strokeLineJoin="round" />
<path
android:fillColor="@color/emergency_primary"
android:pathData="M8,8C9.1,8 10,7.1 10,6C10,4.9 9.1,4 8,4C6.9,4 6,4.9 6,6C6,7.1 6.9,8 8,8Z" />
</vector>
@@ -0,0 +1,16 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="@color/emergency_primary" />
</shape>
</item>
<item
android:top="5dp"
android:bottom="5dp"
android:left="5dp"
android:right="5dp">
<shape android:shape="oval">
<solid android:color="@android:color/white" />
</shape>
</item>
</layer-list>
@@ -0,0 +1,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke
android:width="1dp"
android:color="@color/emergency_card_unselected_border" />
<solid android:color="@android:color/white" />
</shape>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

File diff suppressed because it is too large Load Diff
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/dp_50"
android:background="@color/white">
<RelativeLayout
android:id="@+id/custom_ll_search"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_35"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/dp_12"
android:layout_marginRight="10dp"
android:background="@drawable/bg_search_shap_radius23">
<ImageView
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/dp_17"
android:src="@mipmap/ic_search" />
<EditText
android:id="@+id/custom_search_et"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/dp_38"
android:background="@null"
android:longClickable="false"
android:gravity="center_vertical"
android:hint="@string/search_hint"
android:maxLines="1"
android:imeOptions="actionSearch"
android:singleLine="true"
android:textColor="@color/text_black_33"
android:textColorHint="#B6B6B6"
android:textSize="@dimen/txt13" />
<com.allen.library.shape.ShapeTextView
android:id="@+id/custom_search_tv"
android:layout_width="55dp"
android:layout_height="28dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="@dimen/dp_2"
android:gravity="center"
android:text="@string/search_submit"
android:textColor="@color/white"
android:textSize="@dimen/txt14"
app:shapeCornersRadius="14dp"
app:shapeSolidColor="@color/theme_color" />
</RelativeLayout>
</RelativeLayout>
</layout>
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- 全屏半透明背景层,居中显示白色卡片 -->
<FrameLayout
android:id="@+id/fl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:background="@android:color/transparent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_gravity="center"
android:orientation="vertical"
android:background="@drawable/bg_emergency_dialog_card"
android:paddingBottom="16dp">
<!-- 标题栏 -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="16dp"
android:paddingBottom="12dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="请选择正在应急的工单"
android:textColor="@color/emergency_text_dark"
android:textSize="18sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/iv_close"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="end|center_vertical"
android:src="@drawable/ic_emergency_close"
android:background="@drawable/bg_emergency_close_btn"
android:padding="5dp"
android:contentDescription="关闭" />
</FrameLayout>
<!-- 顶部分割线 -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/emergency_divider" />
<!-- 工单列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_group_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingTop="12dp"
android:paddingBottom="4dp"
android:maxHeight="420dp"
android:clipToPadding="false"
android:scrollbars="none"
tools:listitem="@layout/item_group_info" />
<!-- 底部分割线 -->
<View
android:id="@+id/view_bottom_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/emergency_divider" />
<!-- 确认选择按钮 -->
<TextView
android:id="@+id/tv_confirm"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="确认选择"
android:textColor="@android:color/white"
android:textSize="18sp"
android:textStyle="bold"
android:background="@drawable/bg_emergency_confirm_btn" />
</LinearLayout>
</FrameLayout>
</layout>
@@ -65,20 +65,22 @@
android:id="@+id/fragment_emergency_call_120" android:id="@+id/fragment_emergency_call_120"
android:layout_width="@dimen/dp_70" android:layout_width="@dimen/dp_70"
android:layout_height="@dimen/dp_70" android:layout_height="@dimen/dp_70"
android:layout_marginRight="@dimen/dp_16" android:layout_marginEnd="@dimen/dp_16"
android:src="@drawable/ic_emergency_120" /> android:src="@drawable/ic_emergency_120" />
<ImageView <ImageView
android:id="@+id/fragment_emergency_seek_doctor" android:id="@+id/fragment_emergency_seek_doctor"
android:layout_width="@dimen/dp_70" android:layout_width="@dimen/dp_70"
android:layout_height="@dimen/dp_70" android:layout_height="@dimen/dp_70"
android:layout_marginLeft="@dimen/dp_16"
android:layout_toRightOf="@+id/fragment_emergency_call_120"
android:src="@drawable/ic_emergency_seek_doctor" /> android:src="@drawable/ic_emergency_seek_doctor" />
<ImageView
android:id="@+id/fragment_emergency_paramedic"
android:layout_width="@dimen/dp_70"
android:layout_height="@dimen/dp_70"
android:layout_marginStart="@dimen/dp_16"
android:src="@drawable/ic_paramedic" />
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
+15
View File
@@ -169,7 +169,22 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<com.xjjk.healthyclients.view.HealthKnowledgeView
android:id="@+id/health_knowledge_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginTop="10dp" />
<com.xjjk.healthyclients.view.HealthConsultationView
android:id="@+id/health_consultation_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginTop="10dp" />
<com.youth.banner.Banner <com.youth.banner.Banner
android:layout_marginTop="10dp"
android:id="@+id/banner4" android:id="@+id/banner4"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="120dp" android:layout_height="120dp"
+122
View File
@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="@+id/root_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="16dp"
android:paddingBottom="14dp"
android:background="@drawable/bg_emergency_item_unselected">
<!-- 顶部:姓名 + 选择圆圈 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:id="@+id/tv_user_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="@color/emergency_text_dark"
android:textSize="15sp"
android:textStyle="bold"
android:ellipsize="end"
android:maxLines="1"
tools:text="艾尼瓦尔·吐尔逊" />
<ImageView
android:id="@+id/iv_radio"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginStart="12dp"
android:src="@drawable/ic_emergency_radio_unselected" />
</LinearLayout>
<!-- 部门标签 -->
<TextView
android:id="@+id/tv_dept_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:paddingHorizontal="8dp"
android:paddingVertical="2dp"
android:textColor="@color/emergency_text_gray"
android:textSize="11sp"
android:textStyle="bold"
android:ellipsize="end"
android:maxLines="1"
android:background="@drawable/bg_dept_badge_unselected"
tools:text="员工健康事务部" />
<!-- 内部分割线 -->
<View
android:id="@+id/view_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:background="@color/emergency_divider" />
<!-- 地址行 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:id="@+id/iv_location"
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_emergency_location" />
<TextView
android:id="@+id/tv_org_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:textColor="@color/emergency_text_body"
android:textSize="13sp"
android:ellipsize="end"
android:maxLines="2"
tools:text="监管中心(石油天然气克拉玛依工程质量监督站)" />
</LinearLayout>
<!-- 时间行 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:id="@+id/iv_clock"
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_emergency_clock" />
<TextView
android:id="@+id/tv_init_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:textColor="@color/emergency_text_gray"
android:textSize="13sp"
android:ellipsize="end"
android:maxLines="1"
tools:text="求助时间:2026-07-22 16:24:32" />
</LinearLayout>
</LinearLayout>
</layout>
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="90dp"
android:orientation="horizontal"
android:paddingLeft="@dimen/dp_15"
android:paddingTop="@dimen/dp_12"
android:paddingRight="@dimen/dp_15">
<!-- 左侧文字区域 -->
<!-- 标题 -->
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="90dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="#111225"
android:textSize="@dimen/txt15"
tools:text="高血压患者日常生活注意事项与饮食指南" />
<!-- 右侧图片 80x60 圆角8 -->
<ImageView
android:id="@+id/iv_cover"
android:layout_width="@dimen/dp_80"
android:layout_height="@dimen/dp_60"
android:layout_alignParentRight="true"
android:layout_marginLeft="@dimen/dp_12"
tools:src="@mipmap/ic_placeholder_rectangle" />
<!-- 收藏和分享信息 -->
<TextView
android:id="@+id/tv_meta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginTop="@dimen/dp_8"
android:layout_marginBottom="15dp"
android:textColor="@color/text_tab_color"
android:textSize="@dimen/txt12"
tools:text="收藏 128 分享 36" />
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="#EAECF1" />
</RelativeLayout>
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="130dp"
android:orientation="horizontal"
android:paddingLeft="@dimen/dp_15"
android:paddingTop="@dimen/dp_12"
android:paddingRight="@dimen/dp_15">
<!-- 左侧图片 100x100 圆角15 -->
<ImageView
android:id="@+id/iv_cover"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
tools:src="@mipmap/ic_home_item_head_bg" />
<!-- 右侧文字区域 -->
<RelativeLayout
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_120"
android:orientation="vertical">
<!-- 标题 -->
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#252535"
android:textSize="@dimen/txt15"
tools:text="高血压患者日常生活注意事项" />
<!-- 详情 -->
<TextView
android:id="@+id/tv_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_title"
android:layout_marginTop="@dimen/dp_8"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@color/text_tab_color"
android:textSize="@dimen/txt13"
tools:text="高血压是一种常见的慢性疾病,需要长期坚持治疗和管理..." />
</RelativeLayout>
<!-- 底部:标签 + 日期 -->
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="@dimen/dp_120"
android:layout_marginBottom="20dp">
<!-- 标签图标 -->
<ImageView
android:id="@+id/iv_tag_icon"
android:layout_width="@dimen/dp_20"
android:layout_height="@dimen/dp_20"
android:src="@mipmap/ic_home_know_tag" />
<!-- 标签文本 -->
<TextView
android:layout_marginRight="60dp"
android:id="@+id/tv_tag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/dp_4"
android:layout_toRightOf="@+id/iv_tag_icon"
android:textColor="#14BEBE"
android:textSize="@dimen/txt11"
android:lines="1"
android:ellipsize="end"
tools:text="心血管心血管心血管心血管心血管心血管心血管心血管心血管心血管" />
<!-- 日期 -->
<TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:textColor="@color/text_tab_color"
android:textSize="@dimen/txt11"
tools:text="2024-06-29" />
</RelativeLayout>
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:layout_marginLeft="120dp"
android:background="#EAECF1" />
</RelativeLayout>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_tab_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center"
android:includeFontPadding="false"
android:paddingHorizontal="6dp"
android:paddingVertical="7dp"
android:textColor="@color/color_child_tab_layout_text_index_theme"
android:textSize="14sp" />
<View
android:id="@+id/tv_line"
android:layout_width="18dp"
android:layout_height="3dp"
android:layout_below="@+id/tv_text"
android:layout_centerHorizontal="true"
android:background="@drawable/bg_child_tab_layout_item_line" />
</RelativeLayout>
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/dp_10"
android:background="@drawable/bg_white_background_shap_radius12"
>
<!-- 头部:标题 + 更多箭头 -->
<RelativeLayout
android:id="@+id/rl_header"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@mipmap/ic_home_item_head_bg"
android:scaleType="fitXY">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:text="健康资讯"
android:textColor="@color/text_black_33"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/iv_more"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentRight="true"
android:layout_marginTop="12dp"
android:layout_marginRight="15dp"
android:background="@drawable/arrow_right"
android:padding="10dp" />
</RelativeLayout>
<!-- 列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
android:paddingTop="@dimen/dp_10" />
<!-- 空状态提示 -->
<TextView
android:id="@+id/tv_empty"
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center"
android:text="暂无健康咨询"
android:textColor="#14BEBE"
android:textSize="16sp"
android:visibility="gone" />
</LinearLayout>
</layout>
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data></data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/dp_10"
android:background="@drawable/bg_white_background_shap_radius12"
android:orientation="vertical">
<!-- 头部:标题 + 更多箭头 -->
<RelativeLayout
android:id="@+id/rl_header"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@mipmap/ic_home_item_head_bg"
android:scaleType="fitXY">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:text="健康知识"
android:textColor="@color/text_black_33"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/iv_more"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentRight="true"
android:layout_marginTop="12dp"
android:layout_marginRight="15dp"
android:background="@drawable/arrow_right"
android:padding="10dp" />
</RelativeLayout>
<!-- 搜索栏 -->
<include
android:id="@+id/search_view"
layout="@layout/custom_search_view_home" />
<!-- Tab 标签栏 -->
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:background="@color/white"
app:tabIndicatorFullWidth="false"
app:tabIndicatorHeight="@dimen/dp_0"
app:tabMinWidth="@dimen/dp_0"
app:tabMode="fixed"
app:tabPaddingEnd="@dimen/dp_0"
app:tabPaddingStart="@dimen/dp_0"
app:tabRippleColor="@null" />
<!-- 分隔线 -->
<View
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:background="@color/line" />
<!-- 列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
android:paddingTop="@dimen/dp_10" />
<!-- 空状态提示 -->
<TextView
android:id="@+id/tv_empty"
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center"
android:text="暂无健康知识"
android:textColor="#14BEBE"
android:textSize="16sp"
android:visibility="gone" />
</LinearLayout>
</layout>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+20
View File
@@ -132,6 +132,18 @@
<color name="text_orange_10">#F36510</color> <color name="text_orange_10">#F36510</color>
<color name="text_blue_BE">#21BEBE</color> <color name="text_blue_BE">#21BEBE</color>
<color name="text_blue_F0">#cbebf0</color> <color name="text_blue_F0">#cbebf0</color>
<!-- 应急工单选择 Dialog 颜色(Figma -->
<color name="emergency_card_selected_bg">#0F2EB8B2</color>
<color name="emergency_card_selected_border">#802EB8B2</color>
<color name="emergency_card_unselected_border">#E6E6EA</color>
<color name="emergency_dialog_bg">#F5F7FB</color>
<color name="emergency_divider">#EAECFA</color>
<color name="emergency_text_dark">#252535</color>
<color name="emergency_text_body">#394356</color>
<color name="emergency_text_gray">#77859E</color>
<color name="emergency_close_bg">#F1F5F9</color>
<color name="emergency_primary">#2EB8B2</color>
<color name="text_black_60">#606060</color> <color name="text_black_60">#606060</color>
<color name="text_tab_color">#77849E</color> <color name="text_tab_color">#77849E</color>
@@ -151,4 +163,12 @@
<color name="demo_main_tab_text_selected_color_light">#006EFF</color> <color name="demo_main_tab_text_selected_color_light">#006EFF</color>
<!-- 健康档案页面颜色 -->
<color name="text_primary_25">#252535</color>
<color name="text_teal_dark">#194C4A</color>
<color name="red_f2">#F24439</color>
<color name="divider_ea">#EAECF1</color>
<color name="gray_80">#808080</color>
<color name="bg_gray_f5">#F5F7FB</color>
</resources> </resources>
+1
View File
@@ -43,6 +43,7 @@
<string name="title_Hospital_homepage_info">医院概况</string> <string name="title_Hospital_homepage_info">医院概况</string>
<string name="title_User_Rate">用户评价</string> <string name="title_User_Rate">用户评价</string>
<string name="title_emergency">应急就医</string> <string name="title_emergency">应急就医</string>
<string name="title_paramedic_group">应急就医群</string>
<string name="title_meidacal_point">一线医疗</string> <string name="title_meidacal_point">一线医疗</string>
<string name="title_emergency_detail">应急详情</string> <string name="title_emergency_detail">应急详情</string>
<string name="title_guidance">健康咨询</string> <string name="title_guidance">健康咨询</string>
+10
View File
@@ -39,6 +39,16 @@
<item name="android:backgroundDimAmount">0.5</item> <item name="android:backgroundDimAmount">0.5</item>
</style> </style>
<!-- 应急工单选择Dialog:全屏透明无遮罩 -->
<style name="EmergencyDialogTheme" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
<style name="main_menu_animStyle"> <style name="main_menu_animStyle">
<item name="android:windowEnterAnimation">@anim/dialog_in_anim</item> <item name="android:windowEnterAnimation">@anim/dialog_in_anim</item>
<item name="android:windowExitAnimation">@anim/dialog_out_anim</item> <item name="android:windowExitAnimation">@anim/dialog_out_anim</item>
+2 -2
View File
@@ -2,8 +2,8 @@ ext {
minSdkVersion = 26 minSdkVersion = 26
targetSdkVersion = 32 targetSdkVersion = 32
compileSdkVersion = 33 compileSdkVersion = 33
versionCode = 1013 versionCode = 1015
versionName = "1.0.13" versionName = "1.0.15"
//Dependencies //Dependencies
junitVersion = "4.12" junitVersion = "4.12"
lifecycleVersion = "2.6.0-alpha01" lifecycleVersion = "2.6.0-alpha01"