1.文本内容加载添加默认css样式
2.考试倒计时时间添加,todo,更多细化规则 3.todo..学情反馈数据显示规则待确认等
正在显示
27 个修改的文件
包含
1291 行增加
和
81 行删除
@@ -135,4 +135,5 @@ dependencies { | @@ -135,4 +135,5 @@ dependencies { | ||
135 | // 地图组件库,包括小车平移、点聚合等组件功能,详见开发指南。 | 135 | // 地图组件库,包括小车平移、点聚合等组件功能,详见开发指南。 |
136 | implementation 'com.tencent.map:sdk-utilities:1.0.6' | 136 | implementation 'com.tencent.map:sdk-utilities:1.0.6' |
137 | implementation 'com.tencent.map.geolocation:TencentLocationSdk-openplatform:7.3.0' | 137 | implementation 'com.tencent.map.geolocation:TencentLocationSdk-openplatform:7.3.0' |
138 | + api 'org.jsoup:jsoup:1.11.3' | ||
138 | } | 139 | } |
1 | -package com.br_technology.securitytrain_master.ui.view.home.activity.course | ||
2 | - | ||
3 | -import com.br_technology.securitytrain_master.base.common.ConstantParamKey | ||
4 | -import com.br_technology.securitytrain_master.databinding.ActivityPracticeBinding | ||
5 | -import com.br_technology.securitytrain_master.ui.bean.CourseParam | ||
6 | -import com.br_technology.securitytrain_master.ui.view.home.viewmodel.CoursePracticeViewModel | ||
7 | -import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity | ||
8 | - | ||
9 | -/** | ||
10 | - * Author by YSir | ||
11 | - * Date on 2022/1/23. | ||
12 | - * description | ||
13 | - * PS: Not easy to write code, please indicate. | ||
14 | - */ | ||
15 | -/** | ||
16 | - * 课程练习详情 | ||
17 | - */ | ||
18 | -class CourseExamActivity : | ||
19 | - BaseLifeCycleActivity<CoursePracticeViewModel, ActivityPracticeBinding>(ActivityPracticeBinding::inflate) { | ||
20 | - override fun initDataObserver() { | ||
21 | - } | ||
22 | - | ||
23 | - private var courseBean: CourseParam? = null | ||
24 | - | ||
25 | - override fun initData() { | ||
26 | - super.initData() | ||
27 | - courseBean = intent.getParcelableExtra(ConstantParamKey.COURSE_BEAN) | ||
28 | - courseBean?.let { | ||
29 | - mViewModel.startExam(it.mTrainClassId.toInt()) | ||
30 | - } | ||
31 | - } | ||
32 | -} |
@@ -17,6 +17,10 @@ import com.br_technology.securitytrain_master.view.listener.DialogListener | @@ -17,6 +17,10 @@ import com.br_technology.securitytrain_master.view.listener.DialogListener | ||
17 | import com.br_technology.securitytrain_master.view.listener.ToolBarClickListener | 17 | import com.br_technology.securitytrain_master.view.listener.ToolBarClickListener |
18 | import com.luck.picture.lib.tools.ToastUtils | 18 | import com.luck.picture.lib.tools.ToastUtils |
19 | import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity | 19 | import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity |
20 | +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers | ||
21 | +import io.reactivex.rxjava3.core.Flowable | ||
22 | +import java.util.concurrent.TimeUnit | ||
23 | + | ||
20 | 24 | ||
21 | /** | 25 | /** |
22 | * Author by YSir | 26 | * Author by YSir |
@@ -75,13 +79,6 @@ class CoursePractiseActivity : | @@ -75,13 +79,6 @@ class CoursePractiseActivity : | ||
75 | } else { | 79 | } else { |
76 | mViewModel.startPractise(it.mTrainClassId.toInt()) | 80 | mViewModel.startPractise(it.mTrainClassId.toInt()) |
77 | } | 81 | } |
78 | - binding.toolBar.setTitle( | ||
79 | - if (it.isTrainClass) { | ||
80 | - "班级练习" | ||
81 | - } else { | ||
82 | - "班级考试" | ||
83 | - } | ||
84 | - ) | ||
85 | } | 82 | } |
86 | binding.apply { | 83 | binding.apply { |
87 | // 禁止滑动 | 84 | // 禁止滑动 |
@@ -169,6 +166,33 @@ class CoursePractiseActivity : | @@ -169,6 +166,33 @@ class CoursePractiseActivity : | ||
169 | } | 166 | } |
170 | } | 167 | } |
171 | 168 | ||
169 | + fun countDown(seconds: Int) { | ||
170 | + val total = seconds.toLong() | ||
171 | + //intervalRange四个参数分别为:从0开始、到60结束、延时0开始,单位时间(NANOSECONDS,MICROSECONDS,MILLISECONDS,SECONDS,MINUTES,HOURS,DAYS)。 | ||
172 | + Flowable.intervalRange(0, total, 0, 1, TimeUnit.SECONDS) | ||
173 | + .observeOn(AndroidSchedulers.mainThread()) | ||
174 | + .doOnNext { | ||
175 | + val current = total - it | ||
176 | + val seconds = current % 60 | ||
177 | + val minutes = current / 60 | ||
178 | + val hour = minutes / 60 | ||
179 | + val hourTx = if (hour < 10) { | ||
180 | + "0${hour}" | ||
181 | + } else "${hour}" | ||
182 | + val secondsx = if (seconds < 10) { | ||
183 | + "0${seconds}" | ||
184 | + } else "${seconds}" | ||
185 | + val minutesTx = if (minutes < 10) { | ||
186 | + "0${minutes}" | ||
187 | + } else "${minutes}" | ||
188 | + binding.toolBar.setTitle("倒计时${hourTx}:${minutesTx}:${secondsx}") | ||
189 | + } | ||
190 | + .doOnComplete { //倒计时完毕事件处理 | ||
191 | + finish() | ||
192 | + } | ||
193 | + .subscribe() | ||
194 | + } | ||
195 | + | ||
172 | 196 | ||
173 | override fun initDataObserver() { | 197 | override fun initDataObserver() { |
174 | mViewModel.exam.observe(this) { | 198 | mViewModel.exam.observe(this) { |
@@ -179,6 +203,7 @@ class CoursePractiseActivity : | @@ -179,6 +203,7 @@ class CoursePractiseActivity : | ||
179 | } else { | 203 | } else { |
180 | ToastUtils.s(baseContext, it.msg) | 204 | ToastUtils.s(baseContext, it.msg) |
181 | } | 205 | } |
206 | + countDown(it.data.over_second) | ||
182 | } | 207 | } |
183 | 208 | ||
184 | mViewModel.subSingleData.observe(this) { | 209 | mViewModel.subSingleData.observe(this) { |
@@ -189,6 +214,7 @@ class CoursePractiseActivity : | @@ -189,6 +214,7 @@ class CoursePractiseActivity : | ||
189 | mPagerAdapter.notifyDataSetChanged() | 214 | mPagerAdapter.notifyDataSetChanged() |
190 | mViewModel.subFinish(userItemId) | 215 | mViewModel.subFinish(userItemId) |
191 | } | 216 | } |
217 | + binding.toolBar.setTitle("班级练习") | ||
192 | } | 218 | } |
193 | mViewModel.subFinish.observe(this) { | 219 | mViewModel.subFinish.observe(this) { |
194 | if (!titleDialog.isShowing) { | 220 | if (!titleDialog.isShowing) { |
@@ -10,10 +10,13 @@ import com.br_technology.securitytrain_master.base.common.ConstantParamKey | @@ -10,10 +10,13 @@ import com.br_technology.securitytrain_master.base.common.ConstantParamKey | ||
10 | import com.br_technology.securitytrain_master.base.common.ConstantParamKey.COURSE_BEAN | 10 | import com.br_technology.securitytrain_master.base.common.ConstantParamKey.COURSE_BEAN |
11 | import com.br_technology.securitytrain_master.databinding.ActivityTextDetailBinding | 11 | import com.br_technology.securitytrain_master.databinding.ActivityTextDetailBinding |
12 | import com.br_technology.securitytrain_master.ui.bean.CourseParam | 12 | import com.br_technology.securitytrain_master.ui.bean.CourseParam |
13 | +import com.br_technology.securitytrain_master.ui.bean.FileBean | ||
13 | import com.br_technology.securitytrain_master.ui.view.common.FileReadActivity | 14 | import com.br_technology.securitytrain_master.ui.view.common.FileReadActivity |
15 | +import com.br_technology.securitytrain_master.ui.view.home.adapter.PdfAdapter | ||
14 | import com.br_technology.securitytrain_master.ui.view.home.bean.TextLessonDetailBean | 16 | import com.br_technology.securitytrain_master.ui.view.home.bean.TextLessonDetailBean |
15 | import com.br_technology.securitytrain_master.ui.view.home.viewmodel.TextDetailViewModel | 17 | import com.br_technology.securitytrain_master.ui.view.home.viewmodel.TextDetailViewModel |
16 | import com.br_technology.securitytrain_master.util.TrainFileUtil | 18 | import com.br_technology.securitytrain_master.util.TrainFileUtil |
19 | +import com.br_technology.securitytrain_master.view.listener.OnItemClickListener | ||
17 | import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity | 20 | import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity |
18 | import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers | 21 | import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers |
19 | import io.reactivex.rxjava3.core.Observable | 22 | import io.reactivex.rxjava3.core.Observable |
@@ -38,7 +41,6 @@ class TextDetailActivity : | @@ -38,7 +41,6 @@ class TextDetailActivity : | ||
38 | courseBean?.let { course -> | 41 | courseBean?.let { course -> |
39 | if (course.isTrainClass) { | 42 | if (course.isTrainClass) { |
40 | mViewModel.textLessonsDetail(course.mLessonId.toInt()) | 43 | mViewModel.textLessonsDetail(course.mLessonId.toInt()) |
41 | - | ||
42 | } else { | 44 | } else { |
43 | mViewModel.materialDetail(course.mLessonId.toInt()) | 45 | mViewModel.materialDetail(course.mLessonId.toInt()) |
44 | } | 46 | } |
@@ -75,6 +77,50 @@ class TextDetailActivity : | @@ -75,6 +77,50 @@ class TextDetailActivity : | ||
75 | .startsWith("http") | 77 | .startsWith("http") |
76 | } | 78 | } |
77 | 79 | ||
80 | + override fun onPageFinished(view: WebView?, url: String?) { | ||
81 | + super.onPageFinished(view, url) | ||
82 | + if (courseBean?.isTrainClass == true) { | ||
83 | + mViewModel.mTextLessonDetailBean.value.let { | ||
84 | + val data = it?.data?.detail?.new_file | ||
85 | + binding.pdf.apply { | ||
86 | + val adapterPdf = PdfAdapter() | ||
87 | + adapterPdf.addList(data!!) | ||
88 | + adapter = adapterPdf | ||
89 | + adapterPdf.addListener(object : OnItemClickListener<FileBean> { | ||
90 | + override fun onClick(position: Int, data: FileBean) { | ||
91 | + startActivity( | ||
92 | + Intent( | ||
93 | + this@TextDetailActivity, | ||
94 | + FileReadActivity::class.java | ||
95 | + ) | ||
96 | + .putExtra(ConstantParamKey.COMMON_URL, data.url) | ||
97 | + ) | ||
98 | + } | ||
99 | + }) | ||
100 | + } | ||
101 | + } | ||
102 | + } else { | ||
103 | + mViewModel.mDetailMaterialNormal.value.let { | ||
104 | + val data = it?.data?.detail?.new_file | ||
105 | + binding.pdf.apply { | ||
106 | + val adapterPdf = PdfAdapter() | ||
107 | + adapterPdf.addList(data!!) | ||
108 | + adapter = adapterPdf | ||
109 | + adapterPdf.addListener(object : OnItemClickListener<FileBean> { | ||
110 | + override fun onClick(position: Int, data: FileBean) { | ||
111 | + startActivity( | ||
112 | + Intent( | ||
113 | + this@TextDetailActivity, | ||
114 | + FileReadActivity::class.java | ||
115 | + ) | ||
116 | + .putExtra(ConstantParamKey.COMMON_URL, data.url) | ||
117 | + ) | ||
118 | + } | ||
119 | + }) | ||
120 | + } | ||
121 | + } | ||
122 | + } | ||
123 | + } | ||
78 | } | 124 | } |
79 | content.webChromeClient = WebChromeClient() | 125 | content.webChromeClient = WebChromeClient() |
80 | back.setOnClickListener { | 126 | back.setOnClickListener { |
@@ -42,10 +42,10 @@ class AcademicFeedbackActivity : | @@ -42,10 +42,10 @@ class AcademicFeedbackActivity : | ||
42 | ++page | 42 | ++page |
43 | }) | 43 | }) |
44 | 44 | ||
45 | - mViewModel.mAcademicFeedbackDetailBean.observe(this,{ | 45 | + mViewModel.mAcademicFeedbackDetailBean.observe(this, { |
46 | DialogTitle(this@AcademicFeedbackActivity) | 46 | DialogTitle(this@AcademicFeedbackActivity) |
47 | .setImageTitle(R.mipmap.jiangshipingxi_bg) | 47 | .setImageTitle(R.mipmap.jiangshipingxi_bg) |
48 | - .setInfo(it.data.detail.des) | 48 | + .setInfo(it.data.detail.des ?: "") |
49 | .hideCompleteButton(true) | 49 | .hideCompleteButton(true) |
50 | .setTitleIsVisible(false) | 50 | .setTitleIsVisible(false) |
51 | .show() | 51 | .show() |
@@ -26,7 +26,6 @@ class LearningReportActivity : | @@ -26,7 +26,6 @@ class LearningReportActivity : | ||
26 | 26 | ||
27 | @SuppressLint("SetTextI18n") | 27 | @SuppressLint("SetTextI18n") |
28 | override fun initDataObserver() { | 28 | override fun initDataObserver() { |
29 | - // todo 数据设置 | ||
30 | mViewModel.data.observe(this, { | 29 | mViewModel.data.observe(this, { |
31 | val user = it.data.report.user | 30 | val user = it.data.report.user |
32 | binding.apply { | 31 | binding.apply { |
@@ -4,7 +4,7 @@ import com.br_technology.securitytrain_master.R | @@ -4,7 +4,7 @@ import com.br_technology.securitytrain_master.R | ||
4 | import com.br_technology.securitytrain_master.databinding.ActivityLearningReportDetailBinding | 4 | import com.br_technology.securitytrain_master.databinding.ActivityLearningReportDetailBinding |
5 | import com.br_technology.securitytrain_master.ui.view.home.pojo.VideoCourse | 5 | import com.br_technology.securitytrain_master.ui.view.home.pojo.VideoCourse |
6 | import com.br_technology.securitytrain_master.ui.view.mine.adapter.LearningReportDetailAdapter | 6 | import com.br_technology.securitytrain_master.ui.view.mine.adapter.LearningReportDetailAdapter |
7 | -import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.LearningReportDetailViewModel | 7 | +import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.LearningReportViewModel |
8 | import com.gyf.immersionbar.ImmersionBar | 8 | import com.gyf.immersionbar.ImmersionBar |
9 | import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity | 9 | import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity |
10 | 10 | ||
@@ -15,7 +15,7 @@ import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity | @@ -15,7 +15,7 @@ import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleActivity | ||
15 | * 生成学习报告详情页面 | 15 | * 生成学习报告详情页面 |
16 | */ | 16 | */ |
17 | class LearningReportDetailActivity : | 17 | class LearningReportDetailActivity : |
18 | - BaseLifeCycleActivity<LearningReportDetailViewModel, ActivityLearningReportDetailBinding>( | 18 | + BaseLifeCycleActivity<LearningReportViewModel, ActivityLearningReportDetailBinding>( |
19 | ActivityLearningReportDetailBinding::inflate | 19 | ActivityLearningReportDetailBinding::inflate |
20 | ) { | 20 | ) { |
21 | override fun initDataObserver() { | 21 | override fun initDataObserver() { |
@@ -40,7 +40,7 @@ class TrainTestAdapter : BaseMultiItemQuickAdapter<TrainTestData, BaseViewHolder | @@ -40,7 +40,7 @@ class TrainTestAdapter : BaseMultiItemQuickAdapter<TrainTestData, BaseViewHolder | ||
40 | setComplete( | 40 | setComplete( |
41 | holder, | 41 | holder, |
42 | practice!!.is_pass, | 42 | practice!!.is_pass, |
43 | - practice.score, | 43 | + practice.exam_score.toInt(), |
44 | practice.sub_time, | 44 | practice.sub_time, |
45 | practice.name | 45 | practice.name |
46 | ) | 46 | ) |
@@ -48,7 +48,7 @@ class TrainTestAdapter : BaseMultiItemQuickAdapter<TrainTestData, BaseViewHolder | @@ -48,7 +48,7 @@ class TrainTestAdapter : BaseMultiItemQuickAdapter<TrainTestData, BaseViewHolder | ||
48 | setComplete( | 48 | setComplete( |
49 | holder, | 49 | holder, |
50 | exam!!.is_pass, | 50 | exam!!.is_pass, |
51 | - exam.score, | 51 | + exam.exam_score, |
52 | exam.sub_time, | 52 | exam.sub_time, |
53 | exam.name | 53 | exam.name |
54 | ) | 54 | ) |
@@ -14,8 +14,11 @@ import com.br_technology.securitytrain_master.ui.view.mine.adapter.CourseAdapter | @@ -14,8 +14,11 @@ import com.br_technology.securitytrain_master.ui.view.mine.adapter.CourseAdapter | ||
14 | import com.br_technology.securitytrain_master.ui.view.mine.adapter.TrainTestAdapter | 14 | import com.br_technology.securitytrain_master.ui.view.mine.adapter.TrainTestAdapter |
15 | import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.ClassDutyCourseViewModel | 15 | import com.br_technology.securitytrain_master.ui.view.mine.viewmodel.ClassDutyCourseViewModel |
16 | import com.br_technology.securitytrain_master.util.TranslateUnit | 16 | import com.br_technology.securitytrain_master.util.TranslateUnit |
17 | +import com.br_technology.securitytrain_master.view.DialogMention | ||
17 | import com.br_technology.securitytrain_master.view.VerticalDecoration | 18 | import com.br_technology.securitytrain_master.view.VerticalDecoration |
18 | import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleFragment | 19 | import com.wjx.android.wanandroidmvvm.base.view.BaseLifeCycleFragment |
20 | +import java.text.SimpleDateFormat | ||
21 | +import java.util.* | ||
19 | 22 | ||
20 | /** | 23 | /** |
21 | * Time: 8/3/2021 11:24 | 24 | * Time: 8/3/2021 11:24 |
@@ -210,12 +213,48 @@ class ClassDutyCourseFragment(val type: Int) : | @@ -210,12 +213,48 @@ class ClassDutyCourseFragment(val type: Int) : | ||
210 | getData() | 213 | getData() |
211 | } | 214 | } |
212 | 215 | ||
213 | -// //todo 时间校验限制等 | ||
214 | -// fun checkTime(exam: ExamBean): Boolean { | ||
215 | -// | ||
216 | -// } | 216 | + val dialogMention: DialogMention by lazy { |
217 | + DialogMention(requireContext()).apply { | ||
218 | + setTitle("温馨提示") | ||
219 | + setMention("目前不在考试时间,是否继续进入考试?") | ||
220 | + } | ||
221 | + } | ||
222 | + | ||
223 | + //todo 时间校验限制等 | ||
224 | + fun checkTime(exam: ExamBean) { | ||
225 | + | ||
226 | + | ||
227 | + } | ||
217 | 228 | ||
218 | override fun itemClick(item: TrainTestData) { | 229 | override fun itemClick(item: TrainTestData) { |
230 | + var bool = true | ||
231 | + if (!item.isTest) { | ||
232 | + try { | ||
233 | + val simple = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA) | ||
234 | + val start = simple.parse(item.exam?.exam_start_time ?: "0").time | ||
235 | + val end = simple.parse(item.exam?.exam_end_time ?: "0").time | ||
236 | + bool = System.currentTimeMillis() in (start + 1) until end | ||
237 | + if (item.exam?.is_complete == 0) { | ||
238 | + if (bool) { | ||
239 | + startNext(item) | ||
240 | + } else { | ||
241 | + dialogMention.show() | ||
242 | + dialogMention.setListener { | ||
243 | + startNext(item) | ||
244 | + } | ||
245 | + } | ||
246 | + } else { | ||
247 | + showTip("考试已结束") | ||
248 | + } | ||
249 | + } catch (exc: Exception) { | ||
250 | + exc.printStackTrace() | ||
251 | + } | ||
252 | + } else { | ||
253 | + startNext(item) | ||
254 | + } | ||
255 | + } | ||
256 | + | ||
257 | + fun startNext(item: TrainTestData) { | ||
219 | this@ClassDutyCourseFragment.startActivity( | 258 | this@ClassDutyCourseFragment.startActivity( |
220 | Intent( | 259 | Intent( |
221 | requireActivity(), | 260 | requireActivity(), |
1 | -package com.br_technology.securitytrain_master.ui.view.mine.repository | ||
2 | - | ||
3 | -import androidx.lifecycle.MutableLiveData | ||
4 | -import com.br_technology.securitytrain_master.base.common.State | ||
5 | -import com.br_technology.securitytrain_master.base.repository.ApiRepository | ||
6 | - | ||
7 | -/** | ||
8 | - * Time: 8/2/2021 16:47 | ||
9 | - * Author: Captain | ||
10 | - * Description: 初见时你很迷人 | ||
11 | - */ | ||
12 | -class LearningReportDetailRepository(val loadState: MutableLiveData<State>) : ApiRepository(loadState) { | ||
13 | -} |
1 | -package com.br_technology.securitytrain_master.ui.view.mine.viewmodel | ||
2 | - | ||
3 | -import com.br_technology.securitytrain_master.base.view.BaseViewModel | ||
4 | -import com.br_technology.securitytrain_master.ui.view.mine.repository.LearningReportDetailRepository | ||
5 | - | ||
6 | -/** | ||
7 | - * Time: 8/2/2021 16:47 | ||
8 | - * Author: Captain | ||
9 | - * Description: 初见时你很迷人 | ||
10 | - */ | ||
11 | -class LearningReportDetailViewModel : BaseViewModel<LearningReportDetailRepository>() { | ||
12 | -} |
@@ -5,6 +5,7 @@ import com.br_technology.securitytrain_master.base.network.response.BaseResponse | @@ -5,6 +5,7 @@ import com.br_technology.securitytrain_master.base.network.response.BaseResponse | ||
5 | import com.br_technology.securitytrain_master.base.network.response.CommonReport | 5 | import com.br_technology.securitytrain_master.base.network.response.CommonReport |
6 | import com.br_technology.securitytrain_master.base.repository.TrainRepository | 6 | import com.br_technology.securitytrain_master.base.repository.TrainRepository |
7 | import com.br_technology.securitytrain_master.base.view.BaseViewModel | 7 | import com.br_technology.securitytrain_master.base.view.BaseViewModel |
8 | +import com.br_technology.securitytrain_master.ui.bean.TrainDetail | ||
8 | import com.br_technology.securitytrain_master.ui.bean.TrainReport | 9 | import com.br_technology.securitytrain_master.ui.bean.TrainReport |
9 | 10 | ||
10 | /** | 11 | /** |
@@ -14,8 +15,14 @@ import com.br_technology.securitytrain_master.ui.bean.TrainReport | @@ -14,8 +15,14 @@ import com.br_technology.securitytrain_master.ui.bean.TrainReport | ||
14 | */ | 15 | */ |
15 | class LearningReportViewModel : BaseViewModel<TrainRepository>() { | 16 | class LearningReportViewModel : BaseViewModel<TrainRepository>() { |
16 | val data = MutableLiveData<BaseResponse<CommonReport<TrainReport>>>() | 17 | val data = MutableLiveData<BaseResponse<CommonReport<TrainReport>>>() |
18 | + val data = MutableLiveData<BaseResponse<CommonReport<TrainReport>>>() | ||
17 | 19 | ||
18 | fun getReport(){ | 20 | fun getReport(){ |
19 | mRepository.trainReport(data) | 21 | mRepository.trainReport(data) |
20 | } | 22 | } |
23 | + | ||
24 | + fun getDetail(){ | ||
25 | + mRepository.get(data) | ||
26 | + TrainDetail | ||
27 | + } | ||
21 | } | 28 | } |
1 | +package com.br_technology.securitytrain_master.util; | ||
2 | + | ||
3 | +import android.graphics.Color; | ||
4 | +import android.os.Build; | ||
5 | + | ||
6 | +import androidx.annotation.RequiresApi; | ||
7 | + | ||
8 | +/** | ||
9 | + * Author by YSir | ||
10 | + * Date on 2021/3/22. | ||
11 | + * description | ||
12 | + * PS: Not easy to write code, please indicate. | ||
13 | + */ | ||
14 | +public class ColorTransHelp { | ||
15 | + | ||
16 | + //16进制字符串转color | ||
17 | + @RequiresApi(api = Build.VERSION_CODES.O) | ||
18 | + public static Color fromStrToARGB(String str) { | ||
19 | + String str1 = str.substring(0, 2); | ||
20 | + String str2 = str.substring(2, 4); | ||
21 | + String str3 = str.substring(4, 6); | ||
22 | + String str4 = str.substring(6, 8); | ||
23 | + int alpha = Integer.parseInt(str1, 16); | ||
24 | + int red = Integer.parseInt(str2, 16); | ||
25 | + int green = Integer.parseInt(str3, 16); | ||
26 | + int blue = Integer.parseInt(str4, 16); | ||
27 | + return Color.valueOf(red * 1.0f, green * 1.0f, blue * 1.0f, alpha * 1.0f); | ||
28 | + } | ||
29 | + | ||
30 | + //颜色转16进制字符串 | ||
31 | + public static String toHexEncoding(int color) { | ||
32 | + String R, G, B; | ||
33 | + StringBuilder sb = new StringBuilder(); | ||
34 | + R = Integer.toHexString(Color.red(color)); | ||
35 | + G = Integer.toHexString(Color.green(color)); | ||
36 | + B = Integer.toHexString(Color.blue(color)); | ||
37 | + R = R.length() == 1 ? "0" + R : R; | ||
38 | + G = G.length() == 1 ? "0" + G : G; | ||
39 | + B = B.length() == 1 ? "0" + B : B; | ||
40 | + sb.append(R); | ||
41 | + sb.append(G); | ||
42 | + sb.append(B); | ||
43 | + return "#" + sb.toString(); | ||
44 | + } | ||
45 | + | ||
46 | +} |
1 | +package com.br_technology.securitytrain_master.util; | ||
2 | + | ||
3 | +import android.Manifest; | ||
4 | +import android.content.ContentResolver; | ||
5 | +import android.content.Context; | ||
6 | +import android.content.pm.PackageManager; | ||
7 | +import android.net.ConnectivityManager; | ||
8 | +import android.net.NetworkInfo; | ||
9 | +import android.net.wifi.WifiInfo; | ||
10 | +import android.net.wifi.WifiManager; | ||
11 | +import android.os.Build; | ||
12 | +import android.provider.Settings; | ||
13 | +import android.telephony.TelephonyManager; | ||
14 | +import android.text.TextUtils; | ||
15 | + | ||
16 | +import androidx.core.content.ContextCompat; | ||
17 | + | ||
18 | +import com.luck.picture.lib.tools.SPUtils; | ||
19 | + | ||
20 | +import java.io.BufferedReader; | ||
21 | +import java.io.FileInputStream; | ||
22 | +import java.io.IOException; | ||
23 | +import java.io.InputStreamReader; | ||
24 | +import java.lang.reflect.Method; | ||
25 | +import java.net.InetAddress; | ||
26 | +import java.net.NetworkInterface; | ||
27 | +import java.net.SocketException; | ||
28 | +import java.util.Enumeration; | ||
29 | +import java.util.UUID; | ||
30 | + | ||
31 | +import static android.content.Context.WIFI_SERVICE; | ||
32 | + | ||
33 | +public class DeviceUtils { | ||
34 | + static final String SP_NAME_DEVICE = "device_cache"; | ||
35 | + static final String SP_KEY_DEVICE_ID = "device_id"; | ||
36 | + | ||
37 | + /** | ||
38 | + * 设备id缓存 | ||
39 | + */ | ||
40 | + static String deviceId = null; | ||
41 | + | ||
42 | + /** | ||
43 | + * 获取一个deviceId<br/> | ||
44 | + * 生成规则:<br/> | ||
45 | + * <li>获取本地缓存的deviceId,如果存在直接返回, 如果没有继续执行</li> | ||
46 | + * <li>获取AndroidId当做deviceId,如果获取不到继续执行</li> | ||
47 | + * <li>获取设备编号,如果获取不到继续执行</li> | ||
48 | + * <li>随机生成一个UUID当做deviceId,如果获取不到继续执行</li> | ||
49 | + * device获取后保存到本地,保证以后每次获取都可以获得同样的值 | ||
50 | + * | ||
51 | + * @param context {@link Context} | ||
52 | + * @return deviceId | ||
53 | + */ | ||
54 | + public static String getDeviceId(Context context) { | ||
55 | + if (TextUtils.isEmpty(deviceId)) { | ||
56 | + /*获取sp中缓存的deviceid*/ | ||
57 | + if (TextUtils.isEmpty(deviceId = getCacheDeviceId(context))) { | ||
58 | + /*获取androidId*/ | ||
59 | + if (TextUtils.isEmpty(deviceId = getAndroidId(context))) { | ||
60 | + /*获取设备号*/ | ||
61 | + if (TextUtils.isEmpty(deviceId = getTelDeviceId(context))) { | ||
62 | +// /*生成一个uuid当做设备id*/ | ||
63 | + deviceId = UUID.randomUUID().toString(); | ||
64 | + } | ||
65 | + } | ||
66 | +// SPUtils.putString(context, SP_NAME_DEVICE, SP_KEY_DEVICE_ID, deviceId); | ||
67 | + } | ||
68 | + } | ||
69 | + | ||
70 | + return deviceId; | ||
71 | + } | ||
72 | + | ||
73 | + public static void clearDevId(Context context) { | ||
74 | + deviceId = null; | ||
75 | +// SPUtils.putString(context, SP_NAME_DEVICE, SP_KEY_DEVICE_ID, null); | ||
76 | + } | ||
77 | + | ||
78 | + public static void setDevId(Context context, String devId) { | ||
79 | + deviceId = devId; | ||
80 | +// SPUtils.putString(context, SP_NAME_DEVICE, SP_KEY_DEVICE_ID, deviceId); | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * 获取缓存的设备id | ||
85 | + * | ||
86 | + * @param context | ||
87 | + * @return | ||
88 | + */ | ||
89 | + static String getCacheDeviceId(Context context) { | ||
90 | +// return SPUtils.getString(context, SP_NAME_DEVICE, SP_KEY_DEVICE_ID, null); | ||
91 | + return ""; | ||
92 | + } | ||
93 | + | ||
94 | + /** | ||
95 | + * 获取androidid | ||
96 | + * 通过{@linkplain Settings.Secure#getString(ContentResolver, String) getString}({@linkplain Context#getContentResolver() ContentResolver}, {@link Settings.Secure#ANDROID_ID}) 获得AndroidId | ||
97 | + * | ||
98 | + * @param context {@link Context} | ||
99 | + * @return | ||
100 | + */ | ||
101 | + static String getAndroidId(Context context) { | ||
102 | + | ||
103 | + if (Build.VERSION.SDK_INT != Build.VERSION_CODES.FROYO) { | ||
104 | + String ret = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); | ||
105 | + if (!TextUtils.equals("9774d56d682e549c", ret)) { | ||
106 | + return ret; | ||
107 | + } | ||
108 | + } | ||
109 | + return null; | ||
110 | + } | ||
111 | + | ||
112 | + /** | ||
113 | + * 获取设备id | ||
114 | + * 需要校验权限,不然6.0+系统可能会crash!!! | ||
115 | + * | ||
116 | + * @param context {@link Context} | ||
117 | + * @return | ||
118 | + * @see TelephonyManager#getDeviceId() | ||
119 | + */ | ||
120 | + static String getTelDeviceId(Context context) { | ||
121 | + if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { | ||
122 | + return null; | ||
123 | + } | ||
124 | + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); | ||
125 | + return tm.getDeviceId(); | ||
126 | + } | ||
127 | + | ||
128 | + /** | ||
129 | + * 获取是否有网络 只判断wfii跟移动网络</br> | ||
130 | + * 需要权限{@link Manifest.permission#ACCESS_NETWORK_STATE} | ||
131 | + * | ||
132 | + * @param context | ||
133 | + * @return | ||
134 | + */ | ||
135 | + public static boolean isNetworkConnection(Context context) { | ||
136 | + try { | ||
137 | + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); | ||
138 | + NetworkInfo networkInfo = manager.getActiveNetworkInfo(); | ||
139 | + if (networkInfo == null) { | ||
140 | + return false; | ||
141 | + } | ||
142 | + | ||
143 | + return networkInfo.isAvailable() && (networkInfo.getType() == ConnectivityManager.TYPE_WIFI || networkInfo.getType() == ConnectivityManager.TYPE_MOBILE); | ||
144 | + } catch (Exception e) { | ||
145 | + e.printStackTrace(); | ||
146 | + } | ||
147 | + return true; | ||
148 | + } | ||
149 | + | ||
150 | + /** | ||
151 | + * 获取是否是wifi</br> | ||
152 | + * 需要权限{@link Manifest.permission#ACCESS_NETWORK_STATE} | ||
153 | + * | ||
154 | + * @param context | ||
155 | + * @return | ||
156 | + */ | ||
157 | + public static boolean isConnectionWifi(Context context) { | ||
158 | + try { | ||
159 | + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); | ||
160 | + NetworkInfo networkInfo = manager.getActiveNetworkInfo(); | ||
161 | + if (networkInfo == null) { | ||
162 | + return false; | ||
163 | + } | ||
164 | + | ||
165 | + return networkInfo.isAvailable() && networkInfo.getType() == ConnectivityManager.TYPE_WIFI; | ||
166 | + } catch (Exception e) { | ||
167 | + e.printStackTrace(); | ||
168 | + } | ||
169 | + return false; | ||
170 | + } | ||
171 | + | ||
172 | + /** | ||
173 | + * 获取ip | ||
174 | + * | ||
175 | + * @param context | ||
176 | + * @return | ||
177 | + */ | ||
178 | + public static String getIP(Context context) { | ||
179 | + | ||
180 | + if (isNetworkConnection(context)) { | ||
181 | + if (isConnectionWifi(context)) { | ||
182 | + WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE); | ||
183 | + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); | ||
184 | + // 获取32位整型IP地址 | ||
185 | + int ipAddress = wifiInfo.getIpAddress(); | ||
186 | + | ||
187 | + //返回整型地址转换成“*.*.*.*”地址 | ||
188 | + return String.format("%d.%d.%d.%d", | ||
189 | + (ipAddress & 0xff), (ipAddress >> 8 & 0xff), | ||
190 | + (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); | ||
191 | + } else { | ||
192 | + try { | ||
193 | + for (Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements(); ) { | ||
194 | + NetworkInterface intf = e.nextElement(); | ||
195 | + for (Enumeration<InetAddress> enumIPAddr = intf | ||
196 | + .getInetAddresses(); enumIPAddr.hasMoreElements(); ) { | ||
197 | + InetAddress inetAddress = enumIPAddr.nextElement(); | ||
198 | + // 如果不是回环地址 | ||
199 | + if (!inetAddress.isLoopbackAddress()) { | ||
200 | + // 直接返回本地IP地址 | ||
201 | + return inetAddress.getHostAddress().toString(); | ||
202 | + } | ||
203 | + } | ||
204 | + } | ||
205 | + } catch (SocketException e) { | ||
206 | + e.printStackTrace(); | ||
207 | + } | ||
208 | + } | ||
209 | + } | ||
210 | + | ||
211 | + return null; | ||
212 | + } | ||
213 | + | ||
214 | + public static String getHostname() { | ||
215 | + try { | ||
216 | + Method method = Build.class.getDeclaredMethod("getString", new Class[]{String.class}); | ||
217 | + method.setAccessible(true); | ||
218 | + Object ret = method.invoke(null, new Object[]{"net.hostname"}); | ||
219 | + return (String) ret; | ||
220 | + } catch (Exception e) { | ||
221 | + e.printStackTrace(); | ||
222 | + } | ||
223 | + return null; | ||
224 | + } | ||
225 | + | ||
226 | + public static String getCoreVersion() { | ||
227 | + | ||
228 | + String kernelVersion = ""; | ||
229 | + BufferedReader bufferedReader = null; | ||
230 | + try { | ||
231 | + //读取配置文件 /proc/version | ||
232 | + bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/version")), 8 * 1024); | ||
233 | + String info = ""; | ||
234 | + String line; | ||
235 | + while ((line = bufferedReader.readLine()) != null) { | ||
236 | + info += line; | ||
237 | + } | ||
238 | + | ||
239 | + try { | ||
240 | + if (info != "") { | ||
241 | + final String keyword = "version "; | ||
242 | + int index = info.indexOf(keyword); | ||
243 | + line = info.substring(index + keyword.length()); | ||
244 | + index = line.indexOf(" "); | ||
245 | + kernelVersion = line.substring(0, index); | ||
246 | + } | ||
247 | + } catch (IndexOutOfBoundsException e) { | ||
248 | + e.printStackTrace(); | ||
249 | + } | ||
250 | + } catch (IOException e) { | ||
251 | + e.printStackTrace(); | ||
252 | + } finally { | ||
253 | + if (bufferedReader != null) { | ||
254 | + try { | ||
255 | + bufferedReader.close(); | ||
256 | + } catch (IOException e) { | ||
257 | + e.printStackTrace(); | ||
258 | + } | ||
259 | + } | ||
260 | + } | ||
261 | + return kernelVersion; | ||
262 | + } | ||
263 | + | ||
264 | + | ||
265 | + public static String getNetworkState(Context context) { | ||
266 | + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); | ||
267 | + if (null == cm) { | ||
268 | + return null; | ||
269 | + } | ||
270 | + NetworkInfo networkInfo = cm.getActiveNetworkInfo(); | ||
271 | + if (networkInfo == null) { | ||
272 | + return null; | ||
273 | + } | ||
274 | + String ret = networkInfo.getTypeName(); | ||
275 | + String sub = networkInfo.getSubtypeName(); | ||
276 | + if (!TextUtils.isEmpty(sub)) { | ||
277 | + ret += "-" + sub; | ||
278 | + } | ||
279 | + return ret; | ||
280 | + } | ||
281 | +} |
1 | +package com.br_technology.securitytrain_master.util; | ||
2 | + | ||
3 | +import android.content.Context; | ||
4 | +import android.text.TextUtils; | ||
5 | + | ||
6 | +import com.br_technology.securitytrain_master.base.view.BaseApplication; | ||
7 | + | ||
8 | +import org.jsoup.nodes.Document; | ||
9 | +import org.jsoup.nodes.Element; | ||
10 | + | ||
11 | +import java.util.List; | ||
12 | + | ||
13 | +public class HtmlConvert { | ||
14 | + | ||
15 | + public static String convert(Document doc, boolean isDark, String url, String img) { | ||
16 | + List<Element> list = doc.select("img"); | ||
17 | + List<Element> listVideo = doc.select("video"); | ||
18 | + for (Element element : listVideo) { | ||
19 | + String dataSource = element.attr("src"); | ||
20 | + element.attr("object-fit", "fill"); | ||
21 | + element.attr("preload", "meta"); | ||
22 | + element.removeAttr("height"); | ||
23 | + | ||
24 | + Element parent = element.parent(); | ||
25 | + parent.attr("width", "100%"); | ||
26 | + List<Element> elements = element.children(); | ||
27 | + if (elements != null && elements.size() > 0) { | ||
28 | +// elements.get(0).attr("src", "http://vfile1.hnntv.cn/2020/1605/0853/2443/160508532443.ssm/160508532443.m3u8"); | ||
29 | + element.attr("controls", "controls"); | ||
30 | + element.attr("poster", TextUtils.isEmpty(img) ? "file:///android_res/mipmap/loading_web.png" : img); | ||
31 | + } else { | ||
32 | + if (TextUtils.isEmpty(dataSource) || !dataSource.startsWith("http")) { | ||
33 | + if (!TextUtils.isEmpty(url)) { | ||
34 | + Element sou = doc.createElement("source"); | ||
35 | + sou.attr("src", url); | ||
36 | +// element.attr("src", url); | ||
37 | + sou.appendTo(element); | ||
38 | + element.attr("controls", "controls"); | ||
39 | + element.attr("poster", TextUtils.isEmpty(img) ? "file:///android_res/mipmap/loading_web.png" : img); | ||
40 | + } else { | ||
41 | + element.remove(); | ||
42 | + } | ||
43 | + } | ||
44 | + } | ||
45 | + } | ||
46 | + for (Element element : list) { | ||
47 | + element.removeAttr("class"); | ||
48 | + String souce = element.attr("src"); | ||
49 | + if (loadImage(BaseApplication.Companion.getInstance().getApplicationContext())) { | ||
50 | +// if (!souce.startsWith("http")) { | ||
51 | +// element.attr("src", ConnectUrl.BASE_URL_IMG() + souce); | ||
52 | +// } | ||
53 | + if (element.hasParent()) { | ||
54 | + Element parent = element.parent(); | ||
55 | + if (parent.tagName().equals("a")) { | ||
56 | + element.attr("alt", "none_click"); | ||
57 | + } | ||
58 | + } | ||
59 | + } else { | ||
60 | + element.attr("src", "file:///android_res/mipmap/loading_web.png"); | ||
61 | + if (element.hasParent()) { | ||
62 | + Element parent = element.parent(); | ||
63 | + if (parent.tagName().equals("a")) { | ||
64 | + element.attr("alt", "none_click"); | ||
65 | + } | ||
66 | + } | ||
67 | + } | ||
68 | +// element.attr("onclick",onClick(souce,arr)); | ||
69 | + } | ||
70 | + doc.select("br").remove(); | ||
71 | +// int fontSize = SettingKits.getFontSize(BaseApplication.Companion.getInstance().getApplicationContext()); | ||
72 | + int fontSize = 0; | ||
73 | + List<Element> spanList = doc.select("span"); | ||
74 | + for (Element element : spanList) { | ||
75 | + updateStyle(element, "font-size", "small"); | ||
76 | + } | ||
77 | + Element head = doc.head(); | ||
78 | + head.append("<meta charset=\"utf-8\">") | ||
79 | + .append("<meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" />"); | ||
80 | + if (isDark) { | ||
81 | + head.append("<style>" + | ||
82 | + "body{text-indent:0rem!important;" + | ||
83 | + "text-align:justify!important;text-justify:inter-ideograph!important;" + | ||
84 | + "word-break:break-all!important;font-color:#ffffff;overflow: hidden;}" + | ||
85 | + "img{max-width: 100%!important;height:auto}" + | ||
86 | + "video{width: 100%;display: block;}" + | ||
87 | + "p{padding:0px;overflow: hidden;" + | ||
88 | + "font-size:" + TextKits.fontSize(fontSize) + "px;" + | ||
89 | + "color:#ffffff;" + | ||
90 | + "}" + | ||
91 | + "span{color:#ffffff;text-indent:2em;}" + | ||
92 | + "</style>"); | ||
93 | + } else { | ||
94 | + head.append("<style>" + | ||
95 | + "body{text-indent:0rem!important;" + | ||
96 | + "text-align:justify!important;text-justify:inter-ideograph!important;" + | ||
97 | + "word-break:break-all!important;}" + | ||
98 | + "img{max-width: 100%!important;height:auto}" + | ||
99 | + "p{font-size:" + TextKits.fontSize(fontSize) + "px" + | ||
100 | + ";}" + | ||
101 | + "video{width:100%;}" + | ||
102 | + "span{text-indent:2em;}" + | ||
103 | + "</style>"); | ||
104 | + } | ||
105 | +// if (listVideo.size() > 0) { | ||
106 | +// head.append("<link href=\"file:///android_asset/video-js.min.css\" rel=\"stylesheet\"></link>" + | ||
107 | +// "<script src=\"file:///android_asset/video.min.js\"></script>"); | ||
108 | +// } | ||
109 | + List<Element> elements = doc.select("p"); | ||
110 | + for (Element element : elements) { | ||
111 | + List<Element> list1 = element.children(); | ||
112 | + if (list1 == null || list1.isEmpty()) { | ||
113 | + if (!isTextCenter(element)) { | ||
114 | + updateStyle(element, "text-indent", "2em"); | ||
115 | + } | ||
116 | + } else { | ||
117 | + int count = 0; | ||
118 | + for (Element element1 : list1) { | ||
119 | + if (element1.is("img") | ||
120 | + || element1.is("video") | ||
121 | + || element1.is("audio") | ||
122 | + || element1.is("a") | ||
123 | + || (element1.children() != null && !element1.children().isEmpty()) | ||
124 | + || isTextCenter(element1)) { | ||
125 | + count++; | ||
126 | + } | ||
127 | + } | ||
128 | + if (count == 0) { | ||
129 | + updateStyle(element, "text-indent", "2em"); | ||
130 | + } | ||
131 | + } | ||
132 | + } | ||
133 | + return doc.toString(); | ||
134 | + } | ||
135 | + | ||
136 | + | ||
137 | + public static String convertNone(Document doc, boolean isDark) { | ||
138 | + List<Element> list = doc.select("img"); | ||
139 | + List<Element> listVideo = doc.select("video"); | ||
140 | + for (Element element : listVideo) { | ||
141 | + element.remove(); | ||
142 | + } | ||
143 | + for (Element element : list) { | ||
144 | + element.removeAttr("class"); | ||
145 | + String souce = element.attr("src"); | ||
146 | + if (loadImage(BaseApplication.Companion.getInstance().getApplicationContext())) { | ||
147 | +// if (!souce.startsWith("http")) { | ||
148 | +// element.attr("src", ConnectUrl.BASE_URL_IMG() + souce); | ||
149 | +// } | ||
150 | + if (element.hasParent()) { | ||
151 | + Element parent = element.parent(); | ||
152 | + if (parent.tagName().equals("a")) { | ||
153 | + element.attr("alt", "none_click"); | ||
154 | + } | ||
155 | + } | ||
156 | + } else { | ||
157 | + String url = "file:///android_res/mipmap/loading_web.png"; | ||
158 | + element.attr("src", url); | ||
159 | + } | ||
160 | +// element.attr("onclick",onClick(souce,arr)); | ||
161 | + } | ||
162 | + doc.select("br").remove(); | ||
163 | +// int fontSize = SettingKits.getFontSize(BaseApplication.Companion.getInstance().getApplicationContext()); | ||
164 | + int fontSize = 0; | ||
165 | + List<Element> spanList = doc.select("span"); | ||
166 | + for (Element element : spanList) { | ||
167 | + updateStyle(element, "font-size", "small"); | ||
168 | + } | ||
169 | + Element head = doc.head(); | ||
170 | + head.append("<meta charset=\"utf-8\">") | ||
171 | + .append("<meta name=\"viewport\" content=\"initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" />"); | ||
172 | + if (isDark) { | ||
173 | + head.append("<style>" + | ||
174 | + "body{text-indent:0rem!important;" + | ||
175 | + "text-align:justify!important;text-justify:inter-ideograph!important;" + | ||
176 | + "word-break:break-all!important;font-color:#ffffff;overflow: hidden;}" + | ||
177 | + "img{max-width: 100%!important;height:auto}" + | ||
178 | + "video{width: 100%;display: block;}" + | ||
179 | + "p{padding:0px;overflow: hidden;" + | ||
180 | + "font-size:" + TextKits.fontSize(fontSize) + "px;" + | ||
181 | + "color:#ffffff;" + | ||
182 | + "}" + | ||
183 | + "span{color:#ffffff;text-indent:2em;}" + | ||
184 | + "</style>"); | ||
185 | + } else { | ||
186 | + head.append("<style>" + | ||
187 | + "body{text-indent:0rem!important;" + | ||
188 | + "text-align:justify!important;text-justify:inter-ideograph!important;" + | ||
189 | + "word-break:break-all!important;}" + | ||
190 | + "img{max-width: 100%!important;height:auto}" + | ||
191 | + "p{font-size:" + TextKits.fontSize(fontSize) + "px" + | ||
192 | + ";}" + | ||
193 | + "video{width: 100%;height:260;}" + | ||
194 | + "span{text-indent:2em;}" + | ||
195 | + "</style>"); | ||
196 | + } | ||
197 | + List<Element> elements = doc.select("p"); | ||
198 | + for (Element element : elements) { | ||
199 | + List<Element> list1 = element.children(); | ||
200 | + if (list1 == null || list1.isEmpty()) { | ||
201 | + if (!isTextCenter(element)) { | ||
202 | + updateStyle(element, "text-indent", "2em"); | ||
203 | + } | ||
204 | + } else { | ||
205 | + int count = 0; | ||
206 | + for (Element element1 : list1) { | ||
207 | + if (element1.is("img") | ||
208 | + || element1.is("video") | ||
209 | + || element1.is("audio") | ||
210 | + || element1.is("a") | ||
211 | + || (element1.children() != null && !element1.children().isEmpty()) | ||
212 | + || isTextCenter(element1)) { | ||
213 | + count++; | ||
214 | + } | ||
215 | + } | ||
216 | + if (count == 0) { | ||
217 | + updateStyle(element, "text-indent", "2em"); | ||
218 | + } | ||
219 | + } | ||
220 | + } | ||
221 | + return doc.toString(); | ||
222 | + } | ||
223 | + | ||
224 | + private static boolean loadImage(Context context) { | ||
225 | +// return DeviceUtils.isConnectionWifi(context) || !SettingKits.getLoadWifiImg(context); | ||
226 | + return true; | ||
227 | + } | ||
228 | + | ||
229 | + public static boolean isTextCenter(Element element) { | ||
230 | + if (element.hasAttr("text-align")) { | ||
231 | + String text = element.attr("text-align"); | ||
232 | + return text.contains("center"); | ||
233 | + } | ||
234 | + if (element.hasAttr("style")) { | ||
235 | + String style = element.attr("style"); | ||
236 | + return style.contains("center"); | ||
237 | + } | ||
238 | + return false; | ||
239 | + } | ||
240 | + | ||
241 | + private static void updateStyle(Element element, String attr, String value) { | ||
242 | + if (element.hasAttr("style")) { | ||
243 | + String styleStr = element.attr("style"); | ||
244 | + if (styleStr.contains(attr)) { | ||
245 | + String s1 = styleStr.substring(0, styleStr.indexOf(attr)); | ||
246 | + String s2 = styleStr.substring(styleStr.indexOf(attr)); | ||
247 | + String s3 = s2.contains(";") ? s2.substring(s2.indexOf(";")) : ""; | ||
248 | + element.removeAttr("style"); | ||
249 | + element.attr("style", s1 + attr + ":" + value + s3); | ||
250 | + } else { | ||
251 | + element.removeAttr("style"); | ||
252 | + element.attr("style", styleStr + attr + ":" + value); | ||
253 | + } | ||
254 | + } else { | ||
255 | + element.attr("style", attr + ":" + value); | ||
256 | + } | ||
257 | + } | ||
258 | +} |
1 | +package com.br_technology.securitytrain_master.util; | ||
2 | + | ||
3 | +import android.text.format.Time; | ||
4 | + | ||
5 | + | ||
6 | +public class SettingKits { | ||
7 | + | ||
8 | + public static final int SHOW_MRCODE_GUIDE_VERSION = 30;//扫一扫引导 | ||
9 | + | ||
10 | + static final String SP_NAME = "app_setting"; | ||
11 | + static boolean isUpdate; | ||
12 | + | ||
13 | + public static boolean isUpdate() { | ||
14 | + return isUpdate; | ||
15 | + } | ||
16 | + | ||
17 | + /** | ||
18 | + * - 判断当前系统时间是否在特定时间的段内 | ||
19 | + * <p> | ||
20 | + * <p> | ||
21 | + * - @param beginHour 开始的小时,例如5 | ||
22 | + * <p> | ||
23 | + * - @param beginMin 开始小时的分钟数,例如00 | ||
24 | + * <p> | ||
25 | + * - @param endHour 结束小时,例如 8 | ||
26 | + * <p> | ||
27 | + * - @param endMin 结束小时的分钟数,例如00 | ||
28 | + * <p> | ||
29 | + * - @return true表示在范围内,否则false | ||
30 | + */ | ||
31 | + public static boolean isCurrentInTimeScope(int beginHour, int beginMin, int endHour, int endMin) { | ||
32 | + boolean result = false;// 结果 | ||
33 | + final long aDayInMillis = 1000 * 60 * 60 * 24;// 一天的全部毫秒数 | ||
34 | + final long currentTimeMillis = System.currentTimeMillis();// 当前时间 | ||
35 | + | ||
36 | + Time now = new Time();// 注意这里导入的时候选择android.text.format.Time类,而不是java.sql.Time类 | ||
37 | + now.set(currentTimeMillis); | ||
38 | + | ||
39 | + Time startTime = new Time(); | ||
40 | + startTime.set(currentTimeMillis); | ||
41 | + startTime.hour = beginHour; | ||
42 | + startTime.minute = beginMin; | ||
43 | + | ||
44 | + Time endTime = new Time(); | ||
45 | + endTime.set(currentTimeMillis); | ||
46 | + endTime.hour = endHour; | ||
47 | + endTime.minute = endMin; | ||
48 | + | ||
49 | + if (!startTime.before(endTime)) { | ||
50 | + // 跨天的特殊情况(比如22:00-8:00) | ||
51 | + startTime.set(startTime.toMillis(true) - aDayInMillis); | ||
52 | + result = !now.before(startTime) && !now.after(endTime); // startTime <= now <= endTime | ||
53 | + Time startTimeInThisDay = new Time(); | ||
54 | + startTimeInThisDay.set(startTime.toMillis(true) + aDayInMillis); | ||
55 | + if (!now.before(startTimeInThisDay)) { | ||
56 | + result = true; | ||
57 | + } | ||
58 | + } else { | ||
59 | + // 普通情况(比如 8:00 - 14:00) | ||
60 | + result = !now.before(startTime) && !now.after(endTime); // startTime <= now <= endTime | ||
61 | + } | ||
62 | + return result; | ||
63 | + } | ||
64 | + | ||
65 | +} | ||
66 | + |
1 | +package com.br_technology.securitytrain_master.util; | ||
2 | + | ||
3 | +import android.content.Context; | ||
4 | +import android.graphics.Color; | ||
5 | +import android.text.Html; | ||
6 | +import android.text.Spannable; | ||
7 | +import android.text.SpannableStringBuilder; | ||
8 | +import android.text.Spanned; | ||
9 | +import android.text.TextUtils; | ||
10 | +import android.text.style.AbsoluteSizeSpan; | ||
11 | +import android.text.style.CharacterStyle; | ||
12 | +import android.text.style.ForegroundColorSpan; | ||
13 | +import android.util.Base64; | ||
14 | +import android.widget.TextView; | ||
15 | + | ||
16 | +import com.br_technology.securitytrain_master.base.view.BaseApplication; | ||
17 | + | ||
18 | +import java.math.BigDecimal; | ||
19 | +import java.security.MessageDigest; | ||
20 | +import java.security.NoSuchAlgorithmException; | ||
21 | +import java.text.SimpleDateFormat; | ||
22 | +import java.util.Date; | ||
23 | +import java.util.Locale; | ||
24 | +import java.util.regex.Matcher; | ||
25 | +import java.util.regex.Pattern; | ||
26 | + | ||
27 | +import kotlin.text.Charsets; | ||
28 | + | ||
29 | +public class TextKits { | ||
30 | + private static final int WAN = 10000; | ||
31 | + | ||
32 | + /** | ||
33 | + * MD5加密 | ||
34 | + * | ||
35 | + * @param info 要加密的字符串 | ||
36 | + * @return 加密完成的字符串 | ||
37 | + */ | ||
38 | + public static String getMD5(String info) { | ||
39 | + String result = "加密失败"; | ||
40 | + try { | ||
41 | + MessageDigest md = MessageDigest.getInstance("MD5"); | ||
42 | + md.update(info.getBytes()); | ||
43 | + byte[] b = md.digest(); | ||
44 | + int i; | ||
45 | + StringBuilder buf = new StringBuilder(""); | ||
46 | + for (byte value : b) { | ||
47 | + i = value; | ||
48 | + if (i < 0) i += 256; | ||
49 | + if (i < 16) buf.append("0"); | ||
50 | + buf.append(Integer.toHexString(i)); | ||
51 | + } | ||
52 | + result = buf.toString(); | ||
53 | + } catch (NoSuchAlgorithmException e) { | ||
54 | + e.printStackTrace(); | ||
55 | + } | ||
56 | + return result; | ||
57 | + } | ||
58 | + | ||
59 | + //中文标点符号 | ||
60 | + final static String[] chinesePunctuation = { | ||
61 | +// "!", ",", "。", ";", "《", "》", "(", ")", "?", | ||
62 | +// "{", "}", "“", ":", "【", "】", "”", "‘", "’" | ||
63 | + }; | ||
64 | + | ||
65 | + | ||
66 | + //英文标点符号 | ||
67 | + final static String[] englishPunctuation = { | ||
68 | +// "!", ",", | ||
69 | +// ".", ";", "<", ">", "(", ")", "?", "{", "}", "\"", | ||
70 | +// ":", "{", "}", "\"", "\'", "\'" | ||
71 | + }; | ||
72 | + | ||
73 | + /** | ||
74 | + * 中文标点符号转英文字标点符号 | ||
75 | + * | ||
76 | + * @param str 原字符串 | ||
77 | + * @return str 新字符串 | ||
78 | + */ | ||
79 | + public static String chinesePunctuationToEnglish(String str) { | ||
80 | + if (TextUtils.isEmpty(str)) { | ||
81 | + return str; | ||
82 | + } | ||
83 | + //去除空格 | ||
84 | +// str = str.replaceAll("\\s+", ""); | ||
85 | + for (int i = 0; i < chinesePunctuation.length; i++) { | ||
86 | + str = str.replaceAll(chinesePunctuation[i], englishPunctuation[i]); | ||
87 | + } | ||
88 | + return str; | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * 英文标点符号转中文字标点符号 | ||
93 | + * | ||
94 | + * @param str 原字符串 | ||
95 | + * @return str 新字符串 | ||
96 | + */ | ||
97 | + public static String englishPunctuationToChinese(String str) { | ||
98 | + if (TextUtils.isEmpty(str)) { | ||
99 | + return str; | ||
100 | + } | ||
101 | + //去除空格 | ||
102 | + str = str.replaceAll("\\s+", " "); | ||
103 | + for (int i = 0; i < chinesePunctuation.length; i++) { | ||
104 | + str = str.replaceAll(chinesePunctuation[i], englishPunctuation[i]); | ||
105 | + } | ||
106 | + return str; | ||
107 | + } | ||
108 | + | ||
109 | + /** | ||
110 | + * 全角转半角 | ||
111 | + */ | ||
112 | + public static String ToDBC(String input) { | ||
113 | +// char[] c = input.toCharArray(); | ||
114 | +// for (int i = 0; i < c.length; i++) { | ||
115 | +// if (c[i] == 12288) { | ||
116 | +// c[i] = (char) 32; | ||
117 | +// continue; | ||
118 | +// } | ||
119 | +// if (c[i] > 65280 && c[i] < 65375) | ||
120 | +// c[i] = (char) (c[i] - 65248); | ||
121 | +// } | ||
122 | +// return new String(c); | ||
123 | + return input; | ||
124 | + } | ||
125 | + | ||
126 | + /** | ||
127 | + *关键字高亮显示 | ||
128 | + *@param text 文字 | ||
129 | + *@param keyword1 文字中的关键字数组 | ||
130 | + * | ||
131 | + */ | ||
132 | + public static SpannableStringBuilder matcherSearchContent(String text, String[] keyword1) { | ||
133 | + String[] keyword = new String[keyword1.length]; | ||
134 | + System.arraycopy(keyword1, 0, keyword, 0, keyword1.length); | ||
135 | + SpannableStringBuilder spannable = new SpannableStringBuilder(text); | ||
136 | + | ||
137 | + CharacterStyle span; | ||
138 | + String wordReg; | ||
139 | + for (int i = 0; i < keyword.length; i++) { | ||
140 | + StringBuilder key = new StringBuilder(); | ||
141 | + // 处理通配符问题 | ||
142 | + if (keyword[i].contains("*") || keyword[i].contains("(") || keyword[i].contains(")")) { | ||
143 | + char[] chars = keyword[i].toCharArray(); | ||
144 | + for (char aChar : chars) { | ||
145 | + if (aChar == '*' || aChar == '(' || aChar == ')') { | ||
146 | + key.append("\\").append(aChar); | ||
147 | + } else { | ||
148 | + key.append(aChar); | ||
149 | + } | ||
150 | + } | ||
151 | + keyword[i] = key.toString(); | ||
152 | + } | ||
153 | + | ||
154 | + wordReg = "(?i)" + keyword[i]; //忽略字母大小写 | ||
155 | + Pattern pattern = Pattern.compile(wordReg); | ||
156 | + Matcher matcher = pattern.matcher(text); | ||
157 | + while (matcher.find()) { | ||
158 | + span = new ForegroundColorSpan(Color.parseColor("#ff5656")); | ||
159 | + spannable.setSpan(span, matcher.start(), matcher.end(), Spannable.SPAN_MARK_MARK); | ||
160 | + } | ||
161 | + } | ||
162 | + | ||
163 | + return spannable; | ||
164 | + } | ||
165 | + | ||
166 | + /** | ||
167 | + * 半角转全角 | ||
168 | + */ | ||
169 | + public static String ToSBC(String input) { | ||
170 | + char[] c = input.toCharArray(); | ||
171 | + for (int i = 0; i < c.length; i++) { | ||
172 | + if (c[i] == ' ') { | ||
173 | + c[i] = '\u3000'; | ||
174 | + } else if (c[i] < '\177') { | ||
175 | + c[i] = (char) (c[i] + 65248); | ||
176 | + } | ||
177 | + } | ||
178 | + return new String(c); | ||
179 | + } | ||
180 | + | ||
181 | + public static CharSequence getHighLightText(String text, String highText, int highColor) { | ||
182 | + if (TextUtils.isEmpty(highText)) { | ||
183 | + return text; | ||
184 | + } | ||
185 | + text = TextKits.englishPunctuationToChinese(text); | ||
186 | + if (!TextUtils.isEmpty(text) && text.contains(highText)) { | ||
187 | + SpannableStringBuilder builder = new SpannableStringBuilder(text); | ||
188 | + | ||
189 | + int index = text.indexOf(highText); | ||
190 | + while (index >= 0) { | ||
191 | + builder.setSpan(new ForegroundColorSpan(highColor), index, index + highText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); | ||
192 | + index = text.indexOf(highText, index + highText.length()); | ||
193 | + } | ||
194 | + | ||
195 | + return builder; | ||
196 | + } | ||
197 | + return text; | ||
198 | + } | ||
199 | + | ||
200 | + public static CharSequence getHighLightTextNew(String text, String highText, int highColor) { | ||
201 | + if (TextUtils.isEmpty(highText)) { | ||
202 | + return text; | ||
203 | + } | ||
204 | + if (!TextUtils.isEmpty(text) && text.contains(highText)) { | ||
205 | + SpannableStringBuilder builder = new SpannableStringBuilder(text); | ||
206 | + int index = text.indexOf(highText); | ||
207 | + builder.setSpan(new ForegroundColorSpan(highColor), index, index + highText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); | ||
208 | + return builder; | ||
209 | + } | ||
210 | + return text; | ||
211 | + } | ||
212 | + | ||
213 | + public static void setHighLightTextHtml(String text, String highText, int highColor, TextView textView) { | ||
214 | + String color = ColorTransHelp.toHexEncoding(highColor); | ||
215 | + String font = "<font color='" + color + "'>" + highText + "</font>"; | ||
216 | + String str = text.replaceAll(highText, font); | ||
217 | + textView.setText(Html.fromHtml(str)); | ||
218 | + } | ||
219 | + | ||
220 | + public static CharSequence getLabelText(String text, String big, int sizeBig) { | ||
221 | + if (TextUtils.isEmpty(big)) { | ||
222 | + return text; | ||
223 | + } | ||
224 | + Context context = BaseApplication.Companion.getInstance().getApplicationContext(); | ||
225 | + if (!TextUtils.isEmpty(text) && text.contains(big)) { | ||
226 | + SpannableStringBuilder builder = new SpannableStringBuilder(text); | ||
227 | + | ||
228 | + AbsoluteSizeSpan span = new AbsoluteSizeSpan(TranslateUnit.px2dp(context, TranslateUnit.sp2px(context, sizeBig)), true); | ||
229 | + builder.setSpan(span, 0, big.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); | ||
230 | + return builder; | ||
231 | + } | ||
232 | + return text; | ||
233 | + } | ||
234 | + | ||
235 | + public static String formatCommentCount(int count) { | ||
236 | + if (count < WAN) { | ||
237 | + return String.valueOf(count); | ||
238 | + } else { | ||
239 | + return new BigDecimal(count * 1.0f / WAN).setScale(1, BigDecimal.ROUND_HALF_UP).toString() + "W"; | ||
240 | + } | ||
241 | + } | ||
242 | + | ||
243 | + public static String formatPhone(String phone) { | ||
244 | + if (phone.length() >= 11) { | ||
245 | + return phone.substring(0, 3) + "****" + phone.substring(7); | ||
246 | + } else return "待完善"; | ||
247 | + } | ||
248 | + | ||
249 | + public static void setTextNickName(TextView textView, String name, String cell) { | ||
250 | + String cell_str = TextKits.formatPhone(cell); | ||
251 | + name = TextUtils.isEmpty(name) ? (TextUtils.isEmpty(cell_str) ? "待完善" : cell_str) : name; | ||
252 | + textView.setText(name); | ||
253 | + } | ||
254 | + | ||
255 | + public static String limitCount(String text, int length) { | ||
256 | + if (text == null) { | ||
257 | + return ""; | ||
258 | + } | ||
259 | + if (text.length() > length) { | ||
260 | + return text.substring(0, length) + "…"; | ||
261 | + } | ||
262 | + return text; | ||
263 | + } | ||
264 | + | ||
265 | + public static int fontSize(int font) { | ||
266 | + switch (font) { | ||
267 | + case 0: | ||
268 | + return 13; | ||
269 | + case 1: | ||
270 | + return 15; | ||
271 | + case 2: | ||
272 | + return 16; | ||
273 | + case 3: | ||
274 | + return 17; | ||
275 | + default: | ||
276 | + return 0; | ||
277 | + } | ||
278 | + } | ||
279 | + | ||
280 | + public static String decodeToString(String str) { | ||
281 | + String s = str.replace("\t", "").replace("\n", "") | ||
282 | + .replace("\r", "").trim(); | ||
283 | + try { | ||
284 | + if (isBase64(s)) { | ||
285 | + byte[] bytes = Base64.decode(s.getBytes(Charsets.UTF_8), Base64.DEFAULT); | ||
286 | + String decode = new String(bytes).trim(); | ||
287 | + return (!decode.isEmpty() && !isMessyCode(decode)) ? decode : s; | ||
288 | + } | ||
289 | + return s; | ||
290 | + } catch (Exception e) { | ||
291 | + e.printStackTrace(); | ||
292 | + return s; | ||
293 | + } | ||
294 | + } | ||
295 | + | ||
296 | + /** | ||
297 | + * 判断是否为乱码 | ||
298 | + * | ||
299 | + * @param str | ||
300 | + * @return | ||
301 | + */ | ||
302 | + private static boolean isMessyCode(String str) { | ||
303 | + return str.contains("�"); | ||
304 | + } | ||
305 | + | ||
306 | + public static boolean isComment(String s) { | ||
307 | + return Pattern.matches("^[\\\\w\\u4E00-\\u9FA5\\uF900-\\uFA2D\\\\s]*$", s); | ||
308 | + } | ||
309 | + | ||
310 | + private static boolean isBase64(String str) { | ||
311 | + return Pattern.matches("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$", str); | ||
312 | + } | ||
313 | + | ||
314 | + public static String fontSizeSpan(int font) { | ||
315 | + switch (font) { | ||
316 | + case -1: | ||
317 | + return "small"; | ||
318 | + case 0: | ||
319 | + return "large"; | ||
320 | + case 2: | ||
321 | + return "x-large"; | ||
322 | + case 3: | ||
323 | + return "xx-large"; | ||
324 | + default: | ||
325 | + return "medium"; | ||
326 | + } | ||
327 | + } | ||
328 | + | ||
329 | + private static final SimpleDateFormat format = new SimpleDateFormat("MM月dd日", Locale.CHINA); | ||
330 | + private static final SimpleDateFormat formatDay = new SimpleDateFormat("yyyyMMdd", Locale.CHINA); | ||
331 | + private static final SimpleDateFormat formatTime = new SimpleDateFormat("HHmmss", Locale.CHINA); | ||
332 | + private static final SimpleDateFormat formatTimeSub = new SimpleDateFormat("HH:mm", Locale.CHINA); | ||
333 | + | ||
334 | + | ||
335 | + public static String timeSub(String time) { | ||
336 | + try { | ||
337 | + Date date = formatTime.parse(time); | ||
338 | + if (date != null) { | ||
339 | + return formatTimeSub.format(date); | ||
340 | + } | ||
341 | + } catch (Exception e) { | ||
342 | + e.printStackTrace(); | ||
343 | + } | ||
344 | + return ""; | ||
345 | + } | ||
346 | +} |
1 | +package com.br_technology.securitytrain_master.view | ||
2 | + | ||
3 | +import android.app.Dialog | ||
4 | +import android.content.Context | ||
5 | +import android.os.Bundle | ||
6 | +import android.view.LayoutInflater | ||
7 | +import com.br_technology.securitytrain_master.R | ||
8 | +import com.br_technology.securitytrain_master.databinding.DialogMentionBinding | ||
9 | +import com.br_technology.securitytrain_master.expand.dp2px | ||
10 | +import com.br_technology.securitytrain_master.expand.screenWidth | ||
11 | + | ||
12 | +/** | ||
13 | + * Author by YSir | ||
14 | + * Date on 2022/1/25. | ||
15 | + * description | ||
16 | + * PS: Not easy to write code, please indicate. | ||
17 | + */ | ||
18 | +class DialogMention(context: Context) : Dialog(context, R.style.UserDefaultDialog) { | ||
19 | + private lateinit var listener: () -> Unit | ||
20 | + private val binding by lazy { | ||
21 | + DialogMentionBinding.inflate(LayoutInflater.from(context)) | ||
22 | + } | ||
23 | + | ||
24 | + override fun onCreate(savedInstanceState: Bundle?) { | ||
25 | + super.onCreate(savedInstanceState) | ||
26 | + setContentView(binding.root) | ||
27 | + val attributes = window?.attributes | ||
28 | + attributes?.width = binding.root.screenWidth() - 32.dp2px() | ||
29 | + // 点击区域外取消 | ||
30 | + setCanceledOnTouchOutside(true) | ||
31 | + setCancelable(true) | ||
32 | + binding.apply { | ||
33 | + // 确定 | ||
34 | + tvCancel.setOnClickListener { | ||
35 | + dismiss() | ||
36 | + } | ||
37 | + tvEnsure.setOnClickListener { | ||
38 | + if (::listener.isInitialized) { | ||
39 | + listener.invoke() | ||
40 | + } | ||
41 | + } | ||
42 | + } | ||
43 | + } | ||
44 | + | ||
45 | + fun setListener(listener: () -> Unit): DialogMention { | ||
46 | + this.listener = listener | ||
47 | + return this | ||
48 | + } | ||
49 | + | ||
50 | + fun setTitle(title: String): DialogMention { | ||
51 | + binding.tvTitle.text = title | ||
52 | + return this | ||
53 | + } | ||
54 | + | ||
55 | + fun setMention(title: String): DialogMention { | ||
56 | + binding.tvMention.text = title | ||
57 | + return this | ||
58 | + } | ||
59 | + | ||
60 | +} |
@@ -4,6 +4,8 @@ import android.content.Context | @@ -4,6 +4,8 @@ import android.content.Context | ||
4 | import android.util.AttributeSet | 4 | import android.util.AttributeSet |
5 | import android.webkit.WebView | 5 | import android.webkit.WebView |
6 | import com.br_technology.securitytrain_master.expand.dp2px | 6 | import com.br_technology.securitytrain_master.expand.dp2px |
7 | +import com.br_technology.securitytrain_master.util.HtmlConvert | ||
8 | +import org.jsoup.Jsoup | ||
7 | 9 | ||
8 | /** | 10 | /** |
9 | * createTime:2021/8/4 9:21 | 11 | * createTime:2021/8/4 9:21 |
@@ -29,6 +31,12 @@ class MyWebView(context: Context, attrs: AttributeSet?) : WebView(context, attrs | @@ -29,6 +31,12 @@ class MyWebView(context: Context, attrs: AttributeSet?) : WebView(context, attrs | ||
29 | 31 | ||
30 | 32 | ||
31 | fun loadData(data: String) { | 33 | fun loadData(data: String) { |
32 | - loadDataWithBaseURL(null, data, "text/html", "utf-8", null) | 34 | + val html = HtmlConvert.convert( |
35 | + Jsoup.parse(data), | ||
36 | + false, | ||
37 | + "", | ||
38 | + "" | ||
39 | + ) | ||
40 | + loadDataWithBaseURL(null, html, "text/html", "utf-8", null) | ||
33 | } | 41 | } |
34 | } | 42 | } |
@@ -87,6 +87,7 @@ | @@ -87,6 +87,7 @@ | ||
87 | android:textSize="12sp" /> | 87 | android:textSize="12sp" /> |
88 | 88 | ||
89 | <TextView | 89 | <TextView |
90 | + android:id="@+id/tvClassName" | ||
90 | android:layout_width="wrap_content" | 91 | android:layout_width="wrap_content" |
91 | android:layout_height="wrap_content" | 92 | android:layout_height="wrap_content" |
92 | android:layout_marginTop="15dp" | 93 | android:layout_marginTop="15dp" |
@@ -116,6 +117,7 @@ | @@ -116,6 +117,7 @@ | ||
116 | android:textSize="12sp" /> | 117 | android:textSize="12sp" /> |
117 | 118 | ||
118 | <TextView | 119 | <TextView |
120 | + android:id="@+id/tv_class_type" | ||
119 | android:layout_width="wrap_content" | 121 | android:layout_width="wrap_content" |
120 | android:layout_height="wrap_content" | 122 | android:layout_height="wrap_content" |
121 | android:layout_marginTop="15dp" | 123 | android:layout_marginTop="15dp" |
@@ -144,6 +146,7 @@ | @@ -144,6 +146,7 @@ | ||
144 | android:textSize="12sp" /> | 146 | android:textSize="12sp" /> |
145 | 147 | ||
146 | <TextView | 148 | <TextView |
149 | + android:id="@+id/tv_time" | ||
147 | android:layout_width="wrap_content" | 150 | android:layout_width="wrap_content" |
148 | android:layout_height="wrap_content" | 151 | android:layout_height="wrap_content" |
149 | android:layout_marginTop="15dp" | 152 | android:layout_marginTop="15dp" |
@@ -172,6 +175,7 @@ | @@ -172,6 +175,7 @@ | ||
172 | android:textSize="12sp" /> | 175 | android:textSize="12sp" /> |
173 | 176 | ||
174 | <TextView | 177 | <TextView |
178 | + android:id="@+id/tv_company" | ||
175 | android:layout_width="wrap_content" | 179 | android:layout_width="wrap_content" |
176 | android:layout_height="wrap_content" | 180 | android:layout_height="wrap_content" |
177 | android:layout_marginTop="15dp" | 181 | android:layout_marginTop="15dp" |
@@ -200,6 +204,7 @@ | @@ -200,6 +204,7 @@ | ||
200 | android:textSize="12sp" /> | 204 | android:textSize="12sp" /> |
201 | 205 | ||
202 | <TextView | 206 | <TextView |
207 | + android:id="@+id/tv_lesson" | ||
203 | android:layout_width="wrap_content" | 208 | android:layout_width="wrap_content" |
204 | android:layout_height="wrap_content" | 209 | android:layout_height="wrap_content" |
205 | android:layout_marginTop="15dp" | 210 | android:layout_marginTop="15dp" |
@@ -64,17 +64,23 @@ | @@ -64,17 +64,23 @@ | ||
64 | android:layout_marginEnd="16dp" | 64 | android:layout_marginEnd="16dp" |
65 | android:text="" | 65 | android:text="" |
66 | android:textColor="@color/color_32" | 66 | android:textColor="@color/color_32" |
67 | - android:textSize="26sp" /> | 67 | + android:textSize="18sp" /> |
68 | 68 | ||
69 | <com.br_technology.securitytrain_master.view.MyWebView | 69 | <com.br_technology.securitytrain_master.view.MyWebView |
70 | android:id="@+id/content" | 70 | android:id="@+id/content" |
71 | android:layout_width="match_parent" | 71 | android:layout_width="match_parent" |
72 | - android:layout_height="match_parent" | 72 | + android:layout_height="wrap_content" |
73 | android:layout_marginStart="16dp" | 73 | android:layout_marginStart="16dp" |
74 | android:layout_marginTop="16dp" | 74 | android:layout_marginTop="16dp" |
75 | android:layout_marginEnd="16dp" | 75 | android:layout_marginEnd="16dp" |
76 | android:overScrollMode="never" | 76 | android:overScrollMode="never" |
77 | android:scrollbars="none" /> | 77 | android:scrollbars="none" /> |
78 | + | ||
79 | + <androidx.recyclerview.widget.RecyclerView | ||
80 | + android:id="@+id/pdf" | ||
81 | + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" | ||
82 | + android:layout_width="match_parent" | ||
83 | + android:layout_height="wrap_content"/> | ||
78 | </LinearLayout> | 84 | </LinearLayout> |
79 | </androidx.core.widget.NestedScrollView> | 85 | </androidx.core.widget.NestedScrollView> |
80 | 86 |
app/src/main/res/layout/dialog_mention.xml
0 → 100644
1 | +<?xml version="1.0" encoding="utf-8"?> | ||
2 | +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
3 | + android:layout_width="match_parent" | ||
4 | + android:layout_height="match_parent"> | ||
5 | + | ||
6 | + <LinearLayout | ||
7 | + android:layout_width="match_parent" | ||
8 | + android:layout_height="wrap_content" | ||
9 | + android:layout_margin="16dp" | ||
10 | + android:background="@drawable/shape_dialog_corner" | ||
11 | + android:gravity="center_vertical" | ||
12 | + android:orientation="vertical"> | ||
13 | + | ||
14 | + <TextView | ||
15 | + android:id="@+id/tv_title" | ||
16 | + android:layout_width="match_parent" | ||
17 | + android:layout_height="56dp" | ||
18 | + android:gravity="center_vertical" | ||
19 | + android:padding="12dp" | ||
20 | + android:text="温馨提示" | ||
21 | + android:textColor="@color/black" | ||
22 | + android:textSize="18sp" /> | ||
23 | + | ||
24 | + <TextView | ||
25 | + android:id="@+id/tv_mention" | ||
26 | + android:layout_width="match_parent" | ||
27 | + android:layout_height="wrap_content" | ||
28 | + android:padding="12dp" | ||
29 | + android:text="@string/app_name" /> | ||
30 | + | ||
31 | + <LinearLayout | ||
32 | + android:layout_width="match_parent" | ||
33 | + android:layout_height="44dp" | ||
34 | + android:orientation="horizontal"> | ||
35 | + | ||
36 | + <TextView | ||
37 | + android:id="@+id/tv_cancel" | ||
38 | + android:layout_width="0dp" | ||
39 | + android:layout_height="match_parent" | ||
40 | + android:layout_weight="1" | ||
41 | + android:foreground="?android:attr/selectableItemBackground" | ||
42 | + android:gravity="center" | ||
43 | + android:text="取消" | ||
44 | + android:textColor="@color/black" | ||
45 | + android:textSize="18sp" /> | ||
46 | + | ||
47 | + <View | ||
48 | + android:layout_width="1dp" | ||
49 | + android:layout_height="match_parent" | ||
50 | + android:background="@color/text_light_gray" /> | ||
51 | + | ||
52 | + <TextView | ||
53 | + android:id="@+id/tv_ensure" | ||
54 | + android:layout_width="0dp" | ||
55 | + android:layout_height="match_parent" | ||
56 | + android:layout_weight="1" | ||
57 | + android:foreground="?android:attr/selectableItemBackground" | ||
58 | + android:gravity="center" | ||
59 | + android:text="确认" | ||
60 | + android:textColor="@color/black" | ||
61 | + android:textSize="18sp" /> | ||
62 | + </LinearLayout> | ||
63 | + </LinearLayout> | ||
64 | +</FrameLayout> |
@@ -3,6 +3,8 @@ | @@ -3,6 +3,8 @@ | ||
3 | android:layout_width="match_parent" | 3 | android:layout_width="match_parent" |
4 | android:layout_height="258dp" | 4 | android:layout_height="258dp" |
5 | android:id="@+id/content_course" | 5 | android:id="@+id/content_course" |
6 | + android:layout_marginStart="16dp" | ||
7 | + android:layout_marginEnd="16dp" | ||
6 | android:background="@drawable/solid_eff2_4" | 8 | android:background="@drawable/solid_eff2_4" |
7 | android:orientation="vertical"> | 9 | android:orientation="vertical"> |
8 | 10 |
@@ -8,7 +8,6 @@ | @@ -8,7 +8,6 @@ | ||
8 | android:layout_width="match_parent" | 8 | android:layout_width="match_parent" |
9 | android:layout_height="136dp" | 9 | android:layout_height="136dp" |
10 | android:layout_marginStart="16dp" | 10 | android:layout_marginStart="16dp" |
11 | - android:layout_marginTop="16dp" | ||
12 | android:layout_marginEnd="16dp" | 11 | android:layout_marginEnd="16dp" |
13 | android:background="@drawable/solid_eff2_4"> | 12 | android:background="@drawable/solid_eff2_4"> |
14 | 13 |
@@ -4,12 +4,13 @@ | @@ -4,12 +4,13 @@ | ||
4 | android:layout_width="match_parent" | 4 | android:layout_width="match_parent" |
5 | android:layout_height="wrap_content" | 5 | android:layout_height="wrap_content" |
6 | android:background="@color/white" | 6 | android:background="@color/white" |
7 | + android:layout_marginStart="16dp" | ||
8 | + android:layout_marginEnd="16dp" | ||
7 | android:orientation="vertical"> | 9 | android:orientation="vertical"> |
8 | 10 | ||
9 | <LinearLayout | 11 | <LinearLayout |
10 | android:layout_width="match_parent" | 12 | android:layout_width="match_parent" |
11 | android:layout_height="83dp" | 13 | android:layout_height="83dp" |
12 | - android:layout_marginBottom="16dp" | ||
13 | android:background="@drawable/solid_eff2_4" | 14 | android:background="@drawable/solid_eff2_4" |
14 | android:orientation="vertical"> | 15 | android:orientation="vertical"> |
15 | 16 |
21.2 KB
-
请 注册 或 登录 后发表评论