Browse Source

task

master
suliang 2 years ago
parent
commit
997d39dec6

+ 1
- 0
.idea/misc.xml View File

@@ -90,6 +90,7 @@
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_empty.xml" value="0.4979166666666667" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_historical_route.xml" value="0.4859375" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_spell_single_word.xml" value="0.23632218844984804" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/item_task_image.xml" value="0.23353596757852077" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_course_progress.xml" value="0.25" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/main_item_coursepack.xml" value="0.43500866551126516" />
<entry key="..\:/Work/XKL/XKL/XklLocal/app/src/main/res/layout/merge_recyclerview_smart_refresh_layout.xml" value="0.34427083333333336" />

+ 2
- 0
app/build.gradle View File

@@ -107,5 +107,7 @@ dependencies {
implementation customDependencies.grpc_android
implementation customDependencies.grpc_protobuf
implementation customDependencies.grpc_stub
//XPopup
implementation customDependencies.XPopup

}

BIN
app/src/main/assets/d166b57b-21c7-4c58-a78d-748a57941052.db View File


BIN
app/src/main/assets/d166b57b-21c7-4c58-a78d-748a57941052.zip View File


+ 32
- 0
app/src/main/java/com/xkl/cdl/adapter/AdapterImageTask.kt View File

@@ -0,0 +1,32 @@
package com.xkl.cdl.adapter

import android.view.ViewGroup
import android.widget.ImageView
import com.suliang.common.base.adapter.BaseAdapterViewHolder
import com.suliang.common.base.adapter.BaseRVAdapterVM
import com.suliang.common.extension.click
import com.suliang.common.util.image.ImageLoader
import com.xkl.cdl.R
import com.xkl.cdl.module.learn.LearnCTaskViewModel
import java.io.File

/**
* author suliang
* create 2022/5/23 14:44
* Describe:
*/
class AdapterImageTask(viewModel : LearnCTaskViewModel) : BaseRVAdapterVM<File, LearnCTaskViewModel>(viewModel) {
override fun coverViewHolder(parent : ViewGroup, viewType : Int) : BaseAdapterViewHolder {
return BaseAdapterViewHolder(inflateBinding(parent, R.layout.item_task_image))
}
override fun onBindVH(holder : BaseAdapterViewHolder, position : Int) {
ImageLoader.loadImage(holder.binding.root as ImageView,getItem(position))
holder.binding.root.click {
if (onItemClickIsInitialized()){
onItemClick.invoke(it,position,getItem(position))
}
}
}
}

+ 0
- 65
app/src/main/java/com/xkl/cdl/data/bean/CompositionTaskBean.java View File

@@ -1,65 +0,0 @@
package com.xkl.cdl.data.bean;

import java.io.Serializable;

