Browse Source

task

master
suliang 2 years ago
parent
commit
997d39dec6

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

<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_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_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_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_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/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" /> <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

implementation customDependencies.grpc_android implementation customDependencies.grpc_android
implementation customDependencies.grpc_protobuf implementation customDependencies.grpc_protobuf
implementation customDependencies.grpc_stub 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

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

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

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

package com.xkl.cdl.data.manager package com.xkl.cdl.data.manager


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


/** /**
* author suliang * author suliang
/*** /***
* 检查课程包下课程的db数据文件是否存在,不存在,则复制过去 * 检查课程包下课程的db数据文件是否存在,不存在,则复制过去
* 作文是.zip结尾的文件,需要解压,将文件放入对应的目录
*/ */
fun checkCourseDb() { fun checkCourseDb() {
subjectWithCoursePackMap.forEach { entry -> subjectWithCoursePackMap.forEach { entry ->
entry.value.forEach { coursePack -> entry.value.forEach { coursePack ->
coursePack.childrenCourses.forEach { 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

*/ */
@JvmStatic @JvmStatic
fun getCoursePackDbPath(): File{ fun getCoursePackDbPath(): File{
return File(FileUtil.getSaveDirPath("db"), "course-pack.db")
return File(getDbRootPath(), "course-pack.db")
} }
/** 获取课程数据地址 */ /** 获取课程数据地址 */
@JvmStatic @JvmStatic
fun getCourseDbPath(base:DbControlBase): File{ 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 @JvmStatic
fun getCourseDbPath(subjectId:Int,coursePackId:Long,courseId:Long): File{ 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

val p = when (base.courseType) { val p = when (base.courseType) {
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> COMPOSITION AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> COMPOSITION
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> SPOKEN 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 else -> NORMAL
} }
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getCourseDbPath(currentBase).path,
p,
null,
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getCourseDbPath(currentBase).path, p, null,
SQLiteDatabase.OPEN_READONLY) SQLiteDatabase.OPEN_READONLY)
} }
if (mDataBase == null) { if (mDataBase == null) {
val lessonId = it.getLong(it.getColumnIndex("lesson_id")) val lessonId = it.getLong(it.getColumnIndex("lesson_id"))
val lessonName : String = when (base.courseType) { val lessonName : String = when (base.courseType) {
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION, AppConstants.COURSE_TYPE_CHINESE_LITERACY, AppConstants.COURSE_TYPE_CHINESE_PINYIN -> it.getString( 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")) else -> it.getString(it.getColumnIndex("lesson"))
} }
val wordIds : MutableList<Long> = when (base.courseType) { val wordIds : MutableList<Long> = when (base.courseType) {
// 注:针对口语对话课时,如果没有学习完,是不会设置进度点的。 todo 分课程类型设置进度点 // 注:针对口语对话课时,如果没有学习完,是不会设置进度点的。 todo 分课程类型设置进度点
val learnIsOver = wordIds.size - 1 == learnIndex 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 lessonPositionInList = positionIndex
this.wordIds = wordIds //内容 this.wordIds = wordIds //内容
totalNumber = this.wordIds.size //总数 totalNumber = this.wordIds.size //总数
mutableList.add(lesson) mutableList.add(lesson)
positionIndex += 1 positionIndex += 1
// TODO: 2022/5/9 对课时数量进行限制,课时太多,开发人员不好进行测试 // TODO: 2022/5/9 对课时数量进行限制,课时太多,开发人员不好进行测试
val needBreak = when(base.coursePackType){
val needBreak = when (base.coursePackType) {
AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION -> positionIndex == 11 //保留十个课时 AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION -> positionIndex == 11 //保留十个课时
AppConstants.COURSEPACK_TYPE_ENGLISH_SPOKEN -> positionIndex == 7 //保留六个课时 AppConstants.COURSEPACK_TYPE_ENGLISH_SPOKEN -> positionIndex == 7 //保留六个课时
else -> positionIndex == 3 //保留三个课时 else -> positionIndex == 3 //保留三个课时
} }
if (needBreak){
if (needBreak) {
break break
} }
} }
} }
val sql = when (base.courseType) { 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_DISCERN, AppConstants.COURSE_TYPE_ENGLISH_VOICE,
AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK, AppConstants.COURSE_TYPE_CHINESE_LITERACY, AppConstants.COURSE_TYPE_ENGLISH_SOUNDMARK, AppConstants.COURSE_TYPE_CHINESE_LITERACY,
mDataBase?.rawQuery(sql, null)?.run { mDataBase?.rawQuery(sql, null)?.run {
when (base.courseType) { when (base.courseType) {
//作文知识点测试 //作文知识点测试
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> while (moveToNext()) {
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> while (moveToNext()) {
result.add(ExamBean().apply { result.add(ExamBean().apply {
id = getLong(3) id = getLong(3)
word_id = getLong(2) word_id = getLong(2)
}) })
} }
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 { result.add(ExamBean().apply {
id = getLong(0) id = getLong(0)
word_id = getLong(1) word_id = getLong(1)
//不为空,写入本身,如果为空,用另外的发音方式写入 //不为空,写入本身,如果为空,用另外的发音方式写入
val parentPath = FileUtil.getSaveDirPath(AppConfig.VOICE) val parentPath = FileUtil.getSaveDirPath(AppConfig.VOICE)
val audio_us_file_path = audio_us?.let { 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) val file = File(parentPath, audioFileNameUS)
FileUtil.writeBytesToFile(file, it) FileUtil.writeBytesToFile(file, it)
file.path file.path
} ?: audio_uk?.let { } ?: 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) val file = File(parentPath, audioFileNameUS)
FileUtil.writeBytesToFile(file, it) FileUtil.writeBytesToFile(file, it)
file.path file.path
} }
//不为空,写入本身,如果为空,用另外的发音方式写入 //不为空,写入本身,如果为空,用另外的发音方式写入
val audio_uk_file_path = audio_uk?.let { 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) val file = File(parentPath, audioFileNameUk)
FileUtil.writeBytesToFile(file, it) FileUtil.writeBytesToFile(file, it)
file.path file.path
} ?: audio_us?.let { } ?: 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) val file = File(parentPath, audioFileNameUk)
FileUtil.writeBytesToFile(file, it) FileUtil.writeBytesToFile(file, it)
file.path file.path
while (it.moveToNext()) { while (it.moveToNext()) {
//写入文件 //写入文件
audio_cn_file_path = it.getBlobOrNull(0)?.let { 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) val file = File(FileUtil.getSaveDirPath(AppConfig.VOICE), audioFileNameCN)
FileUtil.writeBytesToFile(file, it) FileUtil.writeBytesToFile(file, it)
file.path file.path
open(dbcb) open(dbcb)
//从lesson已学位置开始获取数据 //从lesson已学位置开始获取数据
val needLearnIds = lesson.wordIds.subList(lesson.learnedIndex + 1, lesson.wordIds.size) 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 { mDataBase?.rawQuery(sql, null)?.run {
while (moveToNext()) { while (moveToNext()) {
//单词id //单词id
val word_id = getLong(getColumnIndex("word_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")) word = getString(getColumnIndex("word"))
basic_explanation = getString(getColumnIndex("basic_explaination")) basic_explanation = getString(getColumnIndex("basic_explaination"))
extend_explanation = getString(getColumnIndex("all_explaination")) extend_explanation = getString(getColumnIndex("all_explaination"))
else -> wordIds.append(value).append(",") 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 { mDataBase?.rawQuery(sql, null)?.run {
while (moveToNext()) { 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 { lesson.lessonType).apply {
word = getString(getColumnIndex("title")) word = getString(getColumnIndex("title"))
basic_explanation = getString(getColumnIndex("explaination")) basic_explanation = getString(getColumnIndex("explaination"))
* @return List<LearnWord> * @return List<LearnWord>
*/ */
@SuppressLint("Range") @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>() val result = mutableListOf<LearnWord>()
open(dbcb) 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" !isNeedOriginSort -> "SELECT * FROM chapter WHERE chapter_id = $chapterId and lesson_id = $lessonId AND word_id in ($wordIds) ORDER by word_sort ASC"
else -> { else -> {
val sortSqlBuilder = StringBuilder() //排序value val sortSqlBuilder = StringBuilder() //排序value
mDataBase?.rawQuery(sql, null)?.run { mDataBase?.rawQuery(sql, null)?.run {
while (moveToNext()) { 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 { AppConstants.LESSON_TYPE_WORD).apply {
word = getString(getColumnIndex("word")) word = getString(getColumnIndex("word"))
basic_explanation = getString(getColumnIndex("basic_explaination")) basic_explanation = getString(getColumnIndex("basic_explaination"))
phrase = getString(getColumnIndex("phrase")) phrase = getString(getColumnIndex("phrase"))
example = getString(getColumnIndex("example")) example = getString(getColumnIndex("example"))
reference = getString(getColumnIndex("reference")) reference = getString(getColumnIndex("reference"))
when (dbcb.courseType) { when (dbcb.courseType) {
AppConstants.COURSE_TYPE_CHINESE_LITERACY -> { AppConstants.COURSE_TYPE_CHINESE_LITERACY -> {
literacyIspolyphone = getInt(getColumnIndex("polyphone")) > 0 literacyIspolyphone = getInt(getColumnIndex("polyphone")) > 0
fun queryCompositionReading(dbcb : DbControlBase, entity : Lesson) : List<CompositionReadingBean> { fun queryCompositionReading(dbcb : DbControlBase, entity : Lesson) : List<CompositionReadingBean> {
val result = mutableListOf<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() val sortedCase = StringBuilder()
it.forEachIndexed{ index,id ->
it.forEachIndexed { index, id ->
sortedCase.append(" WHEN reading_id = $id THEN $index") sortedCase.append(" WHEN reading_id = $id THEN $index")
} }
sortedCase sortedCase
} + " END" } + " END"
open(dbcb) 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() close()
* @param entity Lesson * @param entity Lesson
* @return List<CompositionTaskBean> * @return List<CompositionTaskBean>
*/ */
fun queryCompositonTask(dbcb : DbControlBase,entity : Lesson) : List<CompositionTaskBean>{
fun queryCompositionTask(dbcb : DbControlBase, entity : Lesson) : List<CompositionTaskBean> {
val result = mutableListOf<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 return result
} }

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

package com.xkl.cdl.data.repository package com.xkl.cdl.data.repository


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

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

package com.xkl.cdl.module.learn package com.xkl.cdl.module.learn


import android.media.Image
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils
import android.widget.ImageView
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider 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.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.ActivityLearnCtaskBinding
import com.xkl.cdl.databinding.DialogBottomAutoPlaySelectBinding


/** /**
* author suliang * author suliang
} }
override fun initActivity(savedInstanceState : Bundle?) { 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() { 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

package com.xkl.cdl.module.learn 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.base.viewmodel.BaseViewModel
import com.suliang.common.extension.diskIo2Main
import com.xkl.cdl.data.DataTransferHolder 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.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() { class LearnCTaskViewModel : BaseViewModel() {
val lesson = DataTransferHolder.instance.getData<Lesson>() 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

<?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

grpc_protobuf: "io.grpc:grpc-protobuf:1.27.0", grpc_protobuf: "io.grpc:grpc-protobuf:1.27.0",
grpc_stub: "io.grpc:grpc-stub:1.27.0", grpc_stub: "io.grpc:grpc-stub:1.27.0",
//liveEventBus https://github.com/JeremyLiao/LiveEventBus //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

import com.bumptech.glide.module.LibraryGlideModule import com.bumptech.glide.module.LibraryGlideModule
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.suliang.common.util.file.FileUtil import com.suliang.common.util.file.FileUtil
import com.bumptech.glide.load.model.GlideUrl
import java.io.InputStream



/** /**
* author suliang * author suliang
// setDefaultRequestOptions(apply) // 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