diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 95f13f0..341a847 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -64,7 +64,7 @@ android:resizeableActivity="true" android:roundIcon="@mipmap/ic_launcher_icon" android:supportsRtl="true" - android:theme="@style/Theme.Material" + android:theme="@style/Theme.Base" android:usesCleartextTraffic="true" tools:replace="android:allowBackup,android:supportsRtl"> diff --git a/app/src/main/assets/fonts/Alimama ShuHeiTi.ttf b/app/src/main/assets/fonts/AlimamaShuHeiTi.ttf similarity index 100% rename from app/src/main/assets/fonts/Alimama ShuHeiTi.ttf rename to app/src/main/assets/fonts/AlimamaShuHeiTi.ttf diff --git a/app/src/main/assets/fonts/YouSheBiaoTiHei.ttf b/app/src/main/assets/fonts/YouSheBiaoTiHei.ttf deleted file mode 100644 index 3729151..0000000 Binary files a/app/src/main/assets/fonts/YouSheBiaoTiHei.ttf and /dev/null differ diff --git a/app/src/main/java/com/cheng/bole/bean/CityBean.kt b/app/src/main/java/com/cheng/bole/bean/AreaBean.kt similarity index 67% rename from app/src/main/java/com/cheng/bole/bean/CityBean.kt rename to app/src/main/java/com/cheng/bole/bean/AreaBean.kt index f0e5af3..754437e 100644 --- a/app/src/main/java/com/cheng/bole/bean/CityBean.kt +++ b/app/src/main/java/com/cheng/bole/bean/AreaBean.kt @@ -2,11 +2,11 @@ package com.cheng.bole.bean import java.io.Serializable -class CityBean( +class AreaBean( val id: Int = 0, val pid: Int = 0, val name: String = "", val amount: String = "", - var children: MutableList = mutableListOf(), + var children: MutableList = mutableListOf(), var isChecked: Boolean = false ) : Serializable \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/bean/BidItemBean.kt b/app/src/main/java/com/cheng/bole/bean/BidItemBean.kt index d3a6e12..38a63a8 100644 --- a/app/src/main/java/com/cheng/bole/bean/BidItemBean.kt +++ b/app/src/main/java/com/cheng/bole/bean/BidItemBean.kt @@ -13,32 +13,4 @@ data class BidItemBean( val money: String, val tipsTime: String, val star: String -) { - fun getShortName(): String { - return when (typeName) { - "招标计划" -> "招标" - "采购公告" -> "采购" - "招标公告" -> "预告" - "合同公告" -> "合同" - "中标公告" -> "中标" - "竞争性磋商" -> "竞争性磋商" - "更正公告" -> "更正" - "终止公告" -> "终止" - else -> "其他" - } - } - - fun getTypeColor(): Int { - return when (typeName) { - "招标计划" -> Color.parseColor("#2B88F9") - "采购公告" -> Color.parseColor("#FF7344") - "招标公告" -> Color.parseColor("#14CEB3") - "合同公告" -> Color.parseColor("#FFA91D") - "中标公告" -> Color.parseColor("#FF1B1B") - "竞争性磋商" -> Color.parseColor("#0DA9FF") - "更正公告" -> Color.parseColor("#7066FF") - "终止公告" -> Color.parseColor("#8C9199") - else -> Color.parseColor("#EEEEEE") - } - } -} \ No newline at end of file +) \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/bean/SearchOptionBean.kt b/app/src/main/java/com/cheng/bole/bean/SearchOptionBean.kt new file mode 100644 index 0000000..645746f --- /dev/null +++ b/app/src/main/java/com/cheng/bole/bean/SearchOptionBean.kt @@ -0,0 +1,70 @@ +package com.cheng.bole.bean + +import com.cheng.bole.manager.UserConfigManager +import java.io.Serializable + +class SearchOptionBean( + val title: String, + val items: List, + var isChecked: Boolean = false +) : Serializable { + class OptionItem( + val id: Int = 0, + val name: String = "", + var isChecked: Boolean = false, + + var startTime: String = "", + var endTime: String = "" + ) : Serializable + + companion object { + fun getAreaOptionList(): List { + val areaList = UserConfigManager.getAreaList() + val list = mutableListOf() + list.add(SearchOptionBean("全国地区", listOf( + OptionItem(0, "全国", true) + ))) + areaList.forEach { area -> + val cityList = mutableListOf() + cityList.add(OptionItem(0, "全部")) + area.children.forEach { city -> + cityList.add(OptionItem(city.id, city.name)) + } + list.add(SearchOptionBean(area.name, cityList)) + } + return list + } + + fun getTimeOptionList(): List { + val list = mutableListOf() + list.add(SearchOptionBean("时间排序", listOf( + OptionItem(0, "全部时间", true), + OptionItem(1, "近三天"), + OptionItem(2, "近七天"), + OptionItem(3, "近一个月"), + OptionItem(4, "近三个月"), + OptionItem(5, "近一年") + ))) + return list + } + + fun getSortOptionList(): List { + val list = mutableListOf() + list.add(SearchOptionBean("排序方式", listOf( + OptionItem(0, "综合排序", true), + OptionItem(1, "时间排序") + ))) + return list + } + + fun getTypeOptionList(): List { + val list = mutableListOf() + val typeList = mutableListOf() + UserConfigManager.getBidTypes().forEach { + typeList.add(OptionItem(it.id.toInt(), it.name)) + } + list.add(SearchOptionBean("信息类型", typeList)) + return list + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/bean/WxShareEntity.kt b/app/src/main/java/com/cheng/bole/bean/WxShareEntity.kt index f5bb3d9..1be7595 100644 --- a/app/src/main/java/com/cheng/bole/bean/WxShareEntity.kt +++ b/app/src/main/java/com/cheng/bole/bean/WxShareEntity.kt @@ -3,8 +3,8 @@ package com.cheng.bole.bean import java.io.Serializable data class WxShareEntity( - val content: String = "", - val image: String = "", - val link: String = "", - val title: String = "" + var content: String = "", + var image: String = "", + var link: String = "", + var title: String = "" ) : Serializable \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/common/Constants.kt b/app/src/main/java/com/cheng/bole/common/Constants.kt index 44a5b74..206b580 100644 --- a/app/src/main/java/com/cheng/bole/common/Constants.kt +++ b/app/src/main/java/com/cheng/bole/common/Constants.kt @@ -27,9 +27,8 @@ object Constants { const val Encrypt = "zpzkfp72v3hgatzg5w7pyg86x5342kxt" const val Signature = "ckBHUSWBx3TqwNT2kxMrsXyXFuA3PW" - val almmsht = Typeface.createFromAsset(Utils.getApp().assets, "fonts/Alimama ShuHeiTi.ttf") + val almmsht = Typeface.createFromAsset(Utils.getApp().assets, "fonts/AlimamaShuHeiTi.ttf") val dDIN_PRO_M = Typeface.createFromAsset(Utils.getApp().assets, "fonts/D-DIN-PRO-500-Medium.otf") - val youSheBiaoTiHei = Typeface.createFromAsset(Utils.getApp().assets, "fonts/YouSheBiaoTiHei.ttf") val douyinsansB = Typeface.createFromAsset(Utils.getApp().assets, "fonts/DouyinSansBold.otf") val pmzdbt = Typeface.createFromAsset(Utils.getApp().assets, "fonts/PangMenZhengDaoBiaoTiTi.ttf") } \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/common/EventConstants.kt b/app/src/main/java/com/cheng/bole/common/EventConstants.kt index 270bc86..67d095f 100644 --- a/app/src/main/java/com/cheng/bole/common/EventConstants.kt +++ b/app/src/main/java/com/cheng/bole/common/EventConstants.kt @@ -29,56 +29,19 @@ object EventConstants { const val ERROR_CLIENT_ALIPAY_ERR = "client.alipay.err" //支付宝支付失败 - const val ERROR_CLIENT_DOWNLOAD_IMG = "client.download.img.err" //图片下载失败 - - const val ERROR_CLIENT_DOWNLOAD_VIDEO = "client.download.video.err" //视频下载失败 - - const val ERROR_CLIENT_DOWNLOAD_AUDIO = "client.download.audio.err" //音频下载失败 - - const val CANCEL_DOWNLOAD_VIDEO = "client.download.video.cancel" //取消视频下载 - - const val PAUSE_DOWNLOAD_VIDEO = "client.download.video.pause" //暂停视频下载 - - const val CONTINUE_DOWNLOAD_VIDEO = "client.download.video.continue" //继续视频下载 - - const val RESTART_DOWNLOAD_VIDEO = "client.download.video.restart" //重新视频下载 - - const val SPEED_UP_DOWNLOAD_VIDEO = "client.download.video.speed.up" //加速视频下载 - - const val BACKGROUND_CLIENT_DOWNLOAD = "client.download.background" //后台下载 - - const val FLOAT_WINDOW_CLICK = "client.float.window.click" //点击悬浮窗 - - const val SAVE_AI_MEDIA = "client.ai.media.save" //ai生成文件保存 - - const val RECOGNIZE_AUDIO_TO_TEXT = "client.audio.text.recognize" //音频转文字 const val PKG_UPDATE = "client.pkg.update" //升级弹窗点击更新 const val PKG_CANCEL = "client.pkg.cancel" //升级弹窗点击取消 - const val GET_MATERIAL = "client.get.material" //获取素材 + const val JUMP_TO_BID_DETAIL = "client.jump.to.bid.detail" //跳转到标讯详情页 - const val GET_MATERIAL_CANCEL = "client.get.material.cancel" //取消获取素材 - - const val DIALOG_CONFIRM_SAVE_FILE = "client.dialog.confirm.save.file" //保存文件地址弹框确认 + const val JUMP_TO_BID_SEARCH = "client.jump.to.bid.search" //跳转到搜索 const val DIALOG_GO_TO_VIEW = "client.dialog.go.to.view" //前往保存文件的地址查看 const val JUMP_TO_ABOUT_US = "client.jump.to.about.us" //界面跳转 - const val JUMP_TO_LINK_EXTRACT = "client.jump.to.link.extract" //跳转链接提取 - - const val JUMP_TO_WECHAT_VIDEO = "client.jump.to.wechat.video" //跳转视频号 - - const val JUMP_TO_WECHAT_PLAYBACK = "client.jump.to.wechat.video.playback" //跳转直播回放 - - const val JUMP_TO_COURSE_WX_VIDEO = "client.course.wechat.video" //视频号视频教程 - - const val JUMP_TO_COURSE_PLAYBACK = "client.course.playback" //直播回放视频教程 - - const val JUMP_TO_TOOL = "client.jump.to.home.tool" //跳转工具 - const val MAIN_CENTER_ENABLE = "client.main.center.enable" //首页跳转个人中心 const val JUMP_TO_MEMBER_RECHARGE = "client.jump.to.member.recharge" //跳转到充值页 @@ -95,21 +58,13 @@ object EventConstants { const val JUMP_TO_ACCOUNT_MANAGE = "client.jump.to.account.manage" //跳转到账号管理 - const val JUMP_TO_DOWNLOAD_HISTORY = "client.jump.to.download.history" //跳转到下载记录 - - const val JUMP_TO_DOWNLOAD_TASK_LIST = "client.jump.to.download.task.list" //跳转到下载任务列表 - const val JUMP_TO_RECHARGE_DIAMOND = "client.jump.to.recharge.diamond" //跳转到M币充值 const val JUMP_TO_COUPON_LIST = "client.jump.to.coupon.list" //跳转优惠券列表 const val JUMP_TO_CHALLENGE_TASK = "client.jump.to.challenge.task" //跳转到0元挑战 - const val JUMP_TO_SHARE_WX_VIDEO = "client.jump.to.wechat.share.video" //跳转到视频号分享 - const val JUMP_TO_SHARE_WX_PLAYBACK = "client.jump.to.wechat.share.playback" //跳转到直播回放分享 - - const val JUMP_TO_COURSE = "client.jump.to.course" //跳转到指导教程 const val DOWNLOAD_FILE = "client.download.file" //下载文件 diff --git a/app/src/main/java/com/cheng/bole/event/FavoriteEvent.kt b/app/src/main/java/com/cheng/bole/event/FavoriteEvent.kt new file mode 100644 index 0000000..f50cce3 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/event/FavoriteEvent.kt @@ -0,0 +1,4 @@ +package com.cheng.bole.event + +class FavoriteEvent { +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/manager/EventReportManager.kt b/app/src/main/java/com/cheng/bole/manager/EventReportManager.kt index e0de4c3..3c52d36 100644 --- a/app/src/main/java/com/cheng/bole/manager/EventReportManager.kt +++ b/app/src/main/java/com/cheng/bole/manager/EventReportManager.kt @@ -10,7 +10,7 @@ import okhttp3.RequestBody.Companion.toRequestBody object EventReportManager { - fun eventReport(key: String?, value: String?, extra: String) { + fun eventReport(key: String?, value: String? = "", extra: String = "") { GlobalScope.launch { try { val jsonObject = JSONObject() diff --git a/app/src/main/java/com/cheng/bole/manager/SearchHistoryManager.kt b/app/src/main/java/com/cheng/bole/manager/SearchHistoryManager.kt new file mode 100644 index 0000000..9ecf774 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/manager/SearchHistoryManager.kt @@ -0,0 +1,44 @@ +package com.cheng.bole.manager + +import android.text.TextUtils +import com.example.base.utils.MMKVUtils +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken + +/** + * 搜索历史 + */ +object SearchHistoryManager { + + fun addHistory(keyword: String): List { + val list = getHistory() + if (!list.contains(keyword)) { + if (list.size == 20) list.removeLast() + list.add(0, keyword) + MMKVUtils.put("search_history", Gson().toJson(list)) + } + return list + } + + fun updateHistory(keyword: String): List { + val list = getHistory() + if (list.contains(keyword)) { + list.remove(keyword) + } + list.add(0, keyword) + MMKVUtils.put("search_history", Gson().toJson(list)) + return list + } + + fun getHistory(): MutableList { + val str = MMKVUtils.getString("search_history") + if (!TextUtils.isEmpty(str)) { + return Gson().fromJson(str, object : TypeToken>() {}.type) + } + return mutableListOf() + } + + fun clear() { + MMKVUtils.removeKey("search_history") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/manager/UserConfigManager.kt b/app/src/main/java/com/cheng/bole/manager/UserConfigManager.kt index 874e373..a732bcb 100644 --- a/app/src/main/java/com/cheng/bole/manager/UserConfigManager.kt +++ b/app/src/main/java/com/cheng/bole/manager/UserConfigManager.kt @@ -3,6 +3,8 @@ package com.cheng.bole.manager import android.os.Build import android.text.TextUtils import androidx.lifecycle.MutableLiveData +import com.cheng.bole.bean.BidTypeBean +import com.cheng.bole.bean.AreaBean import com.cheng.bole.net.ApiFactory import com.example.base.extensions.toast import com.example.base.utils.MMKVUtils @@ -210,6 +212,60 @@ object UserConfigManager { return emptyList() } + /** + * 搜索排序 + */ + private fun saveSearchSort(sort: String) { + MMKVUtils.put("search_sort", sort) + } + + fun getSearchSort(): String { + return MMKVUtils.getString("search_sort") ?: "" + } + + /** + * 地区列表 + */ + fun saveAreaList(list: List) { + if (list.isNotEmpty()) { + MMKVUtils.put("area_list", Gson().toJson(list)) + } + } + + fun getAreaList(): MutableList { + val str = MMKVUtils.getString("area_list") + if (!TextUtils.isEmpty(str)) { + return Gson().fromJson(str, object : TypeToken>() {}.type) + } + return mutableListOf() + } + + /** + * 城市列表 + */ + fun getCityList(): List { + val list = mutableListOf() + getAreaList().forEach { + list.addAll(it.children) + } + return list + } + + /** + * 招标类型 + */ + fun saveBidTypes(list: List) { + MMKVUtils.put("bid_type", Gson().toJson(list)) + } + + fun getBidTypes(): List { + val str = MMKVUtils.getString("bid_type") + if (!TextUtils.isEmpty(str)) { + return Gson().fromJson(str, object : TypeToken>() {}.type) + } + return emptyList() + } + /** * 保存个推cid */ diff --git a/app/src/main/java/com/cheng/bole/net/ApiService.kt b/app/src/main/java/com/cheng/bole/net/ApiService.kt index e7bc689..5da1b00 100644 --- a/app/src/main/java/com/cheng/bole/net/ApiService.kt +++ b/app/src/main/java/com/cheng/bole/net/ApiService.kt @@ -3,7 +3,7 @@ package com.cheng.bole.net import com.cheng.bole.bean.BidDetailBean import com.cheng.bole.bean.BidItemBean import com.cheng.bole.bean.BidTypeBean -import com.cheng.bole.bean.CityBean +import com.cheng.bole.bean.AreaBean import com.cheng.bole.bean.CompanyBean import com.cheng.bole.bean.CorpInfoBean import com.cheng.bole.bean.GuideTotalBidInfoBean @@ -182,13 +182,13 @@ interface ApiService { * 城市列表 */ @GET("/api/city") - suspend fun getCityList(): HttpBaseResult> + suspend fun getAreaList(): HttpBaseResult> /** * 获取当前城市 */ @GET("/api/city/default") - suspend fun getUserCity(): HttpBaseResult + suspend fun getUserCity(): HttpBaseResult /** * 总计商机 diff --git a/app/src/main/java/com/cheng/bole/ui/dialog/AccountListDialog.kt b/app/src/main/java/com/cheng/bole/ui/dialog/AccountListDialog.kt index ba4b3f9..7a75391 100644 --- a/app/src/main/java/com/cheng/bole/ui/dialog/AccountListDialog.kt +++ b/app/src/main/java/com/cheng/bole/ui/dialog/AccountListDialog.kt @@ -50,7 +50,7 @@ class AccountListDialog : DialogFragment() { binding = DialogAccountListBinding.bind(view) - binding.tvTitle.typeface = Constants.youSheBiaoTiHei + binding.tvTitle.typeface = Constants.douyinsansB binding.mRecyclerView.adapter = mAdapter binding.mRecyclerView.addItemDecoration(SpacesItemDecoration(DensityUtils.dp2px(10f))) diff --git a/app/src/main/java/com/cheng/bole/ui/dialog/DatePickerDialog.kt b/app/src/main/java/com/cheng/bole/ui/dialog/DatePickerDialog.kt new file mode 100644 index 0000000..18d15ed --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/dialog/DatePickerDialog.kt @@ -0,0 +1,104 @@ +package com.cheng.bole.ui.dialog + +import android.app.Dialog +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import com.cheng.bole.R +import com.cheng.bole.databinding.DialogDatePickerBinding +import com.example.base.extensions.onClick +import com.example.base.utils.ScreenUtils +import com.github.gzuliyujiang.wheelpicker.annotation.DateMode +import com.github.gzuliyujiang.wheelpicker.entity.DateEntity +import java.util.Calendar +import java.util.Date + +class DatePickerDialog : DialogFragment() { + private val title by lazy {arguments?.getString("title")} + private val time by lazy { arguments?.getLong("time") ?: System.currentTimeMillis() } + private val startTime by lazy { arguments?.getLong("start_time") ?: 0 } + private val endTime by lazy { arguments?.getLong("end_time") ?: System.currentTimeMillis() } + private val dateMode by lazy { arguments?.getInt("date_mode") ?: DateMode.YEAR_MONTH_DAY } + + private var selectedTime: Calendar = Calendar.getInstance() + + private var mOnBackListener: ((Long) -> Unit)? = null //回调事件 + + lateinit var binding: DialogDatePickerBinding + + override fun onStart() { + super.onStart() + val window = dialog?.window + val windowParams = window?.attributes + windowParams?.dimAmount = 0.7f + windowParams?.width = ScreenUtils.getWindowSize().x + windowParams?.gravity = Gravity.BOTTOM + windowParams?.windowAnimations = R.style.dialog_bottom + dialog?.window?.attributes = windowParams + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + return super.onCreateView(inflater, container, savedInstanceState) + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val view = layoutInflater.inflate(R.layout.dialog_date_picker, null) + binding = DialogDatePickerBinding.bind(view) + + binding.tvTitle.text = title + + selectedTime.timeInMillis = time + + binding.datePicker.setRange(DateEntity.target(Date(startTime)), if (endTime != 0L) DateEntity.target(Date(endTime)) else null, DateEntity.target(Date(time))) + binding.datePicker.setDateMode(dateMode) + binding.datePicker.setOnDateSelectedListener { year, month, day -> + selectedTime.set(Calendar.YEAR, year) + selectedTime.set(Calendar.MONTH, month - 1) + selectedTime.set(Calendar.DAY_OF_MONTH, day) + } + + binding.tvConfirm.onClick { + mOnBackListener?.invoke(selectedTime.timeInMillis) + dismiss() + } + + binding.tvCancel.onClick { + dismiss() + } + + val dialog = Dialog(requireContext()) + dialog.setContentView(view) + return dialog + } + + fun setOnSelectListener(listener: ((Long) -> Unit)) { + mOnBackListener = listener + } + + companion object { + + fun newInstance( + title: String? = "", + time: Long = System.currentTimeMillis(), + startTime: Long = 0, + endTime: Long = System.currentTimeMillis(), + dateMode: Int = DateMode.YEAR_MONTH_DAY + ): DatePickerDialog { + val arg = Bundle() + val fragment = DatePickerDialog() + arg.putString("title", title) + arg.putLong("time", time) + arg.putLong("start_time", startTime) + arg.putLong("end_time", endTime) + arg.putInt("date_mode", dateMode) + fragment.arguments = arg + return fragment + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/dialog/DownloadAttachmentDialog.kt b/app/src/main/java/com/cheng/bole/ui/dialog/DownloadAttachmentDialog.kt new file mode 100644 index 0000000..bd39c15 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/dialog/DownloadAttachmentDialog.kt @@ -0,0 +1,144 @@ +package com.cheng.bole.ui.dialog + +import android.app.Dialog +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.os.Environment +import android.text.TextUtils +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import androidx.lifecycle.lifecycleScope +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.bole.R +import com.cheng.bole.bean.AttachmentBean +import com.cheng.bole.common.Constants +import com.cheng.bole.databinding.DialogDownloadAttachmentBinding +import com.cheng.bole.manager.DialogEnum +import com.cheng.bole.manager.ShareManager +import com.cheng.bole.utils.DownLoadUtils +import com.example.base.dialog.LoadingDialog +import com.example.base.extensions.longToast +import com.example.base.extensions.onClick +import com.example.base.extensions.toast +import com.example.base.utils.DensityUtils +import com.example.base.utils.ScreenUtils +import com.example.base.utils.SpanUtils +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class DownloadAttachmentDialog : DialogFragment() { + private val mAdapter by lazy { AttachmentAdapter() } + private val attachmentList = mutableListOf() + + private val loadingDialog by lazy { LoadingDialog(requireContext()) } + + private var mOnBackListener: ((DialogEnum) -> Unit)? = null //回调事件 + + lateinit var binding: DialogDownloadAttachmentBinding + + override fun onStart() { + super.onStart() + val window = dialog?.window + val windowParams = window?.attributes + windowParams?.dimAmount = 0.7f + windowParams?.width = (ScreenUtils.getWindowSize().x * 0.8).toInt() + dialog?.window?.attributes = windowParams + + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + return super.onCreateView(inflater, container, savedInstanceState) + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val view = layoutInflater.inflate(R.layout.dialog_download_attachment, null) + + binding = DialogDownloadAttachmentBinding.bind(view) + + binding.tvTitle.typeface = Constants.douyinsansB + + val listStr = arguments?.getString("list") + + if (!TextUtils.isEmpty(listStr)) { + attachmentList.addAll(Gson().fromJson(listStr, object : TypeToken>() {}.type)) + } + binding.rvAttachment.adapter = mAdapter + mAdapter.setList(attachmentList) + + mAdapter.setOnItemChildClickListener { _, v, i -> + when (v.id) { + R.id.btn_download -> { + download(mAdapter.getItem(i)) + } + } + } + + binding.ivClose.onClick { + dismiss() + } + + val dialog = Dialog(requireContext()) + dialog.setContentView(view) + return dialog + } + + private fun download(bean: AttachmentBean) { + loadingDialog.show() + lifecycleScope.launch(Dispatchers.IO) { + DownLoadUtils.getInstance() + .setReadTimeOut(10L) + .setDeleteWhenException(false) + .initUrl(bean.url, null) + .addHeader(mapOf(Pair("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:139.0) Gecko/20100101 Firefox/139.0"))) + .setFilePath(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath) + .setFileName("${bean.title}.${bean.type}") + .setActionCallBack( + actionSuccess = { + ShareManager.shareFile(requireActivity(), it) + longToast("已下载到文件管理/内部储存/下载/${it.name}") + loadingDialog.dismiss() + }, + actionFail = { + loadingDialog.dismiss() + toast("下载失败") + } + ).down() + } + } + + fun setOnSelectListener(listener: ((DialogEnum) -> Unit)) { + mOnBackListener = listener + } + + companion object { + fun newInstance(list: List): DownloadAttachmentDialog { + val arg = Bundle() + arg.putString("list", Gson().toJson(list)) + val fragment = DownloadAttachmentDialog() + fragment.arguments = arg + return fragment + } + } + + inner class AttachmentAdapter : BaseQuickAdapter(R.layout.listitem_bid_attachment) { + init { + addChildClickViewIds(R.id.btn_download) + } + + override fun convert(holder: BaseViewHolder, item: AttachmentBean) { + SpanUtils.with(holder.getView(R.id.tv_name)) + .appendImage(R.mipmap.ic_pdf_attachment) + .appendSpace(DensityUtils.dp2px(8f)) + .append(item.title) + .create() + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/dialog/PopupDialog.kt b/app/src/main/java/com/cheng/bole/ui/dialog/PopupDialog.kt index de7f219..11047cb 100644 --- a/app/src/main/java/com/cheng/bole/ui/dialog/PopupDialog.kt +++ b/app/src/main/java/com/cheng/bole/ui/dialog/PopupDialog.kt @@ -1,5 +1,6 @@ package com.cheng.bole.ui.dialog +import android.annotation.SuppressLint import android.content.Context import android.graphics.Color import android.graphics.drawable.ColorDrawable @@ -7,12 +8,27 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.PopupWindow -import com.example.base.extensions.onClick +import androidx.fragment.app.FragmentManager import com.cheng.bole.R +import com.cheng.bole.bean.SearchOptionBean import com.cheng.bole.databinding.PopAboutTipBinding +import com.cheng.bole.databinding.PopupSearchOptionsBinding import com.cheng.bole.ui.activity.PublicActivity import com.cheng.bole.ui.fragment.guide.GuideFragment import com.cheng.bole.ui.fragment.mine.about.AppConfigFragment +import com.cheng.bole.ui.fragment.search.list.SearchOptionChildAdapter +import com.cheng.bole.ui.fragment.search.list.SearchOptionParentAdapter +import com.cheng.bole.utils.DateUtils +import com.efs.sdk.memleaksdk.monitor.internal.bi +import com.example.base.decoration.DividerItemDecoration +import com.example.base.extensions.getColor +import com.example.base.extensions.getYYYYMMDD +import com.example.base.extensions.gone +import com.example.base.extensions.onClick +import com.example.base.extensions.toast +import com.example.base.extensions.visible +import com.example.base.utils.DensityUtils +import java.util.Calendar object PopupDialog { @@ -39,4 +55,338 @@ object PopupDialog { val height = context.resources.displayMetrics.heightPixels - y popWindow.showAsDropDown(v, 0, 0) } + + fun showSearchAreaOptions(context: Context, v: View, cityList: List, onDismiss: () -> Unit, callback: (List) -> Unit) { + val view = LayoutInflater.from(context).inflate(R.layout.popup_search_options, null, false) + val binding = PopupSearchOptionsBinding.bind(view) + + val parentAdapter = SearchOptionParentAdapter() + binding.rvParent.adapter = parentAdapter + + val childAdapter = SearchOptionChildAdapter(true) + binding.rvChild.adapter = childAdapter + + val optionList = SearchOptionBean.getAreaOptionList() + if (cityList.isNotEmpty()) { + optionList[0].isChecked = false + optionList[0].items[0].isChecked = false + optionList.forEach { option -> + option.items.forEach { item -> + if (cityList.find { it.id == item.id } != null) { + item.isChecked = true + if (optionList.find { it.isChecked } == null) { + option.isChecked = true + } + } + } + val selectedList = option.items.filter { item -> item.id != 0 } + if (selectedList.isNotEmpty() && selectedList.all { item -> item.isChecked }) { + option.isChecked = true + option.items[0].isChecked = true + } + } + } else { + optionList[0].isChecked = true + optionList[0].items[0].isChecked = true + } + parentAdapter.setList(optionList) + childAdapter.setList(optionList.find { it.isChecked }?.items) + + parentAdapter.setOnItemClickListener { _, _, i -> + val item = parentAdapter.getItem(i) + parentAdapter.data.find { it.isChecked }?.isChecked = false + item.isChecked = true + parentAdapter.notifyDataSetChanged() + + childAdapter.setList(item.items) + } + + childAdapter.setOnItemClickListener { _, _, i -> + val item = childAdapter.getItem(i) + item.isChecked = !item.isChecked + if (item.isChecked) { + if (item.id == 0) { + childAdapter.data.forEach { it.isChecked = true } + } else { + if (childAdapter.data.filter { it.id != 0 }.all { it.isChecked }) { + childAdapter.data[0].isChecked = true + } + } + } else { + if (item.id == 0) { + childAdapter.data.forEach { it.isChecked = false } + } else { + if (childAdapter.data[0].isChecked) { + childAdapter.data[0].isChecked = false + } + } + } + + if (parentAdapter.data[0].isChecked) { + for (i in 1 until parentAdapter.data.size) { + parentAdapter.getItem(i).items.forEach { + it.isChecked = false + } + } + } else { + if (parentAdapter.data[0].items[0].isChecked) { + parentAdapter.data[0].items[0].isChecked = false + } + } + + childAdapter.notifyDataSetChanged() + } + + val popWindow = PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true) + popWindow.isClippingEnabled = false + popWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + popWindow.setOnDismissListener { + onDismiss.invoke() + } + + binding.btnReset.onClick { parentAdapter.setList(SearchOptionBean.getAreaOptionList()) } + + binding.btnNext.onClick { + val list = mutableListOf() + parentAdapter.data.forEachIndexed { index, option -> + if (index != 0) { + list.addAll(option.items.filter { it.isChecked && it.id != 0 }) + } + } + if (!parentAdapter.data[0].items[0].isChecked && list.isEmpty()) { + toast("请选择地区") + return@onClick + } + callback.invoke(list) + popWindow.dismiss() + } + + val location = IntArray(2) + v.getLocationOnScreen(location) + popWindow.showAsDropDown(v, 0, 0) + } + + @SuppressLint("NotifyDataSetChanged") + fun showSearchTimeOptions(context: Context, v: View, manager: FragmentManager, time: SearchOptionBean.OptionItem?, onDismiss: () -> Unit, callback: (SearchOptionBean.OptionItem) -> Unit) { + val view = LayoutInflater.from(context).inflate(R.layout.popup_search_options, null, false) + val binding = PopupSearchOptionsBinding.bind(view) + + binding.rvParent.gone() + binding.layoutCustomTime.visible() + + var startTime = 0L + var endTime = 0L + + val adapter = SearchOptionChildAdapter(false) + binding.rvChild.adapter = adapter + binding.rvChild.addItemDecoration(DividerItemDecoration(DensityUtils.dp2px(16f), DensityUtils.dp2px(16f), color = getColor(R.color.color_eeeeee))) + + val optionList = SearchOptionBean.getTimeOptionList()[0] + if (time != null) { + if (time.id == -1) { + optionList.items[0].isChecked = false + } else { + optionList.items.forEach { + it.isChecked = it.id == time.id + } + } + if (time.id != 0) { + startTime = time.startTime.toLong() * 1000 + endTime = time.endTime.toLong() * 1000 + binding.tvStartTime.text = startTime.getYYYYMMDD() + binding.tvEndTime.text = endTime.getYYYYMMDD() + } + } + adapter.setList(optionList.items) + + val popWindow = PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true) + popWindow.isClippingEnabled = false + popWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + popWindow.setOnDismissListener { + onDismiss.invoke() + } + + adapter.setOnItemClickListener { _, _, i -> + val item = adapter.getItem(i) + adapter.data.find { it.isChecked }?.isChecked = false + item.isChecked = true + adapter.notifyDataSetChanged() + + if (item.id == 0) { + startTime = 0L + endTime = 0L + binding.tvStartTime.text = "" + binding.tvEndTime.text = "" + } else { + val calendar = Calendar.getInstance() + when(item.id) { + 1-> calendar.add(Calendar.DATE, -2) + 2-> calendar.add(Calendar.DATE, -6) + 3-> calendar.add(Calendar.MONTH, -1) + 4-> calendar.add(Calendar.MONTH, -3) + 5-> calendar.add(Calendar.YEAR, -1) + } + startTime = DateUtils.getDayStartTime(calendar.timeInMillis) * 1000 + endTime = DateUtils.getDayEndTime() * 1000 + binding.tvStartTime.text = startTime.getYYYYMMDD() + binding.tvEndTime.text = endTime.getYYYYMMDD() + } + } + + binding.tvStartTime.onClick { + val f = DatePickerDialog.newInstance("开始时间") + f.setOnSelectListener { + startTime = DateUtils.getDayStartTime(it) * 1000 + if (endTime in 1.. item.isChecked }?.isChecked = false + adapter.notifyDataSetChanged() + } + } + f.show(manager, DatePickerDialog::class.java.simpleName) + } + + binding.tvEndTime.onClick { + val f = DatePickerDialog.newInstance("结束时间") + f.setOnSelectListener { + endTime = DateUtils.getDayEndTime(it) * 1000 + if (endTime < startTime) { + toast("结束时间不能小于开始时间") + } else { + binding.tvEndTime.text = it.getYYYYMMDD() + optionList.items.find { item -> item.isChecked }?.isChecked = false + adapter.notifyDataSetChanged() + } + } + f.show(manager, DatePickerDialog::class.java.simpleName) + } + + binding.btnReset.onClick { + startTime = 0 + endTime = 0 + binding.tvStartTime.text = "" + binding.tvEndTime.text = "" + + adapter.setList(SearchOptionBean.getTimeOptionList()[0].items) + } + + binding.btnNext.onClick { + var option = adapter.data.find { it.isChecked } + if (option != null) { + option.startTime = if (option.id == 0) "" else "${startTime / 1000}" + option.endTime = if (option.id == 0) "" else "${endTime / 1000}" + } else { + if (startTime == 0L) { + toast("请选择开始时间") + return@onClick + } + if (endTime == 0L) { + toast("请选择结束时间") + return@onClick + } + option = SearchOptionBean.OptionItem(-1, startTime = "${startTime / 1000}", endTime = "${endTime / 1000}") + } + callback.invoke(option) + popWindow.dismiss() + } + + val location = IntArray(2) + v.getLocationOnScreen(location) + popWindow.showAsDropDown(v, 0, 0) + } + + fun showSearchSortOptions(context: Context, v: View, sort: SearchOptionBean.OptionItem?, onDismiss: () -> Unit, callback: (SearchOptionBean.OptionItem) -> Unit) { + val view = LayoutInflater.from(context).inflate(R.layout.popup_search_options, null, false) + val binding = PopupSearchOptionsBinding.bind(view) + + binding.rvParent.gone() + + val adapter = SearchOptionChildAdapter(false) + binding.rvChild.adapter = adapter + binding.rvChild.addItemDecoration(DividerItemDecoration(DensityUtils.dp2px(16f), DensityUtils.dp2px(16f), color = getColor(R.color.color_eeeeee))) + + val optionList = SearchOptionBean.getSortOptionList()[0] + if (sort != null) { + optionList.items.forEach { + it.isChecked = it.id == sort.id + } + } + adapter.setList(optionList.items) + + val popWindow = PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true) + popWindow.isClippingEnabled = false + popWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + popWindow.setOnDismissListener { + onDismiss.invoke() + } + + adapter.setOnItemClickListener { _, _, i -> + val item = adapter.getItem(i) + adapter.data.find { it.isChecked }?.isChecked = false + item.isChecked = true + adapter.notifyDataSetChanged() + } + + binding.btnReset.onClick { adapter.setList(SearchOptionBean.getSortOptionList()[0].items) } + + binding.btnNext.onClick { + val option = adapter.data.find { it.isChecked } + if (option != null) { + callback.invoke(option) + popWindow.dismiss() + } + } + + val location = IntArray(2) + v.getLocationOnScreen(location) + popWindow.showAsDropDown(v, 0, 0) + } + + fun showSearchTypeOptions(context: Context, v: View, typeList: List, onDismiss: () -> Unit, callback: (List) -> Unit) { + val view = LayoutInflater.from(context).inflate(R.layout.popup_search_options, null, false) + val binding = PopupSearchOptionsBinding.bind(view) + + binding.rvParent.gone() + + val adapter = SearchOptionChildAdapter(false) + binding.rvChild.adapter = adapter + binding.rvChild.addItemDecoration(DividerItemDecoration(DensityUtils.dp2px(16f), DensityUtils.dp2px(16f), color = getColor(R.color.color_eeeeee))) + + val optionList = SearchOptionBean.getTypeOptionList()[0] + if (typeList.isNotEmpty()) { + optionList.items.forEach { item -> + if (typeList.find { it.id == item.id } != null) { + item.isChecked = true + } + } + } + adapter.setList(optionList.items) + + val popWindow = PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true) + popWindow.isClippingEnabled = false + popWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + popWindow.setOnDismissListener { + onDismiss.invoke() + } + + adapter.setOnItemClickListener { _, _, i -> + val item = adapter.getItem(i) + item.isChecked = !item.isChecked + adapter.notifyDataSetChanged() + } + + binding.btnReset.onClick { adapter.setList(SearchOptionBean.getTypeOptionList()[0].items) } + + binding.btnNext.onClick { + val list = adapter.data.filter { it.isChecked } + callback.invoke(list) + popWindow.dismiss() + } + + val location = IntArray(2) + v.getLocationOnScreen(location) + popWindow.showAsDropDown(v, 0, 0) + } } \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/dialog/UpdateVersionDialog.kt b/app/src/main/java/com/cheng/bole/ui/dialog/UpdateVersionDialog.kt index c5261a1..82753b1 100644 --- a/app/src/main/java/com/cheng/bole/ui/dialog/UpdateVersionDialog.kt +++ b/app/src/main/java/com/cheng/bole/ui/dialog/UpdateVersionDialog.kt @@ -143,7 +143,7 @@ class UpdateVersionDialog : DialogFragment() { lifecycleScope.launch(Dispatchers.IO) { var totalProgress = 0L DownLoadUtils.getInstance() - .setReadTImeOut(10L) + .setReadTimeOut(10L) .setDeleteWhenException(false) .initUrl(url, null) .setFilePath(com.cheng.bole.utils.FileUtils.getInstance().cacheDownLoderDir.absolutePath) diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/home/BidAdapter.kt b/app/src/main/java/com/cheng/bole/ui/fragment/bid/BidAdapter.kt similarity index 85% rename from app/src/main/java/com/cheng/bole/ui/fragment/home/BidAdapter.kt rename to app/src/main/java/com/cheng/bole/ui/fragment/bid/BidAdapter.kt index 223efd1..f072de5 100644 --- a/app/src/main/java/com/cheng/bole/ui/fragment/home/BidAdapter.kt +++ b/app/src/main/java/com/cheng/bole/ui/fragment/bid/BidAdapter.kt @@ -1,10 +1,11 @@ -package com.cheng.bole.ui.fragment.home +package com.cheng.bole.ui.fragment.bid import android.text.Html import android.text.TextUtils import com.chad.library.adapter.base.viewholder.BaseViewHolder import com.cheng.bole.R import com.cheng.bole.bean.BidItemBean +import com.cheng.bole.utils.BidTypeUtils import com.cheng.bole.widget.CommonShapeView import com.example.base.ui.list.LoadMoreAdapter import java.text.DecimalFormat @@ -13,7 +14,8 @@ class BidAdapter(private val showTipsTime: Boolean = false) : LoadMoreAdapter(R.id.tv_tag) - tvTag.setBgColor(item.getTypeColor()) + tvTag.setBgColor(BidTypeUtils.getTypeColor(item.typeName)) + tvTag.text = BidTypeUtils.getShortName(item.typeName) holder.setText(R.id.tv_title, Html.fromHtml(item.title, Html.FROM_HTML_MODE_LEGACY)) holder.setText(R.id.tv_content, Html.fromHtml(item.content, Html.FROM_HTML_MODE_LEGACY)) diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidDetailFragment.kt b/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidDetailFragment.kt new file mode 100644 index 0000000..ba60dbb --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidDetailFragment.kt @@ -0,0 +1,202 @@ +package com.cheng.bole.ui.fragment.bid.detail + +import android.annotation.SuppressLint +import android.content.Intent +import android.net.Uri +import android.text.TextUtils +import android.util.Base64 +import android.webkit.WebResourceRequest +import android.webkit.WebView +import android.webkit.WebViewClient +import com.cheng.bole.R +import com.cheng.bole.bean.BidDetailBean +import com.cheng.bole.bean.UploadFileBean +import com.cheng.bole.bean.WxShareEntity +import com.cheng.bole.common.Constants +import com.cheng.bole.common.EventConstants +import com.cheng.bole.databinding.FragmentBidDetailBinding +import com.cheng.bole.event.FavoriteEvent +import com.cheng.bole.manager.EventReportManager +import com.cheng.bole.manager.ShareManager +import com.cheng.bole.manager.UserConfigManager +import com.cheng.bole.ui.dialog.DownloadAttachmentDialog +import com.cheng.bole.utils.BidTypeUtils +import com.example.base.browser.BrowserActivity +import com.example.base.common.RxBus +import com.example.base.extensions.getColor +import com.example.base.extensions.gone +import com.example.base.extensions.onClick +import com.example.base.extensions.toast +import com.example.base.extensions.visible +import com.example.base.ui.BaseFragment +import com.example.base.utils.ClipboardUtils +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.tencent.mm.opensdk.openapi.IWXAPI +import com.tencent.mm.opensdk.openapi.WXAPIFactory +import com.umeng.socialize.bean.SHARE_MEDIA + +class BidDetailFragment: BaseFragment() { + private lateinit var api: IWXAPI + private val id by lazy { arguments?.getString("id") ?: "" } + private val infoSource by lazy { arguments?.getString("info_source") ?: "" } + + private val contactsAdapter by lazy { ContactsAdapter() } + private val imageAdapter by lazy { BidImageAdapter() } + + private var detail: BidDetailBean? = null + + private var isFavorite: Boolean = false + + override fun initView() { + super.initView() + binding.rvContacts.adapter = contactsAdapter + + binding.rvImage.adapter = imageAdapter + + initWebView() + } + + private fun initWebView() { + val settings = binding.webView.settings + settings.useWideViewPort = true + settings.loadWithOverviewMode = true + + binding.webView.isVerticalScrollBarEnabled = false + binding.webView.isHorizontalScrollBarEnabled = false + binding.webView.setWebViewClient(object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { + return true + } + }) + } + + override fun initData() { + super.initData() + api = WXAPIFactory.createWXAPI(requireContext(), Constants.WechatAppId) + mViewModel.getBidDetail(id, infoSource) + mViewModel.sendAuth() + EventReportManager.eventReport(EventConstants.JUMP_TO_BID_DETAIL, "", "{\"id\": $id}") + } + + override fun initListener() { + super.initListener() + binding.ivShare.onClick { + if (!api.isWXAppInstalled) { + toast("您没有安装微信客户端,请先下载安装") + return@onClick + } + val shareEntity = WxShareEntity() + shareEntity.title = detail!!.origin_title + shareEntity.link = UserConfigManager.getShareEntity()?.link ?: detail!!.share_url + shareEntity.content = UserConfigManager.getShareEntity()?.content ?: "" + ShareManager.shareUrl(requireActivity(), SHARE_MEDIA.WEIXIN, shareEntity) {} + } + + binding.ivDownload.onClick { + if (detail!!.origin_attachment.isNotEmpty()) { + val f = DownloadAttachmentDialog.newInstance(detail!!.origin_attachment) + f.show(childFragmentManager, DownloadAttachmentDialog::class.java.simpleName) + } else { + toast("不可下载") + } + } + + binding.ivFavorite.onClick { + if (!isFavorite) { + mViewModel.favorite(detail!!.id, detail!!.info_source) + } else { + mViewModel.favoriteCancel(detail!!.id) + } + } + + binding.ivView.onClick { + BrowserActivity.start(requireContext(), "原文", detail!!.origin_url, true) + ClipboardUtils.copyText(detail!!.origin_url) + toast("原文链接已复制") + } + + contactsAdapter.setOnItemChildClickListener { _, view, i -> + val item = contactsAdapter.getItem(i) + when(view.id) { + R.id.iv_call -> { + val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:${item.phone}")) + startActivity(intent) + } + } + + } + } + + override fun initObserve() { + super.initObserve() + mViewModel.detailLiveData.observe(this) { + detail = it + setData() + } + + mViewModel.favoriteLiveData.observe(this) { + isFavorite = true + setFavoriteStyle() + RxBus.defaultInstance.post(FavoriteEvent()) + toast("收藏成功") + } + + mViewModel.cancelLiveData.observe(this) { + isFavorite = false + setFavoriteStyle() + RxBus.defaultInstance.post(FavoriteEvent()) + toast("取消收藏") + } + } + + @SuppressLint("SetJavaScriptEnabled") + private fun setData() { + if (detail != null) { + binding.tvTitle.text = detail!!.origin_title + binding.tvTag.text = BidTypeUtils.getShortName(detail!!.type_name) + binding.tvTag.setBgColor(BidTypeUtils.getTypeColor(detail!!.type_name)) + binding.tvAmount.text = detail!!.project_amount + binding.tvTime.text = detail!!.tips_time + contactsAdapter.setList(detail!!.contact) + + if (TextUtils.isEmpty(detail!!.content_type) || detail!!.content_type == "1") { + val encodedHtml: String = Base64.encodeToString(detail!!.origin_content.toString().toByteArray(), Base64.NO_PADDING) + binding.webView.loadData(encodedHtml,"text/html","base64") + binding.webView.visible() + binding.rvImage.gone() + } else { + val imageList = Gson().fromJson>(Gson().toJson(detail!!.origin_content), object : TypeToken>() {}.type) + imageAdapter.setList(imageList) + binding.rvImage.visible() + binding.webView.gone() + } + + isFavorite = detail!!.is_fav + setFavoriteStyle() + + if (TextUtils.isEmpty(detail?.project_amount)) { + binding.tvAmount.gone() + } + if (detail!!.contact.isEmpty()) { + binding.layoutContacts.gone() + } + if (detail!!.origin_attachment.isEmpty()) { + binding.ivDownload.setImageResource(R.mipmap.ic_bid_download_disable) + } + } + } + + private fun setFavoriteStyle() { + if (isFavorite) { + binding.ivFavorite.setImageResource(R.mipmap.ic_bid_favorited) + } else { + binding.ivFavorite.setImageResource(R.mipmap.ic_bid_favorite) + } + } + + override fun onDestroyView() { + binding.webView.destroy() + super.onDestroyView() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidDetailViewModel.kt b/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidDetailViewModel.kt new file mode 100644 index 0000000..5773e1e --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidDetailViewModel.kt @@ -0,0 +1,75 @@ +package com.cheng.bole.ui.fragment.bid.detail + +import androidx.lifecycle.MutableLiveData +import com.cheng.bole.bean.BidDetailBean +import com.cheng.bole.net.ApiFactory +import com.example.base.extensions.toast +import com.example.base.utils.L +import com.example.base.viewmodel.BaseViewModel +import com.google.gson.JsonObject +import okhttp3.RequestBody.Companion.toRequestBody + +class BidDetailViewModel: BaseViewModel() { + val detailLiveData = MutableLiveData() + val favoriteLiveData = MutableLiveData() + val cancelLiveData = MutableLiveData() + + fun getBidDetail(id: String, infoSource: String) { + showDialog() + launchOnUiTryCatch({ + val response = ApiFactory.apiService.getBidDetail(id, "recommend", infoSource) + if (response.status) { + detailLiveData.postValue(response.data) + } else toast(response.message, true) + dismissDialog() + }, { + dismissDialog() + setError(it) + L.d(it) + }) + } + + fun favorite(id: String, infoSource: String) { + showDialog() + launchOnUiTryCatch({ + val jsonObject = JsonObject() + jsonObject.addProperty("infoId", id) + jsonObject.addProperty("infoSource",infoSource) + val response = ApiFactory.apiService.favorite(jsonObject.toString().toRequestBody()) + if (response.status) { + favoriteLiveData.postValue(Any()) + } + dismissDialog() + }, { + dismissDialog() + setError(it) + L.d(it) + }) + } + + fun favoriteCancel(id: String) { + showDialog() + launchOnUiTryCatch({ + val response = ApiFactory.apiService.favoriteCancel(id) + if (response.status) { + cancelLiveData.postValue(Any()) + } + dismissDialog() + }, { + dismissDialog() + setError(it) + L.d(it) + }) + } + + fun sendAuth() { + launchOnUiTryCatch({ + val jsonObject = JsonObject() + jsonObject.addProperty("scene", "info") + jsonObject.addProperty("count", 1) + ApiFactory.apiService.sendAuth(jsonObject.toString().toRequestBody()) + }, { + L.d(it) + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidImageAdapter.kt b/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidImageAdapter.kt new file mode 100644 index 0000000..f85cc12 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/BidImageAdapter.kt @@ -0,0 +1,32 @@ +package com.cheng.bole.ui.fragment.bid.detail + +import android.graphics.Bitmap +import android.graphics.drawable.Drawable +import com.bumptech.glide.Glide +import com.bumptech.glide.request.target.CustomTarget +import com.bumptech.glide.request.transition.Transition +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.bole.R +import com.cheng.bole.bean.UploadFileBean +import com.cheng.bole.utils.BitmapUtils + +class BidImageAdapter: BaseQuickAdapter(R.layout.listitem_bid_detail_image) { + override fun convert(holder: BaseViewHolder, item: UploadFileBean) { + Glide.with(context) + .asBitmap() + .load(item.url) + .into(object : CustomTarget() { + override fun onResourceReady(resource: Bitmap, transition: Transition?) { + val scale = recyclerView.width / resource.width + val bitmap = BitmapUtils.resizeBitmap(resource, recyclerView.width, resource.height * scale ) + holder.setImageBitmap(R.id.iv_image, bitmap) + } + + override fun onLoadCleared(placeholder: Drawable?) { + + } + + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/ContactsAdapter.kt b/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/ContactsAdapter.kt new file mode 100644 index 0000000..3638d0d --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/bid/detail/ContactsAdapter.kt @@ -0,0 +1,17 @@ +package com.cheng.bole.ui.fragment.bid.detail + +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.bole.R +import com.cheng.bole.bean.ContactsInfoBean + +class ContactsAdapter: BaseQuickAdapter(R.layout.listitem_bid_detail_contact) { + init { + addChildClickViewIds(R.id.iv_call) + } + + override fun convert(holder: BaseViewHolder, item: ContactsInfoBean) { + holder.setText(R.id.tv_name, item.name) + holder.setText(R.id.tv_phone, item.phone) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/home/HomeFragment.kt b/app/src/main/java/com/cheng/bole/ui/fragment/home/HomeFragment.kt index 6391eaf..cce6a7e 100644 --- a/app/src/main/java/com/cheng/bole/ui/fragment/home/HomeFragment.kt +++ b/app/src/main/java/com/cheng/bole/ui/fragment/home/HomeFragment.kt @@ -2,20 +2,28 @@ package com.cheng.bole.ui.fragment.home import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.recyclerview.widget.RecyclerView.HORIZONTAL -import com.chad.library.adapter.base.BaseQuickAdapter -import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.bole.R import com.cheng.bole.bean.BidItemBean import com.cheng.bole.bean.MenuEntity import com.cheng.bole.common.Constants +import com.cheng.bole.common.EventConstants import com.cheng.bole.databinding.FragmentHomeBinding -import com.efs.sdk.memleaksdk.monitor.internal.bi +import com.cheng.bole.manager.EventReportManager +import com.cheng.bole.manager.SearchHistoryManager +import com.cheng.bole.ui.activity.PublicActivity +import com.cheng.bole.ui.fragment.bid.BidAdapter +import com.cheng.bole.ui.fragment.bid.detail.BidDetailFragment +import com.cheng.bole.ui.fragment.mine.vip.VipFragment +import com.cheng.bole.ui.fragment.search.SearchFragment +import com.cheng.bole.ui.fragment.search.list.SearchListFragment import com.example.base.decoration.GridSpaceItemDecoration import com.example.base.decoration.SpacesItemDecoration +import com.example.base.extensions.getColor import com.example.base.extensions.onClick -import com.example.base.ui.BaseFragment import com.example.base.ui.list.ListFragment import com.example.base.utils.DensityUtils -import com.example.base.utils.L +import com.example.base.utils.SpanUtils +import java.text.DecimalFormat import kotlin.math.abs @@ -31,6 +39,8 @@ class HomeFragment : ListFragment + binding.appBarLayout.addOnOffsetChangedListener { appBarLayout, verticalOffset -> val lp = binding.layoutContent.layoutParams as CoordinatorLayout.LayoutParams - if (abs(verticalOffset) >= binding.appBarLayout.height - DensityUtils.dp2px(45f)) { - lp.topMargin = (-DensityUtils.dp2px(25f) * (1f - abs(verticalOffset).toFloat() / (binding.appBarLayout.height - DensityUtils.dp2px(20f)))).toInt() - } else { - lp.topMargin = -DensityUtils.dp2px(65f) - } + lp.topMargin = (-DensityUtils.dp2px(45f) * (1f - abs(verticalOffset).toFloat() / appBarLayout.totalScrollRange)).toInt() binding.layoutContent.layoutParams = lp } + binding.tvSearch.onClick { + PublicActivity.start(requireContext(), SearchFragment::class.java) + EventReportManager.eventReport(EventConstants.JUMP_TO_BID_SEARCH) + } + binding.ivRefresh.onClick { if (keywordAdapter.data.isNotEmpty()) { mViewModel.getHotKeywordList(keywordAdapter.data.last()) @@ -71,6 +82,19 @@ class HomeFragment : ListFragment + mAdapter.setOnItemClickListener { _, _, i -> + item = mAdapter.getItem(i) + mViewModel.checkAuth() + } + } + + keywordAdapter.setOnItemClickListener { _, _, i -> + val item = keywordAdapter.getItem(i) + PublicActivity.start(requireContext(), SearchListFragment::class.java,Pair("keyword", item)) + SearchHistoryManager.addHistory(item) + } } override fun initObserve() { @@ -78,5 +102,27 @@ class HomeFragment : ListFragment() { - override suspend fun requestApi(params: ArrayMap): Result> { - return ApiFactory.apiService.getRecommendList(params).toListResult() - } - + val totalLiveData = MutableLiveData() val authLiveData = MutableLiveData() val recommendLiveData = MutableLiveData>() + override suspend fun requestApi(params: ArrayMap): Result> { + val response = ApiFactory.apiService.getRecommendList(params) + if (response.status) { + totalLiveData.postValue(response.data.total) + } + return response.toListResult() + } + fun getHotKeywordList(query: String) { launchOnUiTryCatch({ val params = mutableMapOf() diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/main/MainFragment.kt b/app/src/main/java/com/cheng/bole/ui/fragment/main/MainFragment.kt index 6e41a6a..bd23787 100644 --- a/app/src/main/java/com/cheng/bole/ui/fragment/main/MainFragment.kt +++ b/app/src/main/java/com/cheng/bole/ui/fragment/main/MainFragment.kt @@ -99,6 +99,9 @@ class MainFragment : BaseFragment() { override fun onResume() { super.onResume() mViewModel.userInfo() + if (UserConfigManager.getAreaList().isEmpty()) { + mViewModel.getAreaList() + } } override fun initObserve() { @@ -121,6 +124,11 @@ class MainFragment : BaseFragment() { } } } + + mViewModel.areaLiveData.observe(this) { + UserConfigManager.saveAreaList(it) + } + mViewModel.getCouponLiveData.observe(this) { toast("领取成功") PublicActivity.start(requireContext(), CouponFragment::class.java) diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/main/MainViewModel.kt b/app/src/main/java/com/cheng/bole/ui/fragment/main/MainViewModel.kt index da06b35..3b67d02 100644 --- a/app/src/main/java/com/cheng/bole/ui/fragment/main/MainViewModel.kt +++ b/app/src/main/java/com/cheng/bole/ui/fragment/main/MainViewModel.kt @@ -1,15 +1,19 @@ package com.cheng.bole.ui.fragment.main import androidx.lifecycle.MutableLiveData +import com.cheng.bole.bean.AreaBean +import com.cheng.bole.bean.UserEntity +import com.cheng.bole.net.ApiFactory import com.example.base.extensions.toast import com.example.base.utils.L import com.example.base.viewmodel.BaseViewModel import com.google.gson.JsonObject -import com.cheng.bole.net.ApiFactory import okhttp3.RequestBody.Companion.toRequestBody class MainViewModel : BaseViewModel() { - val userInfoLiveData = MutableLiveData() + val userInfoLiveData = MutableLiveData() + + val areaLiveData = MutableLiveData>() val getCouponLiveData = MutableLiveData() fun userInfo() { @@ -24,6 +28,19 @@ class MainViewModel : BaseViewModel() { }) } + fun getAreaList() { + launchOnUiTryCatch({ + val response = ApiFactory.apiService.getAreaList() + if (response.status) { + areaLiveData.postValue(response.data) + } else toast(response.message, true) + }, { + setError(it) + L.d(it) + }) + } + + fun getActivityCoupon(ids: String, type: Int) { showDialog() launchOnUiTryCatch({ diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/search/HistoryKeywordAdapter.kt b/app/src/main/java/com/cheng/bole/ui/fragment/search/HistoryKeywordAdapter.kt new file mode 100644 index 0000000..8af7e6c --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/search/HistoryKeywordAdapter.kt @@ -0,0 +1,11 @@ +package com.cheng.bole.ui.fragment.search + +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.bole.R + +class HistoryKeywordAdapter: BaseQuickAdapter(R.layout.listitem_search_history) { + override fun convert(holder: BaseViewHolder, item: String) { + holder.setText(R.id.tv_name, item) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/search/RecommendKeywordAdapter.kt b/app/src/main/java/com/cheng/bole/ui/fragment/search/RecommendKeywordAdapter.kt new file mode 100644 index 0000000..d30d112 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/search/RecommendKeywordAdapter.kt @@ -0,0 +1,11 @@ +package com.cheng.bole.ui.fragment.search + +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.bole.R + +class RecommendKeywordAdapter: BaseQuickAdapter(R.layout.listitem_search_recommend) { + override fun convert(holder: BaseViewHolder, item: String) { + holder.setText(R.id.tv_name, item) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/search/SearchFragment.kt b/app/src/main/java/com/cheng/bole/ui/fragment/search/SearchFragment.kt new file mode 100644 index 0000000..fcaea52 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/search/SearchFragment.kt @@ -0,0 +1,165 @@ +package com.cheng.bole.ui.fragment.search + +import android.annotation.SuppressLint +import android.text.TextUtils +import android.view.View +import android.view.ViewTreeObserver +import android.view.animation.RotateAnimation +import androidx.constraintlayout.widget.ConstraintLayout +import com.cheng.bole.common.Constants +import com.cheng.bole.databinding.FragmentSearchBinding +import com.cheng.bole.impl.TextWatcherImpl +import com.cheng.bole.manager.DialogEnum +import com.cheng.bole.manager.SearchHistoryManager +import com.cheng.bole.ui.activity.PublicActivity +import com.cheng.bole.ui.dialog.TipDialog +import com.cheng.bole.ui.fragment.merchant.MerchantFragment +import com.cheng.bole.ui.fragment.search.list.SearchListFragment +import com.example.base.extensions.gone +import com.example.base.extensions.onClick +import com.example.base.extensions.toast +import com.example.base.extensions.visible +import com.example.base.ui.BaseFragment +import com.google.android.flexbox.FlexDirection +import com.google.android.flexbox.FlexWrap +import com.google.android.flexbox.FlexboxLayoutManager +import com.google.android.flexbox.JustifyContent + +class SearchFragment: BaseFragment() { + private val type by lazy { arguments?.getInt("type") ?: 0 } + + private val historyAdapter by lazy { HistoryKeywordAdapter() } + private val recommendAdapter by lazy { RecommendKeywordAdapter() } + + private val textWatcher = object : TextWatcherImpl() { + @SuppressLint("SetTextI18n") + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + binding.ivClearText.visibility = if (TextUtils.isEmpty(s)) View.INVISIBLE else View.VISIBLE + } + } + + override fun initView() { + super.initView() + binding.tvTitle.typeface = Constants.pmzdbt + + val historyLayoutManager = FlexboxLayoutManager(requireContext()) + historyLayoutManager.flexDirection = FlexDirection.ROW + historyLayoutManager.flexWrap = FlexWrap.WRAP + historyLayoutManager.justifyContent = JustifyContent.FLEX_START + binding.rvHistory.layoutManager = historyLayoutManager + binding.rvHistory.adapter = historyAdapter + + val recommendLayoutManager = FlexboxLayoutManager(requireContext()) + recommendLayoutManager.flexDirection = FlexDirection.ROW + recommendLayoutManager.flexWrap = FlexWrap.WRAP + recommendLayoutManager.justifyContent = JustifyContent.FLEX_START + binding.rvRecommend.layoutManager = recommendLayoutManager + binding.rvRecommend.adapter = recommendAdapter + } + + override fun initData() { + super.initData() + mViewModel.getHotKeywordList("") + } + + override fun initListener() { + super.initListener() + binding.ivTopBg.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + (binding.tvTitle.layoutParams as ConstraintLayout.LayoutParams).topMargin = (binding.ivTopBg.height * 100f / 300f).toInt() + (binding.layoutSearch.layoutParams as ConstraintLayout.LayoutParams).topMargin = (binding.ivTopBg.height * 200f / 300f).toInt() + binding.ivTopBg.viewTreeObserver.addOnGlobalLayoutListener(this) + } + }) + + binding.etSearch.addTextChangedListener(textWatcher) + + binding.ivClearText.onClick { + binding.etSearch.setText("") + } + + binding.btnSearch.onClick { + val keyword = binding.etSearch.text.toString().trim() + if (TextUtils.isEmpty(keyword)) { + toast("请输入搜索关键词") + return@onClick + } + if (type == 0) { + PublicActivity.start(requireContext(), SearchListFragment::class.java, Pair("keyword", keyword)) + } else { + PublicActivity.start(requireContext(), MerchantFragment::class.java, Pair("keyword", keyword)) + } + historyAdapter.setList(SearchHistoryManager.addHistory(keyword)) + binding.layoutHistory.visible() + } + + binding.ivClearHistory.onClick { + val f = TipDialog.newInstance("温馨提示", "确定清空搜索历史?") + f.setOnSelectListener { + if (it == DialogEnum.CLICK_OK) { + SearchHistoryManager.clear() + historyAdapter.setList(emptyList()) + binding.layoutHistory.gone() + } + } + f.show(childFragmentManager, TipDialog::class.java.simpleName) + } + + binding.ivRefreshRecommend.onClick { + startRotate() + mViewModel.getHotKeywordList(if (recommendAdapter.data.isNotEmpty()) recommendAdapter.data.last() else "") + } + + historyAdapter.setOnItemClickListener { _, _, i -> + val item = historyAdapter.getItem(i) + if (type == 0) { + PublicActivity.start(requireContext(), SearchListFragment::class.java, Pair("keyword", item)) + } else { + PublicActivity.start(requireContext(), MerchantFragment::class.java, Pair("keyword", item)) + } + binding.etSearch.setText(item) + historyAdapter.setList(SearchHistoryManager.updateHistory(item)) + } + + recommendAdapter.setOnItemClickListener { _, _, i -> + val item = recommendAdapter.getItem(i) + if (type == 0) { + PublicActivity.start(requireContext(), SearchListFragment::class.java, Pair("keyword", item)) + } else { + PublicActivity.start(requireContext(), MerchantFragment::class.java, Pair("keyword", item)) + } + binding.etSearch.setText(item) + historyAdapter.setList(SearchHistoryManager.addHistory(item)) + binding.layoutHistory.visible() + } + } + + override fun initObserve() { + super.initObserve() + mViewModel.recommendLiveData.observe(this) { + recommendAdapter.setList(it) + } + } + + private fun startRotate() { + if (binding.ivRefreshRecommend.animation != null) { + binding.ivRefreshRecommend.animation.cancel() + } + val anim = RotateAnimation(0f, 360f, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f) + anim.duration = 1000 + binding.ivRefreshRecommend.startAnimation(anim) + } + + override fun onResume() { + super.onResume() + if (SearchHistoryManager.getHistory().isNotEmpty()) { + historyAdapter.setList(SearchHistoryManager.getHistory()) + binding.layoutHistory.visible() + } + } + + override fun onDestroyView() { + binding.etSearch.removeTextChangedListener(textWatcher) + super.onDestroyView() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/search/SearchViewModel.kt b/app/src/main/java/com/cheng/bole/ui/fragment/search/SearchViewModel.kt new file mode 100644 index 0000000..9bbf0c0 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/search/SearchViewModel.kt @@ -0,0 +1,29 @@ +package com.cheng.bole.ui.fragment.search + +import androidx.lifecycle.MutableLiveData +import com.cheng.bole.net.ApiFactory +import com.example.base.extensions.toast +import com.example.base.utils.L +import com.example.base.viewmodel.BaseViewModel + +class SearchViewModel: BaseViewModel() { + val recommendLiveData = MutableLiveData>() + + fun getHotKeywordList(query: String) { + showDialog() + launchOnUiTryCatch({ + val params = mutableMapOf() + params["query"] = query + params["size"] = "12" + val response = ApiFactory.apiService.getHotKeywords(params) + if (response.status) { + recommendLiveData.postValue(response.data) + } else toast(response.message, true) + dismissDialog() + }, { + dismissDialog() + setError(it) + L.d(it) + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchListFragment.kt b/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchListFragment.kt new file mode 100644 index 0000000..bdb6334 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchListFragment.kt @@ -0,0 +1,206 @@ +package com.cheng.bole.ui.fragment.search.list + +import android.animation.ObjectAnimator +import android.annotation.SuppressLint +import android.text.TextUtils +import android.view.KeyEvent +import android.view.View +import androidx.core.animation.addListener +import com.cheng.bole.R +import com.cheng.bole.bean.BidItemBean +import com.cheng.bole.bean.SearchOptionBean +import com.cheng.bole.databinding.FragmentSearchListBinding +import com.cheng.bole.impl.TextWatcherImpl +import com.cheng.bole.manager.SearchHistoryManager +import com.cheng.bole.manager.UserConfigManager +import com.cheng.bole.ui.activity.PublicActivity +import com.cheng.bole.ui.dialog.PopupDialog +import com.cheng.bole.ui.fragment.bid.BidAdapter +import com.cheng.bole.ui.fragment.bid.detail.BidDetailFragment +import com.cheng.bole.ui.fragment.mine.vip.VipFragment +import com.cheng.bole.utils.KeyboardUtils +import com.example.base.extensions.getColor +import com.example.base.extensions.gone +import com.example.base.extensions.onClick +import com.example.base.extensions.toast +import com.example.base.extensions.visible +import com.example.base.ui.list.ListFragment + +class SearchListFragment : ListFragment() { + private val keyword by lazy { arguments?.getString("keyword") ?: "" } + private val typeId by lazy { arguments?.getString("typeId") ?: "" } + + private val cityList = mutableListOf() + private val typeList = mutableListOf() + private var timeOption: SearchOptionBean.OptionItem? = null + private var sortOption: SearchOptionBean.OptionItem? = null + + private var item: BidItemBean? = null + + override fun noDataClick() { + + } + + override fun bindAdapter() = BidAdapter(true) + + private val textWatcher = object : TextWatcherImpl() { + @SuppressLint("SetTextI18n") + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + binding.ivClearText.visibility = if (TextUtils.isEmpty(s)) View.INVISIBLE else View.VISIBLE + } + } + + override fun initView() { + super.initView() + + mEmptyView.setNoDataLogo(R.mipmap.ic_empty_data) + } + + override fun initData() { + super.initData() + binding.etSearch.setText(keyword) + + mViewModel.params["query"] = keyword + mViewModel.params["sort"] = UserConfigManager.getSearchSort() + if (!TextUtils.isEmpty(typeId)) { + val type = UserConfigManager.getBidTypes().find { it.id == typeId } + if (type != null) { + typeList.add(SearchOptionBean.OptionItem(type.id.toInt(), type.name, true)) + mViewModel.params["typeId"] = typeList.map { item -> item.id }.joinToString(",") + } + } + firstLoad() + } + + override fun initListener() { + super.initListener() + binding.etSearch.addTextChangedListener(textWatcher) + + binding.etSearch.setOnEditorActionListener { _, _, event -> + if (event != null && event.keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN) { + val keyword = binding.etSearch.text.toString().trim() + if (TextUtils.isEmpty(keyword)) { + toast("请输入搜索关键词") + return@setOnEditorActionListener true + } + KeyboardUtils.hideSoftInput(requireActivity()) + SearchHistoryManager.addHistory(keyword) + mViewModel.params["query"] = keyword + firstLoad() + return@setOnEditorActionListener true + } + false + } + + binding.ivClearText.onClick { + binding.etSearch.setText("") + } + + binding.btnArea.onClick { + binding.btnArea.setTextColor(getColor(R.color.color_125ffe)) + binding.btnArea.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_option_arrow_up, 0) + PopupDialog.showSearchAreaOptions(requireContext(), binding.layoutOptions, cityList, { + binding.viewMask.gone() + binding.btnArea.setTextColor(getColor(R.color.color_1a1a1a)) + binding.btnArea.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_option_arrow_down, 0) + }, { + cityList.clear() + cityList.addAll(it) + + mViewModel.params["cityId"] = it.map { item -> item.id }.joinToString(",") + firstLoad() + }) + showMask() + } + + binding.btnTime.onClick { + binding.btnTime.setTextColor(getColor(R.color.color_125ffe)) + binding.btnTime.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_option_arrow_up, 0) + PopupDialog.showSearchTimeOptions(requireContext(), binding.layoutOptions, childFragmentManager, timeOption, { + binding.viewMask.gone() + binding.btnTime.setTextColor(getColor(R.color.color_1a1a1a)) + binding.btnTime.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_option_arrow_down, 0) + }, { + timeOption = it + mViewModel.params["start_time"] = it.startTime + mViewModel.params["end_time"] = it.endTime + firstLoad() + }) + showMask() + } + + binding.btnSort.onClick { + binding.btnSort.setTextColor(getColor(R.color.color_125ffe)) + binding.btnSort.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_option_arrow_up, 0) + PopupDialog.showSearchSortOptions(requireContext(), binding.layoutOptions, sortOption, { + binding.viewMask.gone() + binding.btnSort.setTextColor(getColor(R.color.color_1a1a1a)) + binding.btnSort.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_option_arrow_down, 0) + }, { + sortOption = it + if (it.id == 0) { + mViewModel.params["sort"] = UserConfigManager.getSearchSort() + } else { + if (UserConfigManager.getSearchSort() == "issue_time DESC") { + mViewModel.params["sort"] = "issue_time ASC" + } else { + mViewModel.params["sort"] = "issue_time DESC" + } + } + firstLoad() + }) + showMask() + } + + binding.btnType.onClick { + binding.btnType.setTextColor(getColor(R.color.color_125ffe)) + binding.btnType.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_option_arrow_up, 0) + PopupDialog.showSearchTypeOptions(requireContext(), binding.layoutOptions, typeList, { + binding.viewMask.gone() + binding.btnType.setTextColor(getColor(R.color.color_1a1a1a)) + binding.btnType.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_option_arrow_down, 0) + }, { + typeList.addAll(it) + mViewModel.params["typeId"] = it.map { item -> item.id }.joinToString(",") + firstLoad() + }) + showMask() + } + + mAdapter.setOnItemClickListener { _, _, i -> + item = mAdapter.getItem(i) + mViewModel.checkAuth() + } + } + + override fun initObserve() { + super.initObserve() + mViewModel.authLiveData.observe(this) { + if (it.auth) { + PublicActivity.start( + requireContext(), + BidDetailFragment::class.java, + Pair("id", item!!.id), + Pair("info_source", item!!.info_source) + ) + } else { + PublicActivity.start(requireContext(), VipFragment::class.java, Pair("origin", "view_bid")) + } + } + } + + private fun showMask() { + val anim = ObjectAnimator.ofFloat(binding.viewMask, "alpha", 0f, 1f) + anim.duration = 200 + anim.addListener(onStart = { + binding.viewMask.visible() + }) + anim.startDelay = 100 + anim.start() + } + + override fun onDestroyView() { + binding.etSearch.removeTextChangedListener(textWatcher) + super.onDestroyView() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchListViewModel.kt b/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchListViewModel.kt new file mode 100644 index 0000000..207161d --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchListViewModel.kt @@ -0,0 +1,31 @@ +package com.cheng.bole.ui.fragment.search.list + +import androidx.collection.ArrayMap +import androidx.lifecycle.MutableLiveData +import com.cheng.bole.bean.BidItemBean +import com.cheng.bole.bean.UserAuthBean +import com.cheng.bole.net.ApiFactory +import com.cheng.bole.net.model.toListResult +import com.example.base.extensions.toast +import com.example.base.utils.L +import com.example.base.viewmodel.ListViewModel + +class SearchListViewModel: ListViewModel() { + override suspend fun requestApi(params: ArrayMap): Result> { + return ApiFactory.apiService.search(params).toListResult() + } + + val authLiveData = MutableLiveData() + + fun checkAuth() { + launchOnUiTryCatch({ + val response = ApiFactory.apiService.checkAuth() + if (response.status) { + authLiveData.postValue(response.data) + } else toast(response.message, true) + }, { + setError(it) + L.d(it) + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchOptionChildAdapter.kt b/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchOptionChildAdapter.kt new file mode 100644 index 0000000..e803fe1 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchOptionChildAdapter.kt @@ -0,0 +1,24 @@ +package com.cheng.bole.ui.fragment.search.list + +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.bole.R +import com.cheng.bole.bean.SearchOptionBean +import com.example.base.extensions.getColor +import com.example.base.utils.DensityUtils + +class SearchOptionChildAdapter(private val hasParent: Boolean) : + BaseQuickAdapter(R.layout.listitem_search_option_child) { + override fun convert(holder: BaseViewHolder, item: SearchOptionBean.OptionItem) { + holder.setText(R.id.tv_name, item.name) + holder.setTextColor(R.id.tv_name, if (item.isChecked) getColor(R.color.color_125ffe) else getColor(R.color.color_1a1a1a)) + holder.setVisible(R.id.iv_check, item.isChecked) + if (hasParent) { + holder.itemView.layoutParams.height = DensityUtils.dp2px(40f) + holder.itemView.setPadding(DensityUtils.dp2px(30f), 0, DensityUtils.dp2px(25f), 0) + } else { + holder.itemView.layoutParams.height = DensityUtils.dp2px(44f) + holder.itemView.setPadding(DensityUtils.dp2px(16f), 0, DensityUtils.dp2px(16f), 0) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchOptionParentAdapter.kt b/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchOptionParentAdapter.kt new file mode 100644 index 0000000..7f4af9f --- /dev/null +++ b/app/src/main/java/com/cheng/bole/ui/fragment/search/list/SearchOptionParentAdapter.kt @@ -0,0 +1,15 @@ +package com.cheng.bole.ui.fragment.search.list + +import android.graphics.Color +import com.chad.library.adapter.base.BaseQuickAdapter +import com.chad.library.adapter.base.viewholder.BaseViewHolder +import com.cheng.bole.R +import com.cheng.bole.bean.SearchOptionBean + +class SearchOptionParentAdapter: BaseQuickAdapter(R.layout.listitem_search_option_parent) { + override fun convert(holder: BaseViewHolder, item: SearchOptionBean) { + holder.setText(R.id.tv_name, item.title) + holder.setVisible(R.id.view_tag, item.isChecked) + holder.itemView.setBackgroundColor(if (item.isChecked) Color.WHITE else Color.TRANSPARENT) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/utils/BidTypeUtils.kt b/app/src/main/java/com/cheng/bole/utils/BidTypeUtils.kt new file mode 100644 index 0000000..b45f3b7 --- /dev/null +++ b/app/src/main/java/com/cheng/bole/utils/BidTypeUtils.kt @@ -0,0 +1,33 @@ +package com.cheng.bole.utils + +import android.graphics.Color + +object BidTypeUtils { + fun getShortName(typeName: String): String { + return when (typeName) { + "招标计划" -> "招标" + "采购公告" -> "采购" + "招标公告" -> "预告" + "合同公告" -> "合同" + "中标公告" -> "中标" + "竞争性磋商" -> "竞争性磋商" + "更正公告" -> "更正" + "终止公告" -> "终止" + else -> "其他" + } + } + + fun getTypeColor(typeName: String): Int { + return when (typeName) { + "招标计划" -> Color.parseColor("#2B88F9") + "采购公告" -> Color.parseColor("#FF7344") + "招标公告" -> Color.parseColor("#14CEB3") + "合同公告" -> Color.parseColor("#FFA91D") + "中标公告" -> Color.parseColor("#FF1B1B") + "竞争性磋商" -> Color.parseColor("#0DA9FF") + "更正公告" -> Color.parseColor("#7066FF") + "终止公告" -> Color.parseColor("#8C9199") + else -> Color.parseColor("#EEEEEE") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/cheng/bole/utils/DownLoadUtils.kt b/app/src/main/java/com/cheng/bole/utils/DownLoadUtils.kt index c7ced8c..23a4d30 100644 --- a/app/src/main/java/com/cheng/bole/utils/DownLoadUtils.kt +++ b/app/src/main/java/com/cheng/bole/utils/DownLoadUtils.kt @@ -44,7 +44,7 @@ class DownLoadUtils private constructor() { } private var readTimeOut = 30L - fun setReadTImeOut(read: Long): DownLoadUtils { + fun setReadTimeOut(read: Long): DownLoadUtils { this.readTimeOut = read return this } @@ -90,23 +90,24 @@ class DownLoadUtils private constructor() { .addInterceptor(interceptor ?: LoggingInterceptor()) .build() } - private var actionGetTotal: (total: Long) -> Unit? = { _ -> } - private var actionProgress: (position: Long) -> Unit? = { _ -> } - private var actionSuccess: (file: File) -> Unit? = { _ -> } - private var actionCancel: () -> Unit? = { } - private var actionFail: (msg: String) -> Unit? = { _ -> } + private var actionGetTotal: ((total: Long) -> Unit)? = { _ -> } + private var actionProgress: ((position: Long) -> Unit)? = { _ -> } + private var actionSuccess: (file: File) -> Unit = { _ -> } + private var actionFail: ((msg: String) -> Unit)? = { _ -> } + private var actionCancel: (() -> Unit)? = { } fun setActionCallBack( - actionGetTotal: (total: Long) -> Unit, - actionProgress: (position: Long) -> Unit, + actionGetTotal: ((total: Long) -> Unit)? = null, + actionProgress: ((position: Long) -> Unit)? = null, actionSuccess: (file: File) -> Unit, actionFail: (msg: String) -> Unit, + actionCancel: (() -> Unit)? = null ): DownLoadUtils { this.actionGetTotal = actionGetTotal this.actionProgress = actionProgress this.actionSuccess = actionSuccess this.actionFail = actionFail - + this.actionCancel = actionCancel return this } @@ -278,7 +279,7 @@ class DownLoadUtils private constructor() { private fun doException(err: String) { runOnUiThread { if (downCallBack == null) { - actionFail.invoke(err) + actionFail?.invoke(err) } else { downCallBack?.fail(err) } @@ -304,7 +305,7 @@ class DownLoadUtils private constructor() { private fun doGetTotal(total: Long) { runOnUiThread { if (downCallBack == null) { - actionGetTotal.invoke(total) + actionGetTotal?.invoke(total) } else { downCallBack?.total(total) } @@ -315,7 +316,7 @@ class DownLoadUtils private constructor() { private fun doProgress(progress: Long) { runOnUiThread { if (downCallBack == null) { - actionProgress.invoke(progress) + actionProgress?.invoke(progress) } else { downCallBack?.progress(progress) } @@ -325,7 +326,7 @@ class DownLoadUtils private constructor() { private fun doCancel() { runOnUiThread { if (downCallBack == null) { - actionCancel.invoke() + actionCancel?.invoke() } else { downCallBack?.cancel() } diff --git a/app/src/main/res/drawable/shape_bid_detail_bg.xml b/app/src/main/res/drawable/shape_bid_detail_bg.xml new file mode 100644 index 0000000..14b34b2 --- /dev/null +++ b/app/src/main/res/drawable/shape_bid_detail_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_f4f8ff_cor6.xml b/app/src/main/res/drawable/shape_f4f8ff_cor6.xml new file mode 100644 index 0000000..005ab73 --- /dev/null +++ b/app/src/main/res/drawable/shape_f4f8ff_cor6.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_f6f6f6_cor10.xml b/app/src/main/res/drawable/shape_f6f6f6_cor10.xml new file mode 100644 index 0000000..0ce1d16 --- /dev/null +++ b/app/src/main/res/drawable/shape_f6f6f6_cor10.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_f6f6f6_cor25.xml b/app/src/main/res/drawable/shape_f6f6f6_cor25.xml new file mode 100644 index 0000000..e374ad8 --- /dev/null +++ b/app/src/main/res/drawable/shape_f6f6f6_cor25.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_f6f6f6_cor4.xml b/app/src/main/res/drawable/shape_f6f6f6_cor4.xml new file mode 100644 index 0000000..7d40a65 --- /dev/null +++ b/app/src/main/res/drawable/shape_f6f6f6_cor4.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_search_edit_bg.xml b/app/src/main/res/drawable/shape_search_edit_bg.xml new file mode 100644 index 0000000..9c5cab7 --- /dev/null +++ b/app/src/main/res/drawable/shape_search_edit_bg.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_search_option_tag.xml b/app/src/main/res/drawable/shape_search_option_tag.xml new file mode 100644 index 0000000..175f2a3 --- /dev/null +++ b/app/src/main/res/drawable/shape_search_option_tag.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_bottom_cor10.xml b/app/src/main/res/drawable/shape_white_bottom_cor10.xml new file mode 100644 index 0000000..1c65b38 --- /dev/null +++ b/app/src/main/res/drawable/shape_white_bottom_cor10.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_white_top_cor16.xml b/app/src/main/res/drawable/shape_white_top_cor16.xml new file mode 100644 index 0000000..2548501 --- /dev/null +++ b/app/src/main/res/drawable/shape_white_top_cor16.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_date_picker.xml b/app/src/main/res/layout/dialog_date_picker.xml new file mode 100644 index 0000000..12b85a5 --- /dev/null +++ b/app/src/main/res/layout/dialog_date_picker.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_download_attachment.xml b/app/src/main/res/layout/dialog_download_attachment.xml new file mode 100644 index 0000000..e630f83 --- /dev/null +++ b/app/src/main/res/layout/dialog_download_attachment.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_bid_detail.xml b/app/src/main/res/layout/fragment_bid_detail.xml new file mode 100644 index 0000000..b9b5573 --- /dev/null +++ b/app/src/main/res/layout/fragment_bid_detail.xml @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 6cfbf50..59c8da9 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -3,9 +3,11 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:background="@color/white"> @@ -112,7 +114,7 @@ android:layout_marginTop="@dimen/dp_10" android:background="@drawable/shape_white_top_cor20" android:paddingTop="@dimen/dp_17" - android:paddingBottom="@dimen/dp_40" + android:paddingBottom="@dimen/dp_20" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layout_constraintTop_toBottomOf="@id/tv_hot_title" app:spanCount="4" @@ -125,7 +127,7 @@ android:id="@+id/layout_content" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginTop="-65dp" + android:layout_marginTop="-45dp" android:paddingTop="@dimen/dp_45" app:layout_behavior="@string/appbar_scrolling_view_behavior"> @@ -183,6 +185,7 @@ android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginTop="@dimen/dp_12" + android:background="@color/windowBackground" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_bid_title"> diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml new file mode 100644 index 0000000..3869922 --- /dev/null +++ b/app/src/main/res/layout/fragment_search.xml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search_list.xml b/app/src/main/res/layout/fragment_search_list.xml new file mode 100644 index 0000000..e8d4d0c --- /dev/null +++ b/app/src/main/res/layout/fragment_search_list.xml @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_bid_attachment.xml b/app/src/main/res/layout/listitem_bid_attachment.xml new file mode 100644 index 0000000..02c6936 --- /dev/null +++ b/app/src/main/res/layout/listitem_bid_attachment.xml @@ -0,0 +1,40 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_bid_detail_contact.xml b/app/src/main/res/layout/listitem_bid_detail_contact.xml new file mode 100644 index 0000000..1856b81 --- /dev/null +++ b/app/src/main/res/layout/listitem_bid_detail_contact.xml @@ -0,0 +1,40 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_bid_detail_image.xml b/app/src/main/res/layout/listitem_bid_detail_image.xml new file mode 100644 index 0000000..a04aee3 --- /dev/null +++ b/app/src/main/res/layout/listitem_bid_detail_image.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_search_history.xml b/app/src/main/res/layout/listitem_search_history.xml new file mode 100644 index 0000000..30ea738 --- /dev/null +++ b/app/src/main/res/layout/listitem_search_history.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_search_hot_type.xml b/app/src/main/res/layout/listitem_search_hot_type.xml new file mode 100644 index 0000000..0b99cd5 --- /dev/null +++ b/app/src/main/res/layout/listitem_search_hot_type.xml @@ -0,0 +1,44 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_search_option_child.xml b/app/src/main/res/layout/listitem_search_option_child.xml new file mode 100644 index 0000000..e5fcd03 --- /dev/null +++ b/app/src/main/res/layout/listitem_search_option_child.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_search_option_parent.xml b/app/src/main/res/layout/listitem_search_option_parent.xml new file mode 100644 index 0000000..f2a9c29 --- /dev/null +++ b/app/src/main/res/layout/listitem_search_option_parent.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/listitem_search_recommend.xml b/app/src/main/res/layout/listitem_search_recommend.xml new file mode 100644 index 0000000..75a3972 --- /dev/null +++ b/app/src/main/res/layout/listitem_search_recommend.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/popup_search_options.xml b/app/src/main/res/layout/popup_search_options.xml new file mode 100644 index 0000000..d86e5cd --- /dev/null +++ b/app/src/main/res/layout/popup_search_options.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xxhdpi/ic_attachment_dialog_top_bg.png b/app/src/main/res/mipmap-xxhdpi/ic_attachment_dialog_top_bg.png new file mode 100644 index 0000000..d955acd Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_attachment_dialog_top_bg.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bid_detail_top_bg.png b/app/src/main/res/mipmap-xxhdpi/ic_bid_detail_top_bg.png new file mode 100644 index 0000000..5a4bae0 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bid_detail_top_bg.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bid_download.png b/app/src/main/res/mipmap-xxhdpi/ic_bid_download.png new file mode 100644 index 0000000..cf7599d Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bid_download.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bid_download_disable.png b/app/src/main/res/mipmap-xxhdpi/ic_bid_download_disable.png new file mode 100644 index 0000000..1ff88f6 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bid_download_disable.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bid_favorite.png b/app/src/main/res/mipmap-xxhdpi/ic_bid_favorite.png new file mode 100644 index 0000000..c4790c3 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bid_favorite.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bid_favorited.png b/app/src/main/res/mipmap-xxhdpi/ic_bid_favorited.png new file mode 100644 index 0000000..b8f083d Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bid_favorited.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bid_share.png b/app/src/main/res/mipmap-xxhdpi/ic_bid_share.png new file mode 100644 index 0000000..a71c080 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bid_share.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_bid_view.png b/app/src/main/res/mipmap-xxhdpi/ic_bid_view.png new file mode 100644 index 0000000..773f0e5 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_bid_view.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_clear_history.png b/app/src/main/res/mipmap-xxhdpi/ic_clear_history.png new file mode 100644 index 0000000..b816125 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_clear_history.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_clear_text.png b/app/src/main/res/mipmap-xxhdpi/ic_clear_text.png new file mode 100644 index 0000000..f53a031 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_clear_text.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_clear_text.webp b/app/src/main/res/mipmap-xxhdpi/ic_clear_text.webp deleted file mode 100644 index 967aa6b..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_clear_text.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_option_arrow_down.png b/app/src/main/res/mipmap-xxhdpi/ic_option_arrow_down.png new file mode 100644 index 0000000..fda054a Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_option_arrow_down.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_option_arrow_up.png b/app/src/main/res/mipmap-xxhdpi/ic_option_arrow_up.png new file mode 100644 index 0000000..cfb6c17 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_option_arrow_up.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_option_checked.png b/app/src/main/res/mipmap-xxhdpi/ic_option_checked.png new file mode 100644 index 0000000..28f9f85 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_option_checked.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_pdf_attachment.png b/app/src/main/res/mipmap-xxhdpi/ic_pdf_attachment.png new file mode 100644 index 0000000..05cda3a Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_pdf_attachment.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_phone_contacts.png b/app/src/main/res/mipmap-xxhdpi/ic_phone_contacts.png new file mode 100644 index 0000000..684ed03 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_phone_contacts.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_refresh2.png b/app/src/main/res/mipmap-xxhdpi/ic_refresh2.png new file mode 100644 index 0000000..6fc592a Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_refresh2.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_search_history.png b/app/src/main/res/mipmap-xxhdpi/ic_search_history.png new file mode 100644 index 0000000..9405c9b Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_search_history.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_search_hot_type.png b/app/src/main/res/mipmap-xxhdpi/ic_search_hot_type.png new file mode 100644 index 0000000..1081415 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_search_hot_type.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_search_recommend_keyword.png b/app/src/main/res/mipmap-xxhdpi/ic_search_recommend_keyword.png new file mode 100644 index 0000000..f40db55 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_search_recommend_keyword.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_search_top_bg.png b/app/src/main/res/mipmap-xxhdpi/ic_search_top_bg.png new file mode 100644 index 0000000..93cc37b Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_search_top_bg.png differ diff --git a/app/src/main/res/values-v31/themes.xml b/app/src/main/res/values-v31/themes.xml index b2acfc8..a83c8e7 100644 --- a/app/src/main/res/values-v31/themes.xml +++ b/app/src/main/res/values-v31/themes.xml @@ -1,6 +1,6 @@ - - -