/**
* author suliang
* create 2021/4/6 18:25
* Describe: 作文课外练习实体
*/
public class CompositionTaskBean {
private long taskId; //数据id
private int stage; //阶段
private int type; //类型
private String title; //标题
private String introduce; //介绍
private String photo; //图片

public long getTaskId() {
return taskId;
}

public void setTaskId(long taskId) {
this.taskId = taskId;
}

public int getStage() {
return stage;
}

public void setStage(int stage) {
this.stage = stage;
}

public int getType() {
return type;
}

public void setType(int type) {
this.type = type;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getIntroduce() {
return introduce;
}

public void setIntroduce(String introduce) {
this.introduce = introduce;
}

public String getPhoto() {
return photo;
}

public void setPhoto(String photo) {
this.photo = photo;
}
}

+ 14
- 0
app/src/main/java/com/xkl/cdl/data/bean/CompositionTaskBean.kt View File

@@ -0,0 +1,14 @@
package com.xkl.cdl.data.bean

/**
* author suliang
* create 2021/4/6 18:25
* Describe: 作文课外练习实体
*/
data class CompositionTaskBean(val taskId : Long, //数据id
val stage : Long, //阶段
val type : Long, //类型
val title : String, //标题
var introduce : String?, //介绍
var photo : String?,
val position : Int)

+ 45
- 6
app/src/main/java/com/xkl/cdl/data/manager/CourseManager.kt View File

@@ -1,15 +1,18 @@
package com.xkl.cdl.data.manager

import appApi.AppApi
import com.suliang.common.util.AppGlobals
import com.suliang.common.util.file.FileUtil
import com.xkl.cdl.data.AppConstants
import com.xkl.cdl.data.bean.course.CoursePack
import com.xkl.cdl.data.bean.course.ExamBean
import com.xkl.cdl.data.bean.course.Lesson
import java.io.File
import java.io.*
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat
import java.util.zip.ZipFile
import java.util.zip.ZipInputStream

/**
* author suliang
@@ -66,16 +69,52 @@ object CourseManager {
/***
* 检查课程包下课程的db数据文件是否存在,不存在,则复制过去
* 作文是.zip结尾的文件,需要解压,将文件放入对应的目录
*/
fun checkCourseDb() {
subjectWithCoursePackMap.forEach { entry ->
entry.value.forEach { coursePack ->
coursePack.childrenCourses.forEach {
val file = File(FileUtil.getSaveDirPath("db"),
"${entry.key}/${coursePack.coursePackId}/${it.courseId}/course.db")
//不存在,复制,存在则不操作
if (!file.exists()) {
FileUtil.copyAsset(it.dbPathName, file)
//如果是作文,作文需要检查数据库,同时需要检查其下的图片、视频和关键帧
if (it.subjectId == AppConstants.SUBJECT_CHINESE && it.coursePackType == AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION){
val assetFileName = it.dbPathName.substringBeforeLast(".") + ".zip"
val inputStream = AppGlobals.application.resources.assets.open(assetFileName)
val zipInputStream = ZipInputStream(inputStream)
var count = 0
val buffer = ByteArray(5120)
var nextEntry = zipInputStream.nextEntry
while (nextEntry != null){
when{
nextEntry.name.endsWith(".mp4.png") -> File(FilePathManager.getMp4PngRootPath(),"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${nextEntry.name.substringAfterLast("/")}")
nextEntry.name.endsWith(".mp4") -> File(FilePathManager.getMp4RootPath(),"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${nextEntry.name.substringAfterLast("/")}")
nextEntry.name.endsWith(".png") -> File(FilePathManager.getPngRootPath(),"${entry.key}/${coursePack.coursePackId}/${it.courseId}/${nextEntry.name.substringAfterLast("/")}")
nextEntry.name.endsWith(".db") -> File(FilePathManager.getDbRootPath(),"${entry.key}/${coursePack.coursePackId}/${it.courseId}/course.db")
else -> null
}?.let { file ->
//文件不存在 ,复制当前文件进入该文件
if (!file.exists()){
file.parentFile?.let { parentFile ->
if (!parentFile.exists()) parentFile.mkdirs()
}
val outputStream = BufferedOutputStream(FileOutputStream(file))
while ((zipInputStream.read(buffer).also { count = it }) != -1 ){
outputStream.write(buffer,0,count)
}
outputStream.close()
}
}
nextEntry = zipInputStream.nextEntry
}
}else{ //其他的项目只需要复制和检查数据库
val file = File(FilePathManager.getDbRootPath(), "${entry.key}/${coursePack.coursePackId}/${it.courseId}/course.db")
//不存在,复制,存在则不操作
if (!file.exists()) {
FileUtil.copyAsset(it.dbPathName, file)
}
}
}
}

+ 25
- 3
app/src/main/java/com/xkl/cdl/data/manager/FilePathManager.kt View File

@@ -18,17 +18,39 @@ class FilePathManager {
*/
@JvmStatic
fun getCoursePackDbPath(): File{
return File(FileUtil.getSaveDirPath("db"), "course-pack.db")
return File(getDbRootPath(), "course-pack.db")
}
/** 获取课程数据地址 */
@JvmStatic
fun getCourseDbPath(base:DbControlBase): File{
return File(FileUtil.getSaveDirPath("db"), "${base.subjectId}/${base.coursePackId}/${base.courseId}/course.db")
return File(getDbRootPath(), "${base.subjectId}/${base.coursePackId}/${base.courseId}/course.db")
}
/** 获取课程数据地址 */
@JvmStatic
fun getCourseDbPath(subjectId:Int,coursePackId:Long,courseId:Long): File{
return File(FileUtil.getSaveDirPath("db"), "subjectId/coursePackId/courseId/course.db")
return File(getDbRootPath(), "subjectId/coursePackId/courseId/course.db")
}
/** db文件保存的文件夹 */
fun getDbRootPath(): String{
return FileUtil.getSaveDirPath("db")
}
/**作文mp4.png保存的文件夹*/
fun getMp4PngRootPath():String{
return FileUtil.getSaveDirPath("mp4png")
}
/**作文课外练习png保存的文件夹*/
fun getPngRootPath():String{
return FileUtil.getSaveDirPath("png")
}
/**作文课外练习png保存的文件*/
fun getPngFile(subjectId : Int,coursePackId : Long,courseId : Long, pngName:String):File{
return File(getPngRootPath(),"$subjectId/$coursePackId/$courseId/$pngName")
}
/**作文视频MP4保存的文件夹*/
fun getMp4RootPath():String{
return FileUtil.getSaveDirPath("mp4")
}

}

+ 91
- 96
app/src/main/java/com/xkl/cdl/data/manager/db/DBCourseManager.kt View File

@@ -44,12 +44,10 @@ object DBCourseManager {
val p = when (base.courseType) {
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> COMPOSITION
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> SPOKEN
AppConstants.COURSE_TYPE_CHINESE_LITERACY,AppConstants.COURSE_TYPE_CHINESE_PINYIN -> LITERACY_PINYING
AppConstants.COURSE_TYPE_CHINESE_LITERACY, AppConstants.COURSE_TYPE_CHINESE_PINYIN -> LITERACY_PINYING
else -> NORMAL
}
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getCourseDbPath(currentBase).path,
p,
null,
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getCourseDbPath(currentBase).path, p, null,
SQLiteDatabase.OPEN_READONLY)
}
if (mDataBase == null) {
@@ -89,7 +87,7 @@ object DBCourseManager {
val lessonId = it.getLong(it.getColumnIndex("lesson_id"))
val lessonName : String = when (base.courseType) {
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION, AppConstants.COURSE_TYPE_CHINESE_LITERACY, AppConstants.COURSE_TYPE_CHINESE_PINYIN -> it.getString(
it.getColumnIndex("lesson_title"))
it.getColumnIndex("lesson_title"))
else -> it.getString(it.getColumnIndex("lesson"))
}
val wordIds : MutableList<Long> = when (base.courseType) {
@@ -109,15 +107,8 @@ object DBCourseManager {
// 注:针对口语对话课时,如果没有学习完,是不会设置进度点的。 todo 分课程类型设置进度点
val learnIsOver = wordIds.size - 1 == learnIndex
val lesson = Lesson(base.subjectId,
base.coursePackId,
base.coursePackType,
base.courseId,
base.courseType,
chapterId,
chapterName,
lessonId,
lessonName).apply {
val lesson = Lesson(base.subjectId, base.coursePackId, base.coursePackType, base.courseId, base.courseType,
chapterId, chapterName, lessonId, lessonName).apply {
lessonPositionInList = positionIndex
this.wordIds = wordIds //内容
totalNumber = this.wordIds.size //总数
@@ -132,12 +123,12 @@ object DBCourseManager {
mutableList.add(lesson)
positionIndex += 1
// TODO: 2022/5/9 对课时数量进行限制,课时太多,开发人员不好进行测试
val needBreak = when(base.coursePackType){
val needBreak = when (base.coursePackType) {
AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION -> positionIndex == 11 //保留十个课时
AppConstants.COURSEPACK_TYPE_ENGLISH_SPOKEN -> positionIndex == 7 //保留六个课时
else -> positionIndex == 3 //保留三个课时
}
if (needBreak){
if (needBreak) {
break
}
}
@@ -164,7 +155,9 @@ object DBCourseManager {
}
val sql = when (base.courseType) {
//作文知识点测试
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> "SELECT * FROM exam WHERE chapter_id = ${lesson!!.chapterId} AND exam_id in (${Joiner.on(",").join(lesson.wordIds)}) ORDER BY random()"
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> "SELECT * FROM exam WHERE chapter_id = ${lesson!!.chapterId} AND exam_id in (${
Joiner.on(",").join(lesson.wordIds)
}) ORDER BY random()"
AppConstants.COURSE_TYPE_ENGLISH_DISCERN, AppConstants.COURSE_TYPE_ENGLISH_VOICE,
AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK, AppConstants.COURSE_TYPE_CHINESE_LITERACY,
@@ -203,7 +196,7 @@ object DBCourseManager {
mDataBase?.rawQuery(sql, null)?.run {
when (base.courseType) {
//作文知识点测试
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> while (moveToNext()) {
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> while (moveToNext()) {
result.add(ExamBean().apply {
id = getLong(3)
word_id = getLong(2)
@@ -218,23 +211,21 @@ object DBCourseManager {
})
}
AppConstants.COURSE_TYPE_ENGLISH_DISCERN, AppConstants.COURSE_TYPE_ENGLISH_VOICE,
AppConstants.COURSE_TYPE_CHINESE_LITERACY,
AppConstants.COURSE_TYPE_CHINESE_PINYIN -> while (moveToNext()) {
result.add(ExamBean().apply {
id = getLong(0)
word_id = getLong(1)
word = getString(2)
correct = getString(3)
error1 = getString(4)
error2 = getString(5)
error3 = getString(6)
type = AppConstants.TEST_QUEST_TYPE_CHOICE // 为1
chapterId = getLong(8)
lessonId = getLong(9)
})
}
AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK -> while (moveToNext()) {
AppConstants.COURSE_TYPE_ENGLISH_DISCERN, AppConstants.COURSE_TYPE_ENGLISH_VOICE, AppConstants.COURSE_TYPE_CHINESE_LITERACY, AppConstants.COURSE_TYPE_CHINESE_PINYIN -> while (moveToNext()) {
result.add(ExamBean().apply {
id = getLong(0)
word_id = getLong(1)
word = getString(2)
correct = getString(3)
error1 = getString(4)
error2 = getString(5)
error3 = getString(6)
type = AppConstants.TEST_QUEST_TYPE_CHOICE // 为1
chapterId = getLong(8)
lessonId = getLong(9)
})
}
AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK -> while (moveToNext()) {
result.add(ExamBean().apply {
id = getLong(0)
word_id = getLong(1)
@@ -355,28 +346,24 @@ object DBCourseManager {
//不为空,写入本身,如果为空,用另外的发音方式写入
val parentPath = FileUtil.getSaveDirPath(AppConfig.VOICE)
val audio_us_file_path = audio_us?.let {
val audioFileNameUS =
"${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_US}"
val audioFileNameUS = "${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_US}"
val file = File(parentPath, audioFileNameUS)
FileUtil.writeBytesToFile(file, it)
file.path
} ?: audio_uk?.let {
val audioFileNameUS =
"${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_US}"
val audioFileNameUS = "${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_US}"
val file = File(parentPath, audioFileNameUS)
FileUtil.writeBytesToFile(file, it)
file.path
}
//不为空,写入本身,如果为空,用另外的发音方式写入
val audio_uk_file_path = audio_uk?.let {
val audioFileNameUk =
"${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_UK}"
val audioFileNameUk = "${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_UK}"
val file = File(parentPath, audioFileNameUk)
FileUtil.writeBytesToFile(file, it)
file.path
} ?: audio_us?.let {
val audioFileNameUk =
"${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_UK}"
val audioFileNameUk = "${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_UK}"
val file = File(parentPath, audioFileNameUk)
FileUtil.writeBytesToFile(file, it)
file.path
@@ -392,8 +379,7 @@ object DBCourseManager {
while (it.moveToNext()) {
//写入文件
audio_cn_file_path = it.getBlobOrNull(0)?.let {
val audioFileNameCN =
"${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_CN}"
val audioFileNameCN = "${base.subjectId}_${base.coursePackId}_${base.courseId}_${wordId}_${AppConstants.SOUND_TYPE_CN}"
val file = File(FileUtil.getSaveDirPath(AppConfig.VOICE), audioFileNameCN)
FileUtil.writeBytesToFile(file, it)
file.path
@@ -434,25 +420,16 @@ object DBCourseManager {
open(dbcb)
//从lesson已学位置开始获取数据
val needLearnIds = lesson.wordIds.subList(lesson.learnedIndex + 1, lesson.wordIds.size)
val sql =
"SELECT * FROM chapter WHERE chapter_id = ${lesson.chapterId} and lesson_id = ${lesson.lessonId} AND word_id in (${
Joiner.on(",").join(needLearnIds)
}) " + "ORDER by word_sort ASC"
val sql = "SELECT * FROM chapter WHERE chapter_id = ${lesson.chapterId} and lesson_id = ${lesson.lessonId} AND word_id in (${
Joiner.on(",").join(needLearnIds)
}) " + "ORDER by word_sort ASC"
mDataBase?.rawQuery(sql, null)?.run {
while (moveToNext()) {
//单词id
val word_id = getLong(getColumnIndex("word_id"))
//学习单词实体
result.add(LearnWord(dbcb.subjectId,
dbcb.coursePackId,
dbcb.courseId,
dbcb.coursePackType,
dbcb.courseType,
lesson.chapterId,
lesson.lessonId,
word_id,
true,
lesson.lessonType).apply {
result.add(LearnWord(dbcb.subjectId, dbcb.coursePackId, dbcb.courseId, dbcb.coursePackType, dbcb.courseType,
lesson.chapterId, lesson.lessonId, word_id, true, lesson.lessonType).apply {
word = getString(getColumnIndex("word"))
basic_explanation = getString(getColumnIndex("basic_explaination"))
extend_explanation = getString(getColumnIndex("all_explaination"))
@@ -506,21 +483,13 @@ object DBCourseManager {
else -> wordIds.append(value).append(",")
}
}
val sql =
"SELECT * FROM knowledge WHERE chapter_id = ${lesson.chapterId} AND knowledge_id in ($wordIds) ORDER by CASE $sortSqlBuilder END"
val sql = "SELECT * FROM knowledge WHERE chapter_id = ${lesson.chapterId} AND knowledge_id in ($wordIds) ORDER by CASE $sortSqlBuilder END"
mDataBase?.rawQuery(sql, null)?.run {
while (moveToNext()) {
//学习单词实体
result.add(LearnWord(dbcb.subjectId,
dbcb.coursePackId,
dbcb.courseId,
dbcb.coursePackType,
dbcb.courseType,
lesson.chapterId,
lesson.lessonId,
getLong(getColumnIndex("knowledge_id")),
true,
result.add(LearnWord(dbcb.subjectId, dbcb.coursePackId, dbcb.courseId, dbcb.coursePackType, dbcb.courseType,
lesson.chapterId, lesson.lessonId, getLong(getColumnIndex("knowledge_id")), true,
lesson.lessonType).apply {
word = getString(getColumnIndex("title"))
basic_explanation = getString(getColumnIndex("explaination"))
@@ -558,10 +527,14 @@ object DBCourseManager {
* @return List<LearnWord>
*/
@SuppressLint("Range")
fun queryLearnWord(dbcb : DbControlBase, chapterId:Long, lessonId:Long, wordIds:String, isNeedOriginSort:Boolean = false):List<LearnWord>{
fun queryLearnWord(dbcb : DbControlBase,
chapterId : Long,
lessonId : Long,
wordIds : String,
isNeedOriginSort : Boolean = false) : List<LearnWord> {
val result = mutableListOf<LearnWord>()
open(dbcb)
val sql = when{
val sql = when {
!isNeedOriginSort -> "SELECT * FROM chapter WHERE chapter_id = $chapterId and lesson_id = $lessonId AND word_id in ($wordIds) ORDER by word_sort ASC"
else -> {
val sortSqlBuilder = StringBuilder() //排序value
@@ -574,15 +547,8 @@ object DBCourseManager {
mDataBase?.rawQuery(sql, null)?.run {
while (moveToNext()) {
//学习单词实体
result.add(LearnWord(dbcb.subjectId,
dbcb.coursePackId,
dbcb.courseId,
dbcb.coursePackType,
dbcb.courseType,
chapterId,
lessonId,
getLong(getColumnIndex("word_id")),
true,
result.add(LearnWord(dbcb.subjectId, dbcb.coursePackId, dbcb.courseId, dbcb.coursePackType, dbcb.courseType,
chapterId, lessonId, getLong(getColumnIndex("word_id")), true,
AppConstants.LESSON_TYPE_WORD).apply {
word = getString(getColumnIndex("word"))
basic_explanation = getString(getColumnIndex("basic_explaination"))
@@ -590,7 +556,7 @@ object DBCourseManager {
phrase = getString(getColumnIndex("phrase"))
example = getString(getColumnIndex("example"))
reference = getString(getColumnIndex("reference"))
when (dbcb.courseType) {
AppConstants.COURSE_TYPE_CHINESE_LITERACY -> {
literacyIspolyphone = getInt(getColumnIndex("polyphone")) > 0
@@ -619,23 +585,21 @@ object DBCourseManager {
fun queryCompositionReading(dbcb : DbControlBase, entity : Lesson) : List<CompositionReadingBean> {
val result = mutableListOf<CompositionReadingBean>()
val sql = "SELECT * FROM reading WHERE reading_id in (${Joiner.on(",").join(entity.wordIds)}) AND chapter_id = 5272 ORDER by CASE " + entity.wordIds.let {
val sql = "SELECT * FROM reading WHERE reading_id in (${
Joiner.on(",")
.join(entity.wordIds)
}) AND chapter_id = ${entity.chapterId} ORDER by CASE " + entity.wordIds.let {
val sortedCase = StringBuilder()
it.forEachIndexed{ index,id ->
it.forEachIndexed { index, id ->
sortedCase.append(" WHEN reading_id = $id THEN $index")
}
sortedCase
} + " END"
open(dbcb)
mDataBase?.rawQuery(sql,null)?.run {
while (moveToNext()){
result.add(CompositionReadingBean(
getLong(2),
getString(3),
getString(4),
getString(7),
getString(6)).apply {
collectId = 0
mDataBase?.rawQuery(sql, null)?.run {
while (moveToNext()) {
result.add(CompositionReadingBean(getLong(2), getString(3), getString(4), getString(7), getString(6)).apply {
collectId = 0
})
}
close()
@@ -650,10 +614,41 @@ object DBCourseManager {
* @param entity Lesson
* @return List<CompositionTaskBean>
*/
fun queryCompositonTask(dbcb : DbControlBase,entity : Lesson) : List<CompositionTaskBean>{
fun queryCompositionTask(dbcb : DbControlBase, entity : Lesson) : List<CompositionTaskBean> {
val result = mutableListOf<CompositionTaskBean>()
val sql = "SELECT * FROM task WHERE task_id in (${
Joiner.on(",")
.join(entity.wordIds)
}) AND chapter_id = ${entity.chapterId} ORDER by CASE " + entity.wordIds.let {
val sortedCase = StringBuilder()
it.forEachIndexed { index, id ->
sortedCase.append(" WHEN task_id = $id THEN $index")
}
sortedCase
} + " END"
open(dbcb)
mDataBase?.rawQuery(sql, null)?.run {
var position = 0
while (moveToNext()) {
result.add(CompositionTaskBean(getLong(2),
getLong(4),
getLong(3),
getString(6),
getString(7),
getString(8),
position))
position++
result.add(CompositionTaskBean(getLong(2),
getLong(4),
getLong(3),
getString(6),
getString(7),
getString(8),
position))
position++
}
close()
}
return result
}

+ 0
- 1
app/src/main/java/com/xkl/cdl/data/repository/DataRepository.kt View File

@@ -1,6 +1,5 @@
package com.xkl.cdl.data.repository

import androidx.lifecycle.MutableLiveData
import com.suliang.common.util.file.FileUtil
import com.xkl.cdl.data.bean.course.CourseDetail
import com.xkl.cdl.data.bean.course.Lesson

+ 94
- 1
app/src/main/java/com/xkl/cdl/module/learn/LearnCTaskActivity.kt View File

@@ -1,9 +1,28 @@
package com.xkl.cdl.module.learn

import android.media.Image
import android.os.Bundle
import android.text.TextUtils
import android.widget.ImageView
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.ImageViewerPopupView
import com.lxj.xpopup.interfaces.OnSrcViewUpdateListener
import com.lxj.xpopup.util.SmartGlideImageLoader
import com.suliang.common.base.activity.BaseActivityVM
import com.suliang.common.extension.click
import com.xkl.cdl.R
import com.xkl.cdl.adapter.AdapterBottomDialogSwitch
import com.xkl.cdl.adapter.AdapterImageTask
import com.xkl.cdl.data.bean.CompositionReadingBean
import com.xkl.cdl.data.bean.CompositionTaskBean
import com.xkl.cdl.data.manager.FilePathManager
import com.xkl.cdl.databinding.ActivityLearnCtaskBinding
import com.xkl.cdl.databinding.DialogBottomAutoPlaySelectBinding

/**
* author suliang
@@ -17,11 +36,85 @@ class LearnCTaskActivity : BaseActivityVM<ActivityLearnCtaskBinding,LearnCTaskVi
}
override fun initActivity(savedInstanceState : Bundle?) {
binding.titleBar.textViewTitle.run {
ellipsize = TextUtils.TruncateAt.MIDDLE
text = vm.lesson.lessonName
}
binding.titleBar.onBackClick = {
finish()
}
binding.titleBar.onRightClick = {
showChangeTaskDialog()
}
//初始化图片显示recyclerView
binding.recyclerView.apply {
layoutManager = StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL)
adapter = AdapterImageTask(vm).apply {
onItemClick = { v, position, item ->
XPopup.Builder(this@LearnCTaskActivity)
.asImageViewer(v as ImageView, position,
(binding.recyclerView.adapter as AdapterImageTask).getData() as List<*>, object : OnSrcViewUpdateListener{
override fun onSrcViewUpdate(popupView : ImageViewerPopupView, position : Int) {
popupView.updateSrcView(binding.recyclerView.getChildAt(position) as ImageView)
}
}, SmartGlideImageLoader())
.show()
}
}
}
}
override fun loadData() {
vm.queryData()
//当前练习
vm.currentTask.observe(this){
binding.run {
topicValue.text = it.title
requireValue.text = it.introduce
sourceValue.text = "学考乐"
}
it.photo?.run {
val fileList = split(",").map {
FilePathManager.getPngFile(vm.lesson.subjectId,vm.lesson.coursePackId,vm.lesson.courseId,it.substringAfterLast ("/"))
}.toMutableList()
(binding.recyclerView.adapter as AdapterImageTask).setData(fileList)
}
}
}
private var changeTaskDialog: BottomSheetDialog? = null
/** 切换item的dialog */
private fun showChangeTaskDialog() {
if (!vm.isCanSwitch) return
if (changeTaskDialog == null) {
changeTaskDialog = BottomSheetDialog(this, R.style.dialog_style).apply {
val autoPlayBinding = DataBindingUtil.inflate<DialogBottomAutoPlaySelectBinding>(layoutInflater,
R.layout.dialog_bottom_auto_play_select,
null, false)
setContentView(autoPlayBinding.root)
autoPlayBinding.tvTitle.text = "请选择课外练习查看详情"
autoPlayBinding.ivCancel.click { v -> dismiss() }
autoPlayBinding.rvRepeat.run {
layoutManager = LinearLayoutManager(this@LearnCTaskActivity, LinearLayoutManager.VERTICAL, false)
adapter = AdapterBottomDialogSwitch<CompositionTaskBean>().apply {
onItemClick = { _, position, _ ->
dismiss()
vm.currentTask.value = vm.mTaskList[position]
}
setData(vm.mTaskList.toMutableList())
}
}
//显示时,定位到当前item的位置
setOnShowListener{
(autoPlayBinding.rvRepeat.adapter as AdapterBottomDialogSwitch<*>).selectItemIndex = vm.currentTask.value!!.position
autoPlayBinding.rvRepeat.scrollToPosition( vm.currentTask.value!!.position)
}
}
}
changeTaskDialog?.show()
}


+ 32
- 1
app/src/main/java/com/xkl/cdl/module/learn/LearnCTaskViewModel.kt View File

@@ -1,15 +1,46 @@
package com.xkl.cdl.module.learn

import androidx.lifecycle.MutableLiveData
import com.suliang.common.base.activity.ToastEvent
import com.suliang.common.base.viewmodel.BaseViewModel
import com.suliang.common.extension.diskIo2Main
import com.xkl.cdl.data.DataTransferHolder
import com.xkl.cdl.data.bean.CompositionTaskBean
import com.xkl.cdl.data.bean.course.Lesson
import com.xkl.cdl.data.manager.db.DBCourseManager
import com.xkl.cdl.data.manager.db.DbControlBase
import io.reactivex.rxjava3.core.Observable

class LearnCTaskViewModel : BaseViewModel() {
val lesson = DataTransferHolder.instance.getData<Lesson>()
val dbControlBase = DbControlBase(lesson.subjectId, lesson.coursePackId, lesson.coursePackType, lesson.courseId,
lesson.courseType)
fun queryData(){
//是否有切换的练习
var isCanSwitch = false
//数据列表
lateinit var mTaskList : List<CompositionTaskBean>
//当前显示task
val currentTask = MutableLiveData<CompositionTaskBean>()
/**
* 查询数据
*/
fun queryData() {
Observable.create<List<CompositionTaskBean>> {
it.onNext(DBCourseManager.queryCompositionTask(dbControlBase, lesson))
it.onComplete()
}.compose(diskIo2Main()).subscribe({
isCanSwitch = it.size > 1
mTaskList = it
currentTask.value = mTaskList[0]
}, {
it.printStackTrace()
showToast(ToastEvent(content = "课外练习数据获取异常,请联系管理人员进行处理"))
})
}
}

+ 14
- 0
app/src/main/res/layout/item_task_image.xml View File

@@ -0,0 +1,14 @@
<?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>

<com.google.android.material.imageview.ShapeableImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
app:shapeAppearance="@style/roundedCornerStyle" />
</layout>

+ 5
- 1
build.gradle View File

@@ -100,7 +100,11 @@ ext {
grpc_protobuf: "io.grpc:grpc-protobuf:1.27.0",
grpc_stub: "io.grpc:grpc-stub:1.27.0",
//liveEventBus https://github.com/JeremyLiao/LiveEventBus
liveEventBus : "io.github.jeremyliao:live-event-bus-x:1.8.0"
liveEventBus : "io.github.jeremyliao:live-event-bus-x:1.8.0",
//BigImageViewPager
// BigImageViewPager : "com.github.SherlockGougou:BigImageViewPager:androidx-7.0.0",
//XPopup https://github.com/li-xiaojun/XPopup
XPopup : "com.github.li-xiaojun:XPopup:2.8.0"
]



+ 10
- 0
lib/common/src/main/java/com/suliang/common/util/image/MyGlideApp.kt View File

@@ -16,6 +16,9 @@ import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.module.LibraryGlideModule
import com.bumptech.glide.request.RequestOptions
import com.suliang.common.util.file.FileUtil
import com.bumptech.glide.load.model.GlideUrl
import java.io.InputStream


/**
* author suliang
@@ -66,5 +69,12 @@ class MyGlideApp : AppGlideModule() {
// setDefaultRequestOptions(apply)
}
}
override fun registerComponents(context : Context, glide : Glide, registry : Registry) {
super.registerComponents(context, glide, registry)
// 替换底层网络框架为okhttp3,这步很重要!如果不添加会无法正常显示原图的加载百分比,或者卡在1%
// 如果你的app中已经存在了自定义的GlideModule,你只需要把这一行代码,添加到对应的重载方法中即可。
// registry.replace(GlideUrl::class.java, InputStream::class.java, Factory(ProgressManager.getOkHttpClient()))
}

}

Loading…
Cancel
Save