|
@@ -0,0 +1,386 @@
|
|
|
+package xn.xxp.main.risk;
|
|
|
+
|
|
|
+import android.content.Intent;
|
|
|
+import android.graphics.Bitmap;
|
|
|
+import android.os.Bundle;
|
|
|
+import android.util.Log;
|
|
|
+import android.view.View;
|
|
|
+import android.webkit.WebSettings;
|
|
|
+import android.webkit.WebView;
|
|
|
+
|
|
|
+import androidx.activity.EdgeToEdge;
|
|
|
+import androidx.appcompat.app.AppCompatActivity;
|
|
|
+import androidx.core.graphics.Insets;
|
|
|
+import androidx.core.view.ViewCompat;
|
|
|
+import androidx.core.view.WindowInsetsCompat;
|
|
|
+import androidx.fragment.app.Fragment;
|
|
|
+import androidx.recyclerview.widget.LinearLayoutManager;
|
|
|
+
|
|
|
+import com.blankj.utilcode.util.ThreadUtils;
|
|
|
+import com.bumptech.glide.Glide;
|
|
|
+
|
|
|
+import org.greenrobot.eventbus.EventBus;
|
|
|
+import org.greenrobot.eventbus.Subscribe;
|
|
|
+import org.greenrobot.eventbus.ThreadMode;
|
|
|
+import org.jsoup.Jsoup;
|
|
|
+import org.jsoup.nodes.Document;
|
|
|
+import org.jsoup.nodes.Element;
|
|
|
+import org.jsoup.select.Elements;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import core.ui.activity.BaseCountDownActivity;
|
|
|
+import core.util.EscapeUnescape;
|
|
|
+import http.client.ApiRepository;
|
|
|
+import http.vo.request.HazardReq;
|
|
|
+import http.vo.response.LabHazardVo;
|
|
|
+import io.reactivex.rxjava3.disposables.Disposable;
|
|
|
+import xn.xxp.R;
|
|
|
+import xn.xxp.databinding.ActivityBrowserBinding;
|
|
|
+import xn.xxp.databinding.ActivityRiskBinding;
|
|
|
+import xn.xxp.databinding.ActivityRiskListBinding;
|
|
|
+import xn.xxp.main.msds.HtmlFullScreenActivity;
|
|
|
+import xn.xxp.room.RoomTool;
|
|
|
+import xn.xxp.room.bean.LabConfig;
|
|
|
+import xn.xxp.utils.QrTool;
|
|
|
+import xn.xxp.widget.ITitleBar;
|
|
|
+import xn.xxp.widget.NavViewCompat;
|
|
|
+
|
|
|
+public class RiskListActivity extends BaseCountDownActivity<ActivityRiskListBinding> {
|
|
|
+ private ActivityRiskListBinding binding;
|
|
|
+ private RiskListAdapter riskListAdapter;
|
|
|
+ private LabHazardVo mCurrentData; // 当前选中的危险源数据
|
|
|
+ private LabConfig labConfig; // 实验室配置信息
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ITitleBar getMTitleBar() {
|
|
|
+ return binding.titleBar;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public NavViewCompat getMNavView() {
|
|
|
+ return binding.navView;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected ActivityRiskListBinding createViewBinding() {
|
|
|
+ return binding = ActivityRiskListBinding.inflate(getLayoutInflater());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void initViews(Bundle savedInstanceState) {
|
|
|
+ super.initViews(savedInstanceState);
|
|
|
+ // 初始化实验室配置
|
|
|
+ labConfig = RoomTool.getInstance().labConfigDao().getLabConfig();
|
|
|
+ initWeb();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void initListener() {
|
|
|
+ // 全屏按钮点击事件
|
|
|
+ binding.fullScreen.setOnClickListener(v -> {
|
|
|
+ if (mCurrentData == null) return;
|
|
|
+ Intent intent = new Intent(this, HtmlFullScreenActivity.class);
|
|
|
+ intent.putExtra("html_content", mCurrentData.content);
|
|
|
+ intent.putExtra("onEboard", true);
|
|
|
+ intent.putExtra("name", mCurrentData.chName);
|
|
|
+ startActivity(intent);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void initData() {
|
|
|
+ super.initData();
|
|
|
+ riskListAdapter = new RiskListAdapter(new ArrayList<>());
|
|
|
+ // 设置列表项点击监听
|
|
|
+ riskListAdapter.setOnItemClickListener((adapter, view, position) -> {
|
|
|
+ LabHazardVo item = riskListAdapter.getItem(position);
|
|
|
+ riskListAdapter.setSelectedItemId(item.hazardId);
|
|
|
+ refreshDetailUI(item);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 配置RecyclerView
|
|
|
+ binding.risk.setLayoutManager(new LinearLayoutManager(this));
|
|
|
+ binding.risk.setAdapter(riskListAdapter);
|
|
|
+ // 加载数据
|
|
|
+ queryHazardList();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询危险源列表数据
|
|
|
+ */
|
|
|
+ private void queryHazardList() {
|
|
|
+ showLoading("加载中...");
|
|
|
+
|
|
|
+ // 构建请求参数
|
|
|
+ HazardReq param = new HazardReq();
|
|
|
+ param.subId = String.valueOf(labConfig.getLabId());
|
|
|
+ param.pageNum = 1;
|
|
|
+ param.pageSize = 20;
|
|
|
+
|
|
|
+ Disposable disposable = ApiRepository.INSTANCE.hazardlist(param)
|
|
|
+ .subscribe(data -> {
|
|
|
+ dismissLoading();
|
|
|
+ handleDataSuccess(data);
|
|
|
+ }, throwable -> {
|
|
|
+ dismissLoading();
|
|
|
+ handleDataError(throwable);
|
|
|
+ });
|
|
|
+
|
|
|
+ addDisposable(disposable);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理数据加载成功
|
|
|
+ */
|
|
|
+ private void handleDataSuccess(List<LabHazardVo> data) {
|
|
|
+ riskListAdapter.setNewInstance(data);
|
|
|
+
|
|
|
+ if (data.isEmpty()) {
|
|
|
+ riskListAdapter.setEmptyView(R.layout.view_list_empty);
|
|
|
+ binding.qrGroup.setVisibility(View.INVISIBLE);
|
|
|
+ } else {
|
|
|
+ binding.qrGroup.setVisibility(View.VISIBLE);
|
|
|
+ // 默认选中第一条数据
|
|
|
+ riskListAdapter.setSelectedItemId(data.get(0).hazardId);
|
|
|
+ refreshDetailUI(data.get(0));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理数据加载失败
|
|
|
+ */
|
|
|
+ private void handleDataError(Throwable throwable) {
|
|
|
+ showNetError(throwable);
|
|
|
+ riskListAdapter.setEmptyView(R.layout.view_list_empty);
|
|
|
+ binding.qrGroup.setVisibility(View.INVISIBLE);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void refreshDetailUI(LabHazardVo data) {
|
|
|
+ mCurrentData = data;
|
|
|
+ if (data == null) return;
|
|
|
+
|
|
|
+ // 加载HTML内容
|
|
|
+ if (data.content != null && !data.content.isEmpty()) {
|
|
|
+ load(EscapeUnescape.unescape(data.content));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成二维码
|
|
|
+ ThreadUtils.executeByCached(new ThreadUtils.SimpleTask<Bitmap>() {
|
|
|
+ @Override
|
|
|
+ public Bitmap doInBackground() throws Throwable {
|
|
|
+ return QrTool.generateQRCode(data.qrCodeUrl, 150);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onSuccess(Bitmap result) {
|
|
|
+ Glide.with(RiskListActivity.this)
|
|
|
+ .asBitmap()
|
|
|
+ .load(result)
|
|
|
+ .error(R.mipmap.img_error)
|
|
|
+ .into(binding.qrCode);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void load(String html) {
|
|
|
+ Document document = Jsoup.parse(html);
|
|
|
+
|
|
|
+ Element head = document.head();
|
|
|
+ // 移除现有的charset meta标签
|
|
|
+ head.select("meta[charset]").remove();
|
|
|
+ head.select("meta[http-equiv=Content-Type]").remove();
|
|
|
+ // 创建并添加新的UTF-8 meta标签
|
|
|
+ Element metaCharset = new Element("meta");
|
|
|
+ metaCharset.attr("charset", "UTF-8");
|
|
|
+ head.prependChild(metaCharset); // 添加到head的开头
|
|
|
+
|
|
|
+ // 删除所有video中的其它属性和内在的内容
|
|
|
+ Elements videos = document.select("video");
|
|
|
+ for (Element video : videos) {
|
|
|
+ // 获取需要保留的属性值
|
|
|
+ String id = video.attr("id");
|
|
|
+ String width = video.attr("width");
|
|
|
+ String height = video.attr("height");
|
|
|
+ String src = video.attr("src");
|
|
|
+ // 清除所有属性
|
|
|
+ video.clearAttributes();
|
|
|
+ // 重新设置需要保留的属性
|
|
|
+ if (!id.isEmpty()) {
|
|
|
+ video.attr("id", id);
|
|
|
+ }
|
|
|
+ if (!width.isEmpty()) {
|
|
|
+ video.attr("width", width);
|
|
|
+ }
|
|
|
+ if (!height.isEmpty()) {
|
|
|
+ video.attr("height", height);
|
|
|
+ }
|
|
|
+ if (!src.isEmpty()) {
|
|
|
+ video.attr("src", src);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移除video标签内的所有子元素(如source标签)
|
|
|
+ video.html("");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 注入video元素的操作
|
|
|
+ Element script = new Element("script");
|
|
|
+ script.append("// 页面加载完成后执行");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("document.addEventListener('DOMContentLoaded', function() {");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("// 获取所有video元素");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("var videos = document.querySelectorAll('video');");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append(" var srcDisplay = document.getElementById('srcDisplay');");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("// 为每个video元素添加点击事件");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("for (var i = 0; i < videos.length; i++) {");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("videos[i].addEventListener('click', function() {");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("// 获取当前视频的src属性");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("var videoSrc = this.getAttribute('src');");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("// 保存当前video元素的引用");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("var videoElement = this;");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("// 调用原生接口");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("if (typeof Android !== 'undefined') {");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("Android.playVideo(videoSrc);");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("console.log('视频被点击了,调用原生播放!', videoSrc);");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("} else {");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("// 切换播放/暂停状态");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("if (this.paused) {");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("console.log('视频被点击了,使用web播放', videoSrc);");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("this.play();");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("} else {");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("console.log('视频被点击了,使用web暂停', videoSrc);");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("this.pause();");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("}");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("}");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("// 添加点击反馈");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("this.style.boxShadow = '0 0 10px rgba(0, 150, 255, 0.7)';");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("setTimeout(function() {");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("videoElement.style.boxShadow = 'none';");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("}, 300);");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("});");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("}");
|
|
|
+ script.append("\r\n");
|
|
|
+ script.append("});");
|
|
|
+ script.append("\r\n");
|
|
|
+
|
|
|
+ document.body().appendChild(script);
|
|
|
+
|
|
|
+ html = document.html();
|
|
|
+ Log.d("最终的html", html);
|
|
|
+ binding.webView.loadDataWithBaseURL(
|
|
|
+ null,
|
|
|
+ html,
|
|
|
+ "text/html",
|
|
|
+ "utf-8",
|
|
|
+ null
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onResume() {
|
|
|
+ super.onResume();
|
|
|
+ binding.webView.onResume();
|
|
|
+ binding.webView.resumeTimers();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onPause() {
|
|
|
+ super.onPause();
|
|
|
+ binding.webView.onPause();
|
|
|
+ binding.webView.pauseTimers();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onDestroy() {
|
|
|
+ Fragment fragment = getSupportFragmentManager().findFragmentByTag("video_dialog");
|
|
|
+ if (fragment instanceof VideoDialogFragment) {
|
|
|
+ ((VideoDialogFragment) fragment).dismissAllowingStateLoss();
|
|
|
+ }
|
|
|
+ binding.webView.stopLoading();
|
|
|
+ binding.webView.setWebViewClient(null);
|
|
|
+ binding.webView.setWebChromeClient(null);
|
|
|
+ binding.webView.destroy();
|
|
|
+ super.onDestroy();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Subscribe(threadMode = ThreadMode.MAIN)
|
|
|
+ public void onMessageEvent(PlayVideoEvent playVideoEvent) {
|
|
|
+ VideoDialogFragment videoDialogFragment = VideoDialogFragment.newInstance(playVideoEvent.url, "视频观看");
|
|
|
+ videoDialogFragment.show(getSupportFragmentManager(), "video_dialog");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onStart() {
|
|
|
+ super.onStart();
|
|
|
+ EventBus.getDefault().register(this); // 注册
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onStop() {
|
|
|
+ super.onStop();
|
|
|
+ EventBus.getDefault().unregister(this); // 注销
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initWeb() {
|
|
|
+ // 在WebView初始化前设置
|
|
|
+ WebView.setWebContentsDebuggingEnabled(true);
|
|
|
+ // 某些设备上可以尝试这个hack
|
|
|
+ System.setProperty("media.stagefright.force-software", "1");
|
|
|
+ setContentView(binding.getRoot());
|
|
|
+ WebSettings settings = binding.webView.getSettings();
|
|
|
+ // 基础功能
|
|
|
+ settings.setJavaScriptEnabled(true); // 启用JS
|
|
|
+ settings.setDomStorageEnabled(true); // 启用DOM存储
|
|
|
+ settings.setDatabaseEnabled(true); // 启用数据库
|
|
|
+ settings.setCacheMode(WebSettings.LOAD_NO_CACHE); // 缓存模式
|
|
|
+ // 视口设置
|
|
|
+ settings.setUseWideViewPort(true); // 使用宽视口
|
|
|
+ settings.setLoadWithOverviewMode(true); // 缩放至屏幕宽度
|
|
|
+ // 缩放控制
|
|
|
+ settings.setSupportZoom(true); // 支持缩放
|
|
|
+ settings.setBuiltInZoomControls(false); // 显示缩放控件
|
|
|
+ settings.setDisplayZoomControls(false); // 隐藏默认缩放按钮
|
|
|
+ // 其他设置
|
|
|
+ settings.setAllowFileAccess(true); // 允许访问文件
|
|
|
+ settings.setAllowContentAccess(true); // 允许内容访问
|
|
|
+ settings.setAllowFileAccessFromFileURLs(true); // 允许文件URL访问
|
|
|
+ settings.setAllowUniversalAccessFromFileURLs(true); // 允许跨域访问
|
|
|
+
|
|
|
+ settings.setMediaPlaybackRequiresUserGesture(false); // 允许自动播放
|
|
|
+ settings.setPluginState(WebSettings.PluginState.ON); // 启用插件
|
|
|
+ settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
|
|
|
+ binding.webView.addJavascriptInterface(new WebAppInterface(), "Android");
|
|
|
+ }
|
|
|
+}
|