Commit ccb1d111 authored by 赵鹏翔's avatar 赵鹏翔

Merge branch 'feature_v2.1_converse' into 'develop'

Feature v2.1 converse

See merge request !2
parents cbe26dab 004011b2
......@@ -4,6 +4,8 @@ plugins {
id 'kotlin-kapt'
}
apply from: '../versions.gradle'
android {
compileSdkVersion 31
buildToolsVersion "30.0.3"
......@@ -21,8 +23,8 @@ android {
applicationId "com.miya.fastcashier"
minSdkVersion 19
targetSdkVersion 31
versionCode 21
versionName "2.1"
versionCode VERSION_CODE.toInteger()
versionName VERSION_NAME.toString()
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
......@@ -48,6 +50,20 @@ android {
buildFeatures {
viewBinding true
}
android.applicationVariants.all { variant ->
variant.outputs.all { output ->
outputFileName = new File(output.outputFile.parent,
"${getAppChannel()}" + "_v" +
variant.versionName + "_" +
variant.versionCode + "_" +
variant.buildType.name + "_" +
"${buildTime()}" +
".apk"
).getName()
}
}
}
dependencies {
......@@ -86,4 +102,15 @@ dependencies {
implementation 'com.elvishew:xlog:1.10.1'
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
implementation 'com.contrarywind:Android-PickerView:4.1.9'
implementation 'com.guolindev.permissionx:permissionx:1.6.1'
}
static String buildTime() {
Date date = new Date()
String dates = date.format("yyyyMMddHHmm", TimeZone.getTimeZone("Asia/Shanghai"))
return dates
}
String getAppChannel() {
return project.channel
}
\ No newline at end of file
......@@ -2,9 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.miya.fastcashier">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".BaseApplication"
......@@ -12,6 +12,7 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.MiYaFastCashier.Dark"
android:supportsRtl="true">
<activity
android:name=".ui.LoginActivity"
......@@ -20,7 +21,6 @@
android:theme="@style/Theme.MiYaFastCashier.Light">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
......@@ -52,6 +52,12 @@
<activity
android:name=".ui.SearchOrderActivity"
android:theme="@style/Theme.MiYaFastCashier.Dark" />
<activity
android:name=".ui.SettingActivity"
android:exported="true" />
<activity
android:name=".ui.ResetAuthorizePasswordActivity"
android:exported="true" />
</application>
</manifest>
\ No newline at end of file
package com.miya.fastcashier
import android.app.Activity
import android.app.Application
import android.content.Context
import android.os.Bundle
import androidx.multidex.MultiDexApplication
import com.blankj.utilcode.util.LogUtils
import com.elvishew.xlog.LogConfiguration
import com.elvishew.xlog.LogLevel
import com.elvishew.xlog.LogUtils
import com.elvishew.xlog.XLog
import com.elvishew.xlog.printer.AndroidPrinter
import com.elvishew.xlog.printer.ConsolePrinter
......@@ -15,10 +13,15 @@ import com.elvishew.xlog.printer.Printer
import com.elvishew.xlog.printer.file.FilePrinter
import com.elvishew.xlog.printer.file.backup.NeverBackupStrategy
import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator
import com.miya.fastcashier.service.AccountService
import com.miya.fastcashier.utils.ContextUtils
import com.miya.fastcashier.utils.DateUtils
import com.miya.fastcashier.utils.DensityUtils
import com.miya.fastcashier.utils.LogFileUtils
import com.miya.fastcashier.utils.manage.OrderRecordManageKit
import com.miya.print.PrinterManager
import com.sdy.miya.moblie.component.pay.core.net.MiYaPayMobileApiClient
import com.sdy.miya.moblie.component.pay.core.net.MiyaHttpLoggingInterceptor
import com.sdy.miya.moblie.component.pay.core.utils.PayLogFileUtils
import com.tencent.mmkv.MMKV
import java.io.File
......@@ -26,8 +29,16 @@ import java.util.*
class BaseApplication : MultiDexApplication() {
companion object {
private lateinit var instance: BaseApplication
fun getApplication() = instance
}
override fun onCreate() {
super.onCreate()
instance = this
ContextUtils.init(this)
//打印机初始化
PrinterManager.getInstance().init(this)
......@@ -77,6 +88,26 @@ class BaseApplication : MultiDexApplication() {
.absolutePath
+ File.separator + "payLog"
)
var loggingInterceptor: MiyaHttpLoggingInterceptor? = null
try {
loggingInterceptor = MiyaHttpLoggingInterceptor { message ->
if (!LogFileUtils.isProhibitWrite) {
LogFileUtils.writeLog(
ContextUtils.getContext(),
DateUtils.getDateStringByTimeStamp(System.currentTimeMillis())
.toString() + " " + message + "\n"
)
}
if (BuildConfig.DEBUG) {
LogUtils.d("fastcashier", message)
}
}
loggingInterceptor.level = MiyaHttpLoggingInterceptor.Level.BODY
} catch (ex: Exception) {
ex.printStackTrace()
}
MiYaPayMobileApiClient.init(true, loggingInterceptor)
}
private fun screenAdapt() {
......@@ -112,4 +143,11 @@ class BaseApplication : MultiDexApplication() {
})
}
fun resetConfig() {
MMKV.defaultMMKV().clearAll()
//清除本地订单昨天的流水信息
OrderRecordManageKit.clearOrderDataYeaterday()
//清除本地个人信息
AccountService.clear()
}
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ import android.text.TextUtils
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.miya.fastcashier.dao.DatabaseKeeper
import com.miya.fastcashier.service.AccountService
import com.miya.fastcashier.utils.isEmpty
import com.sdy.miya.moblie.component.pay.platform.bean.PayServiceResponse
import java.lang.RuntimeException
......@@ -33,6 +34,7 @@ data class ViewPayOrderData(
val oriOrderPrice: String? = null,//订单原价
val refundPrice: String? = null,//退款价格
val payQrCode: String? = null,//支付条码
val userName: String? = null
) {
companion object {
......@@ -58,11 +60,35 @@ data class ViewPayOrderData(
refundOrderNo = payServiceResponse.refundOrderNo,
oriOrderPrice = payServiceResponse.oriOrderPrice,
refundPrice = payServiceResponse.refundPrice,
payQrCode = payServiceResponse.payQrCode
payQrCode = payServiceResponse.payQrCode,
userName = AccountService.getUserName(),
)
}
fun transformPayServiceResponse(orderData: ViewPayOrderData): PayServiceResponse {
var payServiceResponse = PayServiceResponse()
payServiceResponse.shopTradeNo = orderData.orderNo
payServiceResponse.tradStatus = orderData.tradStatus
payServiceResponse.chanelSerialNumber = orderData.tradeNo
payServiceResponse.tradPrice = orderData.tradPrice
payServiceResponse.chanelTag = orderData.chanelTag
payServiceResponse.buyerId = orderData.buyerId
payServiceResponse.couponMessage = orderData.couponMessage
payServiceResponse.chanelOrderTradeTime = orderData.chanelOrderTradeTime
payServiceResponse.miyaResponseTime = orderData.miyaResponseTime
payServiceResponse.miyaOrderDesc = orderData.miyaOrderDesc
payServiceResponse.vipShopTag = orderData.vipShopTag
payServiceResponse.buyerAccount = orderData.buyerAccount
payServiceResponse.memberCardNumber = orderData.memberCardNumber
payServiceResponse.platformName = orderData.platformName
payServiceResponse.refundOrderNo = orderData.refundOrderNo
payServiceResponse.oriOrderPrice = orderData.oriOrderPrice
payServiceResponse.refundPrice = orderData.refundPrice
payServiceResponse.payQrCode = orderData.payQrCode
return payServiceResponse
}
fun insert(payServiceResponse: PayServiceResponse) {
if (TextUtils.isEmpty(payServiceResponse.shopTradeNo)) {
return
......
package com.miya.fastcashier.config
interface IntentExtra {
companion object {
const val KEY_EXTRA_DATA = "extra_data"
const val KEY_EXTRA_TYPE = "extra_type"
}
}
\ No newline at end of file
......@@ -8,7 +8,7 @@ import com.miya.fastcashier.utils.MiYaPayPlantformPayWayEnum
@Dao
interface PayDataDao {
companion object{
companion object {
const val NUM_OF_SINGLE_PAGE = 10
}
......@@ -30,6 +30,12 @@ interface PayDataDao {
beginIndex: Int
): MutableList<ViewPayOrderData>
@Query("SELECT * FROM pay_data WHERE chanelTag =:payType ORDER BY id DESC ")
fun queryAllWithType(payType: String): MutableList<ViewPayOrderData>
@Query("SELECT * FROM pay_data WHERE chanelTag =:payType AND userName=:userName ORDER BY id DESC ")
fun queryAllWithTypeAndName(payType: String,userName:String): MutableList<ViewPayOrderData>
@Query("SELECT COUNT(*) FROM pay_data WHERE chanelTag =:payType")
fun sizeOfType(payType: String): Int
......
......@@ -5,9 +5,12 @@ import androidx.room.RoomDatabase
import com.miya.fastcashier.beans.ViewPayOrderData
import androidx.room.Room
import com.miya.fastcashier.utils.ContextUtils
import androidx.sqlite.db.SupportSQLiteDatabase
import androidx.room.migration.Migration
@Database(entities = [ViewPayOrderData::class],exportSchema=false, version = 1)
@Database(entities = [ViewPayOrderData::class], exportSchema = false, version = 2)
abstract class PayDatabase : RoomDatabase() {
abstract fun payDataDao(): PayDataDao
}
......@@ -16,12 +19,18 @@ abstract class PayDatabase : RoomDatabase() {
class DatabaseKeeper {
companion object {
private val DATABASE_NAME = "pay_data"
val payDatabase: PayDatabase by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
Room.databaseBuilder(
ContextUtils.getContext(),
PayDatabase::class.java, "pay_data"
).build()
Room.databaseBuilder(ContextUtils.getContext(), PayDatabase::class.java, DATABASE_NAME)
.addMigrations(MIGRATION_1_2)
.build()
}
val MIGRATION_1_2: Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("alter table pay_data add userName Text")
}
}
}
}
package com.miya.fastcashier.repository
import android.text.TextUtils
import android.util.Log
import androidx.annotation.WorkerThread
import com.blankj.utilcode.util.LogUtils
import com.miya.fastcashier.service.AccountService
......@@ -227,11 +228,16 @@ object PayRepository {
return miYaMobilePayResult.payServiceResponse
} else if (!TextUtils.isEmpty(miYaMobilePayResult.errorMsg)) {
throw RuntimeException(miYaMobilePayResult.errorMsg)
} else if (miYaMobilePayResult.payServiceResponse != null && !TextUtils.isEmpty(
miYaMobilePayResult.payServiceResponse.chanelErrorMsg
)
} else if (miYaMobilePayResult.payServiceResponse != null &&
!TextUtils.isEmpty(miYaMobilePayResult.payServiceResponse.chanelErrorMsg)
) {
throw RuntimeException(miYaMobilePayResult.payServiceResponse.chanelErrorMsg)
if ("[微信]订单支付成功(有退款)".equals(miYaMobilePayResult.payServiceResponse.chanelErrorMsg)) {
//微信多次退款会有该提示,视为查询成功状态
return miYaMobilePayResult.payServiceResponse
} else {
throw RuntimeException(miYaMobilePayResult.payServiceResponse.chanelErrorMsg)
}
} else {
throw RuntimeException("支付异常!")
}
......
......@@ -3,24 +3,39 @@ package com.miya.fastcashier.service
import com.miya.fastcashier.beans.SelfCashierAccountInfo
import com.sdy.miya.moblie.component.pay.platform.bean.MiyaOrderRefundResponse
object AccountService{
object AccountService {
private var selfCashierAccountInfo : SelfCashierAccountInfo? = null;
private var userName : String? = ""
private var selfCashierAccountInfo: SelfCashierAccountInfo? = null;
private var userName: String? = ""
private var accountPassword: String? = ""
fun setAccountInfo(selfCashierAccountInfo : SelfCashierAccountInfo?){
this.selfCashierAccountInfo = selfCashierAccountInfo
fun setAccountInfo(selfCashierAccountInfo: SelfCashierAccountInfo?) {
this.selfCashierAccountInfo = selfCashierAccountInfo
}
fun getAccountInfo(): SelfCashierAccountInfo? {
return selfCashierAccountInfo;
}
fun setUserName(userName:String){
fun setUserName(userName: String) {
this.userName = userName
}
fun getUserName():String{
fun getUserName(): String {
return userName.toString();
}
fun getAccountPassword(): String {
return accountPassword.toString();
}
fun setAccountPassword(accountPassword: String) {
this.accountPassword = accountPassword
}
fun clear(){
selfCashierAccountInfo = null
userName = ""
accountPassword = ""
}
}
\ No newline at end of file
package com.miya.fastcashier.service
import android.text.TextUtils
import com.blankj.utilcode.util.LogUtils
import com.esc.LogUlit
import com.miya.fastcashier.beans.SelfCashierAccountInfo
import com.miya.fastcashier.beans.ViewOrderStatisticsInfo
import com.miya.fastcashier.utils.DateUtils
import com.miya.fastcashier.utils.MiYaPayPlantformPayWayEnum
import com.miya.fastcashier.utils.StringPriceFormat
import com.miya.fastcashier.utils.isEmpty
import com.miya.fastcashier.utils.manage.OrderRecordManageKit
import com.miya.print.BuildConfig
import com.miya.print.IPrinter
import com.miya.print.PrinterManager
......@@ -22,7 +25,6 @@ object PrintService {
private var payServiceResponse: PayServiceResponse? = null;
/**
* 退款
*/
......@@ -41,6 +43,48 @@ object PrintService {
printer.endPrint()
}
/**
* 查询订单单项打印
*/
fun printSearchOrder(
selfCashierAccountInfo: SelfCashierAccountInfo,
payServiceResponse: PayServiceResponse,
isRefund: Boolean
) {
if (isRefund) {
refundPrint(selfCashierAccountInfo, payServiceResponse)
} else {
val printer = PrinterManager.getInstance().printer
printer.beginPrint()
//检查打印机状态
printer.printerStatus
printer.set58mm()
if (BuildConfig.DEBUG) {
printCashier(
printer,
payServiceResponse,
selfCashierAccountInfo,
OrderRecordManageKit.getSerialNoByOrderNo(payServiceResponse.shopTradeNo))
} else {
printCashier(
printer,
payServiceResponse,
selfCashierAccountInfo,
OrderRecordManageKit.getSerialNoByOrderNo(payServiceResponse.shopTradeNo)
)
printCustomer(
printer,
payServiceResponse,
selfCashierAccountInfo,
OrderRecordManageKit.getSerialNoByOrderNo(payServiceResponse.shopTradeNo)
)
}
printer.feedPaper()
printer.endPrint()
}
}
/**
* 打印上一单
*/
......@@ -63,7 +107,8 @@ object PrintService {
this.payServiceResponse = payServiceResponse
//记录流水号,退款要用
setSerialNoByOrderNo(payServiceResponse.shopTradeNo, getSerialNumber())
val serialNumber = OrderRecordManageKit.getSerialNumber()
OrderRecordManageKit.setSerialNoByOrderNo(payServiceResponse.shopTradeNo, serialNumber)
val printer = PrinterManager.getInstance().printer
printer.beginPrint()
......@@ -71,10 +116,10 @@ object PrintService {
printer.printerStatus
printer.set58mm()
// if (BuildConfig.DEBUG) {
// printCashier(printer, payServiceResponse, selfCashierAccountInfo)
// printCashier(printer, payServiceResponse, selfCashierAccountInfo, serialNumber)
// } else {
printCashier(printer, payServiceResponse, selfCashierAccountInfo)
printCustomer(printer, payServiceResponse, selfCashierAccountInfo)
printCashier(printer, payServiceResponse, selfCashierAccountInfo, serialNumber)
printCustomer(printer, payServiceResponse, selfCashierAccountInfo, serialNumber)
// }
printer.feedPaper()
printer.endPrint()
......@@ -204,7 +249,8 @@ object PrintService {
private fun printCashier(
printer: IPrinter,
payServiceResponse: PayServiceResponse,
selfCashierAccountInfo: SelfCashierAccountInfo
selfCashierAccountInfo: SelfCashierAccountInfo,
serialNumber: String
) {
val shopInfo = selfCashierAccountInfo.shopInfo
......@@ -223,7 +269,7 @@ object PrintService {
)
printer.printText(Page58MmPrintUtils.printDivideLineString())
printer.printText("日期/时间:${DateUtils.format18(Date())}")
printer.printText("流水号:${getSerialNumber()}")
printer.printText("流水号:${serialNumber}")
printer.printText("商户订单号:")
printer.printText(payServiceResponse.shopTradeNo)
printer.printText("支付平台交易号:")
......@@ -274,7 +320,8 @@ object PrintService {
private fun printCustomer(
printer: IPrinter,
payServiceResponse: PayServiceResponse,
selfCashierAccountInfo: SelfCashierAccountInfo
selfCashierAccountInfo: SelfCashierAccountInfo,
serialNumber: String
) {
val shopInfo = selfCashierAccountInfo.shopInfo
printer.printText(IPrinter.ALIGN_CENTER, 3, shopInfo.storeName, true)
......@@ -294,7 +341,7 @@ object PrintService {
)
printer.printText(Page58MmPrintUtils.printDivideLineString())
printer.printText("日期/时间:${DateUtils.format18(Date())}")
printer.printText("流水号:${getSerialNumber()}")
printer.printText("流水号:${serialNumber}")
printer.printText("商户订单号:")
printer.printText(payServiceResponse.shopTradeNo)
printer.printText("支付平台交易号:")
......@@ -360,7 +407,7 @@ object PrintService {
)
printer.printText(Page58MmPrintUtils.printDivideLineString())
printer.printText("日期/时间:${DateUtils.format18(Date())}")
printer.printText("流水号:${getSerialNoByOrderNo(payServiceResponse.shopTradeNo)}")
printer.printText("流水号:${OrderRecordManageKit.getSerialNoByOrderNo(payServiceResponse.shopTradeNo)}")
printer.printText("商户订单号:")
printer.printText(payServiceResponse.shopTradeNo)
printer.printText("支付平台交易号:")
......@@ -433,7 +480,7 @@ object PrintService {
)
printer.printText(Page58MmPrintUtils.printDivideLineString())
printer.printText("日期/时间:${DateUtils.format18(Date())}")
printer.printText("流水号:${getSerialNoByOrderNo(payServiceResponse.shopTradeNo)}")
printer.printText("流水号:${OrderRecordManageKit.getSerialNoByOrderNo(payServiceResponse.shopTradeNo)}")
printer.printText("商户订单号:")
printer.printText(payServiceResponse.refundOrderNo)
printer.printText("支付平台交易号:")
......@@ -475,30 +522,4 @@ object PrintService {
}
printer.printText("\n\n")
}
private fun getSerialNumber(): String {
val today = DateUtils.format8(Date())
val kv = MMKV.defaultMMKV()
val no = kv.getInt(today, 0).toString()
var listNo = no
for (index in 1..(5 - no.length)) {
listNo = "0$listNo"
}
return listNo;
}
/**
* 根据订单号获取流水号
* //todo 定期删除机制
*/
private fun getSerialNoByOrderNo(orderNo: String): String {
return MMKV.defaultMMKV().getString(orderNo, "00000").toString()
}
private fun setSerialNoByOrderNo(orderNo: String, serialNo: String) {
MMKV.defaultMMKV().putString(orderNo, serialNo);
}
}
\ No newline at end of file
......@@ -20,11 +20,13 @@ import com.miya.fastcashier.R.mipmap.ic_wxpay
import com.miya.fastcashier.databinding.ActivityAliPayCodeBinding
import com.miya.fastcashier.databinding.ActivityPayCodeBinding
import com.miya.fastcashier.databinding.ActivityPriceInputBinding
import com.miya.fastcashier.service.PrintService
import com.miya.fastcashier.ui.dialog.PayChooseDialog
import com.miya.fastcashier.utils.CenterToasty
import com.miya.fastcashier.utils.DateUtils
import com.miya.fastcashier.utils.StringPriceFormat
import com.miya.fastcashier.utils.clickWithTrigger
import com.miya.fastcashier.utils.manage.OrderRecordManageKit
import com.miya.fastcashier.viewmodel.PayViewModel
import com.miya.print.utils.BitmapUtils
import com.sdy.miya.moblie.component.pay.platform.bean.PayServiceResponse
......@@ -83,11 +85,7 @@ class AliPayCodeActivity : AppCompatActivity() {
result.getOrNull().also {
it?.let { it1 ->
//自增流水
val today = DateUtils.format8(Date())
var no = kv.getInt(today,0);
kv.putInt(DateUtils.format8(Date()),++no)
OrderRecordManageKit.setSerialNumber()
val intent = Intent()
intent.setClass(this@AliPayCodeActivity, PayResultActivity::class.java)
......
package com.miya.fastcashier.ui
import android.Manifest
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.Editable
......@@ -11,21 +13,30 @@ import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.ToastUtils
import com.miya.fastcashier.databinding.ActivityLoginBinding
import com.miya.fastcashier.service.AccountService
import com.miya.fastcashier.utils.clickWithTrigger
import com.miya.fastcashier.utils.withTrigger
import com.miya.fastcashier.viewmodel.LoginViewModel
import com.permissionx.guolindev.PermissionX
import com.permissionx.guolindev.callback.RequestCallback
import com.tencent.mmkv.MMKV
class LoginActivity : AppCompatActivity() {
private lateinit var loginViewModel: LoginViewModel
private lateinit var binding: ActivityLoginBinding
companion object{
fun start(context: Context, flags: Int) {
val intent = Intent(context, LoginActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or flags
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLoginBinding.inflate(layoutInflater)
......@@ -55,8 +66,8 @@ class LoginActivity : AppCompatActivity() {
result.getOrNull().also {
it?.let { it1 ->
kv.encode("username",username.text.toString())
kv.encode("password",password.text.toString())
kv.encode("username", username.text.toString())
kv.encode("password", password.text.toString())
AccountService.setUserName(username.text.toString())
AccountService.setAccountInfo(it1)
......@@ -92,7 +103,7 @@ class LoginActivity : AppCompatActivity() {
}
setOnEditorActionListener { _, actionId, _ ->
when (actionId) {
EditorInfo.IME_ACTION_NEXT ->{
EditorInfo.IME_ACTION_NEXT -> {
password.requestFocus()
password.text?.let { password.setSelection(it.length) };
}
......@@ -111,7 +122,7 @@ class LoginActivity : AppCompatActivity() {
setOnEditorActionListener { _, actionId, _ ->
when (actionId) {
EditorInfo.IME_ACTION_DONE ->{
EditorInfo.IME_ACTION_DONE -> {
loading.visibility = View.VISIBLE;
loginViewModel.login(
username.text.toString(),
......@@ -123,26 +134,45 @@ class LoginActivity : AppCompatActivity() {
}
binding.login.clickWithTrigger {
loading.visibility = View.VISIBLE
loginViewModel.login(username.text.toString(), password.text.toString())
checkPermissions()
}
}
kv.decodeString("username")?.let {
username.setText(it)
}
kv.decodeString("username")?.let {
username.setText(it)
}
kv.decodeString("password")?.let {
password.setText(it)
}
if(!TextUtils.isEmpty(username.text)
&& !TextUtils.isEmpty(password.text)){
if (!TextUtils.isEmpty(username.text)
&& !TextUtils.isEmpty(password.text)
) {
loading.visibility = View.VISIBLE;
loginViewModel.login(username.text.toString(), password.text.toString())
}
}
private fun checkPermissions() {
PermissionX.init(this)
.permissions(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
.request(RequestCallback { allGranted: Boolean, grantedList: List<String?>?, deniedList: List<String?>? ->
if (allGranted) {
binding.loading.visibility = View.VISIBLE
loginViewModel.login(
binding.username.text.toString(),
binding.password.text.toString()
)
} else {
ToastUtils.showShort("请检查权限后重试")
}
})
}
/**
* Extension function to simplify setting an afterTextChanged action to EditText components.
*/
......
......@@ -5,6 +5,7 @@ import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Gravity
import android.widget.Toast
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.miya.fastcashier.R
......@@ -12,11 +13,14 @@ import com.miya.fastcashier.databinding.ActivityLoginBinding
import com.miya.fastcashier.databinding.ActivityMainBinding
import com.miya.fastcashier.service.AccountService
import com.miya.fastcashier.service.PrintService
import com.miya.fastcashier.ui.dialog.AuthorizePasswordInputDialog
import com.miya.fastcashier.ui.dialog.CommonDialog
import com.miya.fastcashier.ui.dialog.MessageDialog
import com.miya.fastcashier.utils.CenterToasty
import com.miya.fastcashier.utils.DateSelectHelper
import com.miya.fastcashier.utils.clickWithTrigger
import com.miya.fastcashier.utils.manage.AccountPasswordManageKit
import com.miya.fastcashier.utils.manage.OrderRecordManageKit
import com.miya.fastcashier.viewmodel.MainViewModel
import com.sdy.miya.moblie.component.pay.platform.bean.PayServiceResponse
import com.tencent.mmkv.MMKV
......@@ -26,7 +30,6 @@ import java.util.*
class MainActivity : BaseActivity() {
//退出登录 二次确认弹窗
private var alertDialog: CommonDialog? = null
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: MainViewModel
private var dateSelectHelper: DateSelectHelper? = null
......@@ -40,7 +43,7 @@ class MainActivity : BaseActivity() {
val llPay = binding.llPay
val llRefund = binding.llRefund
val tvPrintLast = binding.tvPrintLast
val ivLoginOut = binding.ivLoginOut
val ivSetting = binding.ivSetting
val tvStoreName = binding.tvStoreName
val tvSlog = binding.tvSlog
......@@ -48,14 +51,10 @@ class MainActivity : BaseActivity() {
tvSlog.text = AccountService.getUserName()
llPay.clickWithTrigger {
val intent = Intent()
intent.setClass(this@MainActivity, PriceInputActivity::class.java)
startActivity(intent)
PriceInputActivity.start(this@MainActivity)
}
llRefund.clickWithTrigger {
val intent = Intent()
intent.setClass(this@MainActivity, RefundActivity::class.java)
startActivity(intent)
toRefund()
}
tvPrintLast.clickWithTrigger {
try {
......@@ -69,8 +68,8 @@ class MainActivity : BaseActivity() {
startActivity(intent)
}
ivLoginOut.clickWithTrigger {
loginOut()
ivSetting.clickWithTrigger {
SettingActivity.start(this@MainActivity)
}
binding.llStatistic.clickWithTrigger {
......@@ -101,8 +100,23 @@ class MainActivity : BaseActivity() {
}
}
initData()
checkAccountPassword()
OrderRecordManageKit.clearOrderDataYeaterday()
}
private fun toRefund() {
val FRAGMENT_TAG = "Authorize_Password"
val fm: FragmentManager = getSupportFragmentManager()
val oldFrag = fm.findFragmentByTag(FRAGMENT_TAG)
if (oldFrag != null) {
fm.beginTransaction().remove(oldFrag).commitAllowingStateLoss()
}
AuthorizePasswordInputDialog.newInstance().show(fm, FRAGMENT_TAG)
}
private fun checkAccountPassword() {
AccountPasswordManageKit.getInstance().checkAccountPassword(this)
}
private fun initData() {
......@@ -125,37 +139,6 @@ class MainActivity : BaseActivity() {
})
}
private fun loginOut() {
if (alertDialog == null || !alertDialog!!.isShowing) {
alertDialog = CommonDialog(this)
alertDialog!!.setCustomMessage(getString(R.string.app_text_login_out))
.setNegativeStr(getString(R.string.cancel))
.setPositiveStr(getString(R.string.text_login_out_sure))
.setMessageGravity(Gravity.CENTER_HORIZONTAL)
.setOnClickListener(object : CommonDialog.OnDialogClickListener {
override fun onNegativeClick() {
alertDialog!!.dismiss()
alertDialog = null
}
override fun onPositiveClick() {
alertDialog!!.dismiss()
alertDialog = null
run {
MMKV.defaultMMKV().clearAll()
AccountService.setAccountInfo(null)
val intent = Intent()
intent.setClass(this@MainActivity,
LoginActivity::class.java)
startActivity(intent)
finish()
}
}
})
.show()
}
}
override fun onDestroy() {
dateSelectHelper?.dismiss()
super.onDestroy()
......
......@@ -6,10 +6,12 @@ import android.view.KeyEvent
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import com.miya.fastcashier.databinding.ActivityPayBinding
import com.miya.fastcashier.service.PrintService
import com.miya.fastcashier.utils.CenterToasty
import com.miya.fastcashier.utils.DateUtils
import com.miya.fastcashier.utils.ScanGunKeyEventHelper
import com.miya.fastcashier.utils.clickWithTrigger
import com.miya.fastcashier.utils.manage.OrderRecordManageKit
import com.miya.fastcashier.viewmodel.PayViewModel
import com.tencent.mmkv.MMKV
import java.util.*
......@@ -24,7 +26,6 @@ class PayActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val kv = MMKV.defaultMMKV()
binding = ActivityPayBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(this).get(PayViewModel::class.java)
......@@ -39,11 +40,7 @@ class PayActivity : BaseActivity() {
it.message?.let { it1 -> CenterToasty.error(this, it1, Toast.LENGTH_LONG).show() }
}
payResult.onSuccess {
//自增流水
val today = DateUtils.format8(Date())
var no = kv.getInt(today, 0);
kv.putInt(DateUtils.format8(Date()), ++no)
OrderRecordManageKit.setSerialNumber()
val intent = Intent()
intent.setClass(this@PayActivity, PayResultActivity::class.java)
......
......@@ -3,16 +3,28 @@ package com.miya.fastcashier.ui
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.Gravity
import android.view.View
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import com.miya.fastcashier.R
import com.miya.fastcashier.config.IntentExtra
import com.miya.fastcashier.databinding.ActivityPriceInputBinding
import com.miya.fastcashier.service.AccountService
import com.miya.fastcashier.ui.dialog.CommonDialog
import com.miya.fastcashier.ui.dialog.MessageDialog
import com.miya.fastcashier.ui.dialog.PayChooseDialog
import com.miya.fastcashier.ui.dialog.PayChooseDialog.GeneratePayCodeClickListener
import com.miya.fastcashier.utils.CenterToasty
import com.miya.fastcashier.utils.StringPriceFormat
import com.miya.fastcashier.utils.WordUtil
import com.miya.fastcashier.utils.clickWithTrigger
import com.miya.fastcashier.viewmodel.PayViewModel
import com.miya.fastcashier.widget.DecimalKeyboard.DELETE
import com.miya.fastcashier.widget.DecimalKeyboard.DOT
import com.sdy.miya.moblie.component.pay.platform.bean.PayServiceResponse
import com.tencent.mmkv.MMKV
import java.math.BigDecimal
......@@ -20,8 +32,25 @@ class PriceInputActivity : BaseActivity() {
private lateinit var viewModel: PayViewModel
private lateinit var binding: ActivityPriceInputBinding
private var payChooseDialog: PayChooseDialog? = null;
private var payChooseDialog: PayChooseDialog? = null
private var alertDialog: CommonDialog? = null
private lateinit var payServiceResponse: PayServiceResponse
companion object {
const val PRICEINPUT_TYPE_COLLECTION = 1
const val PRICEINPUT_TYPE_CREFUND = 2
fun start(context: BaseActivity) {
start(context, PRICEINPUT_TYPE_COLLECTION, null)
}
fun start(context: BaseActivity, type: Int, payServiceResponse: PayServiceResponse?) {
val intent = Intent(context, PriceInputActivity::class.java)
intent.putExtra(IntentExtra.KEY_EXTRA_DATA, payServiceResponse)
intent.putExtra(IntentExtra.KEY_EXTRA_TYPE, type)
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......@@ -30,17 +59,44 @@ class PriceInputActivity : BaseActivity() {
setContentView(binding.root)
viewModel = ViewModelProvider(this).get(PayViewModel::class.java)
val tvGeneratePayCode = binding.tvGeneratePayCode
val tvScanPayCode = binding.tvScanPayCode
val llBack = binding.llBack
val etPrice = binding.etPrice
val numKeyboard = binding.numKeyboard
initView()
initListener()
}
private fun initView() {
val type = intent.getIntExtra(IntentExtra.KEY_EXTRA_TYPE, PRICEINPUT_TYPE_COLLECTION)
when (type) {
PRICEINPUT_TYPE_COLLECTION -> {
binding.tvTitle.text = "收款"
binding.tvPriceText.text = "收款金额"
binding.etPrice.setHint("输入收款金额")
binding.tvRefundPriceTotal.visibility = View.GONE
binding.tvScanPayCode.visibility = View.VISIBLE
binding.tvGeneratePayCode.visibility = View.VISIBLE
binding.tvRefund.visibility = View.GONE
}
PRICEINPUT_TYPE_CREFUND -> {
binding.tvTitle.text = "退款"
binding.tvPriceText.text = "订单金额"
binding.etPrice.setHint("输入退款金额")
binding.tvRefundPriceTotal.visibility = View.VISIBLE
this.payServiceResponse =
intent.getSerializableExtra(IntentExtra.KEY_EXTRA_DATA) as PayServiceResponse
binding.tvRefundPriceTotal.text =
"¥${StringPriceFormat.transStringPriceToDecimalString(payServiceResponse.tradPrice)}"
binding.tvScanPayCode.visibility = View.GONE
binding.tvGeneratePayCode.visibility = View.GONE
binding.tvRefund.visibility = View.VISIBLE
}
}
}
tvScanPayCode.clickWithTrigger {
private fun initListener() {
binding.tvScanPayCode.clickWithTrigger {
val price = etPrice.text
if(TextUtils.isEmpty(price)){
CenterToasty.error(this,"请输入金额!",Toast.LENGTH_LONG).show()
val price = binding.etPrice.text
if (TextUtils.isEmpty(price)) {
CenterToasty.error(this, "请输入金额!", Toast.LENGTH_LONG).show()
return@clickWithTrigger
}
......@@ -48,59 +104,64 @@ class PriceInputActivity : BaseActivity() {
intent.setClass(this@PriceInputActivity, PayActivity::class.java)
intent.putExtra("price", price)
startActivity(intent)
}
tvGeneratePayCode.clickWithTrigger {
binding.tvGeneratePayCode.clickWithTrigger {
if (null == payChooseDialog) {
payChooseDialog = PayChooseDialog(this)
payChooseDialog!!.setGeneratePayCodeClickListener(object :
GeneratePayCodeClickListener {
override fun choose(payType: String) {
showProgressDialog("生成付款码")
viewModel.generatePayCode(etPrice.text.toString(),payType)
viewModel.generatePayCode(binding.etPrice.text.toString(), payType)
}
})
}
payChooseDialog!!.show()
}
llBack.clickWithTrigger { finish() }
binding.llBack.clickWithTrigger { finish() }
numKeyboard.setKeyboardClickListener {
binding.numKeyboard.setKeyboardClickListener {
when (it) {
DELETE -> {
if (TextUtils.isEmpty(etPrice.text.toString())) {
if (TextUtils.isEmpty(binding.etPrice.text.toString())) {
return@setKeyboardClickListener
}
var currentCode: String = etPrice.text.toString()
var currentCode: String = binding.etPrice.text.toString()
currentCode = if (currentCode.length <= 1) {
""
} else {
currentCode.substring(0, currentCode.length - 1)
}
etPrice.setText(currentCode)
binding.etPrice.setText(currentCode)
if (binding.tvInvalidRefundPrice.visibility == View.VISIBLE) {
binding.tvInvalidRefundPrice.visibility = View.GONE
}
}
DOT -> {
var currentCode: String = etPrice.text.toString()
var currentCode: String = binding.etPrice.text.toString()
if (!currentCode.contains(".") && !TextUtils.isEmpty(currentCode)) {
currentCode += "."
etPrice.setText(currentCode)
binding.etPrice.setText(currentCode)
} else {
CenterToasty.error(this, "金额格式有误!", Toast.LENGTH_SHORT).show()
}
}
else -> {
var currentCode: String = etPrice.text.toString()
var currentCode: String = binding.etPrice.text.toString()
if (currentCode.contains(".")) {
val tmp =
currentCode.substring(currentCode.indexOf("."), currentCode.length - 1)
currentCode.substring(
currentCode.indexOf("."),
currentCode.length - 1
)
if (tmp.length < 2) {
if (BigDecimal(currentCode + it).compareTo(BigDecimal.ZERO) == 0 && tmp.length == 1) {
CenterToasty.error(this, "金额不能为0!", Toast.LENGTH_SHORT).show()
} else {
currentCode += it
etPrice.text = currentCode
binding.etPrice.text = currentCode
}
} else {
CenterToasty.error(this, "金额最多设置2位小数!", Toast.LENGTH_SHORT).show()
......@@ -110,10 +171,11 @@ class PriceInputActivity : BaseActivity() {
CenterToasty.error(this, "第二位不能输入0!", Toast.LENGTH_SHORT).show()
} else {
if (BigDecimal(currentCode + it).compareTo(BigDecimal("99999")) == 1) {
CenterToasty.error(this, "金额不能超过99999!", Toast.LENGTH_SHORT).show()
CenterToasty.error(this, "金额不能超过99999!", Toast.LENGTH_SHORT)
.show()
} else {
currentCode += it
etPrice.text = currentCode
binding.etPrice.text = currentCode
}
}
}
......@@ -125,16 +187,18 @@ class PriceInputActivity : BaseActivity() {
dismissProgressDialog()
result.getOrElse {
it.message?.let { it1 -> CenterToasty.error(this, it1, Toast.LENGTH_LONG).show() }
it.message?.let { it1 ->
CenterToasty.error(this, it1, Toast.LENGTH_LONG).show()
}
return@observe
}
result.getOrNull().also {
it?.let { it1 ->
val intent = Intent()
if ("1" == it1.chanelTag){
if ("1" == it1.chanelTag) {
intent.setClass(this@PriceInputActivity, WxPayCodeActivity::class.java)
}else{
} else {
intent.setClass(this@PriceInputActivity, AliPayCodeActivity::class.java)
}
intent.putExtra("payServiceResponse", it1)
......@@ -142,10 +206,85 @@ class PriceInputActivity : BaseActivity() {
}
}
})
viewModel.refundLiveData.observe(this, { payResult ->
payResult.onFailure {
dismissProgressDialog()
it.message?.let { it1 ->
if(it1.contains("大于可退金额")){
CenterToasty.error(this, "本次退款金额大于可退金额!", Toast.LENGTH_LONG).show()
}else{
CenterToasty.error(this, it1, Toast.LENGTH_LONG).show()
}
}
}
payResult.onSuccess {
dismissProgressDialog()
CenterToasty.success(this, "退款成功!!", Toast.LENGTH_LONG).show()
finish()
}
})
binding.tvRefund.clickWithTrigger {
val price = binding.etPrice.text.toString()
if (TextUtils.isEmpty(price)) {
CenterToasty.error(this, "退款金额不能为空!", Toast.LENGTH_SHORT).show()
return@clickWithTrigger
}
val priceYuan2Fen = StringPriceFormat.transStringYuan2Fen(price)
if (priceYuan2Fen.toDouble() > payServiceResponse.tradPrice.toDouble()) {
binding.tvInvalidRefundPrice.visibility = View.VISIBLE
return@clickWithTrigger
}
doubleRefundConfirm(price)
}
}
/**
* 二次退款确认
*/
private fun doubleRefundConfirm(refundPrice: String) {
var content: String = getString(R.string.text_refund_amount, refundPrice)
if (null == alertDialog) {
alertDialog = CommonDialog(this)
}
alertDialog!!.setCustomMessage(
WordUtil.matcherDiscolor(
this,
R.color.color_D83773, content,
"¥$refundPrice"
)
)
.setNegativeStr(getString(R.string.cancel))
.setPositiveStr("确认退款")
.setOnClickListener(object : CommonDialog.OnDialogClickListener {
override fun onNegativeClick() {
alertDialog!!.dismiss()
alertDialog = null
}
override fun onPositiveClick() {
alertDialog!!.dismiss()
alertDialog = null
run {
showProgressDialog("退款中")
viewModel.refund(
payServiceResponse,
StringPriceFormat.getPayPriceFenStringFromYuan(refundPrice, "0")
)
}
}
})
.show()
}
override fun onStop() {
super.onStop()
payChooseDialog?.dismiss()
alertDialog?.dismiss()
}
}
\ No newline at end of file
package com.miya.fastcashier.ui
import android.content.Intent
import android.os.Bundle
import android.view.KeyEvent
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import com.miya.fastcashier.config.IntentExtra
import com.miya.fastcashier.databinding.ActivityRefundBinding
import com.miya.fastcashier.ui.dialog.MessageDialog
import com.miya.fastcashier.ui.dialog.NumberManualDialog
import com.miya.fastcashier.ui.dialog.NumberManualDialog.NumberInputListener
import com.miya.fastcashier.ui.dialog.RefundInfoDialog
import com.miya.fastcashier.utils.CenterToasty
import com.miya.fastcashier.utils.ScanGunKeyEventHelper
import com.miya.fastcashier.utils.clickWithTrigger
......@@ -17,48 +18,49 @@ import com.sdy.miya.moblie.component.pay.platform.bean.PayServiceResponse
class RefundActivity : BaseActivity() {
private var alertDialog: MessageDialog? = null
private lateinit var viewModel: PayViewModel
private lateinit var binding: ActivityRefundBinding
private var refundInfoDialog: RefundInfoDialog? = null
private var numberManualDialog: NumberManualDialog? = null
private var numberManualDialog: NumberManualDialog? = null
private var scanGunKeyEventHelper: ScanGunKeyEventHelper = ScanGunKeyEventHelper()
companion object {
fun start(context: BaseActivity) {
val intent = Intent(context, RefundActivity::class.java)
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRefundBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(this).get(PayViewModel::class.java)
viewModel.payResultLiveData.observe(this, { payResult ->
viewModel.payResultLiveData.observe(this, { payResult ->
payResult.onFailure {
dismissProgressDialog()
it.message?.let { it1 -> CenterToasty.error(this, it1,Toast.LENGTH_LONG).show() }
it.message?.let { it1 -> CenterToasty.error(this, it1, Toast.LENGTH_LONG).show() }
}
payResult.onSuccess { payServiceResponse ->
dismissProgressDialog()
//金额确认弹窗
if(null == refundInfoDialog){
refundInfoDialog = RefundInfoDialog(this)
}
refundInfoDialog?.setData(payServiceResponse) {
doubleRefundConfirm(it)
};
refundInfoDialog?.show()
PriceInputActivity.start(
this@RefundActivity,
PriceInputActivity.PRICEINPUT_TYPE_CREFUND,
payServiceResponse
)
}
})
viewModel.refundLiveData.observe(this, { payResult ->
viewModel.refundLiveData.observe(this, { payResult ->
payResult.onFailure {
dismissProgressDialog()
it.message?.let { it1 -> CenterToasty.error(this, it1,Toast.LENGTH_LONG).show() }
it.message?.let { it1 -> CenterToasty.error(this, it1, Toast.LENGTH_LONG).show() }
}
payResult.onSuccess {
dismissProgressDialog()
CenterToasty.success(this,"退款成功!!",Toast.LENGTH_LONG).show()
CenterToasty.success(this, "退款成功!!", Toast.LENGTH_LONG).show()
finish()
}
})
......@@ -87,33 +89,8 @@ class RefundActivity : BaseActivity() {
}
}
/**
* 二次退款确认
*/
private fun doubleRefundConfirm(payServiceResponse: PayServiceResponse) {
if (null == alertDialog) {
alertDialog = MessageDialog(this)
.setCustomMessage("是否确认退款")
.setPositiveButton("确认退款"
) { _, _ ->
run {
showProgressDialog("退款中")
viewModel.refund(payServiceResponse)
}
}
}
alertDialog?.show()
}
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
scanGunKeyEventHelper.analysisKeyEvent(event)
return super.dispatchKeyEvent(event)
}
override fun onStop() {
super.onStop()
refundInfoDialog?.dismiss()
}
}
\ No newline at end of file
package com.miya.fastcashier.ui
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.view.Gravity
import com.blankj.utilcode.util.ToastUtils
import com.miya.fastcashier.R
import com.miya.fastcashier.databinding.ActivityResetAuthorizePasswordBinding
import com.miya.fastcashier.databinding.ActivitySettingBinding
import com.miya.fastcashier.service.AccountService
import com.miya.fastcashier.ui.dialog.CommonDialog
import com.miya.fastcashier.utils.CenterToasty
import com.miya.fastcashier.utils.clickWithTrigger
import com.miya.fastcashier.utils.manage.AccountPasswordManageKit
import com.tencent.mmkv.MMKV
class ResetAuthorizePasswordActivity : BaseActivity() {
private lateinit var viewBinding: ActivityResetAuthorizePasswordBinding
companion object {
@JvmStatic
fun start(context: Context) {
val intent = Intent(context, ResetAuthorizePasswordActivity::class.java)
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = ActivityResetAuthorizePasswordBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
init()
}
private fun init() {
viewBinding.llBack.clickWithTrigger { finish() }
viewBinding.tvConfirm.clickWithTrigger { updateAuthorizePassword() }
}
private fun updateAuthorizePassword() {
val originPassword = viewBinding.etOriginPassword.text.toString()
val newPassword = viewBinding.etNewPassword.text.toString()
val newConfirmPassword = viewBinding.etNewPasswordConfirm.text.toString()
if (TextUtils.isEmpty(originPassword) or
TextUtils.isEmpty(newPassword) or
TextUtils.isEmpty(newConfirmPassword)
) {
when {
TextUtils.isEmpty(originPassword) -> CenterToasty.error(this, "请输入原始密码!").show()
TextUtils.isEmpty(newPassword) -> CenterToasty.error(this, "请输入新密码!").show()
TextUtils.isEmpty(newConfirmPassword) -> CenterToasty.error(this, "请输入确认密码!").show()
}
return
}
if (originPassword.length != 6) {
CenterToasty.error(this, "请输入6位原始密码!").show()
return
}
if (newPassword.length != 6) {
CenterToasty.error(this, "请输入6位新密码!").show()
return
}
if (newConfirmPassword.length != 6) {
CenterToasty.error(this, "请输入6位确认密码!").show()
return
}
if (newPassword.equals(originPassword)) {
CenterToasty.error(this, "新密码与原密码不能相同!").show()
return
}
if (!newPassword.equals(newConfirmPassword)) {
CenterToasty.error(this, "新密码两次输入不一致!").show()
return
}
val accountAuthorizePassword = AccountPasswordManageKit.getInstance().accountPassword
if (TextUtils.isEmpty(accountAuthorizePassword)) {
AccountPasswordManageKit.getInstance()
.loadAccountPassword(this) {
if (!it.equals(originPassword)) {
CenterToasty.error(this, "原始密码输入错误!").show()
} else {
updateAuthorizePasswordSucced(newPassword)
}
}
} else {
if (!accountAuthorizePassword.equals(originPassword)) {
CenterToasty.error(this, "原始密码输入错误!").show()
}else{
updateAuthorizePasswordSucced(newPassword)
}
}
}
private fun updateAuthorizePasswordSucced(newPassword: String) {
CenterToasty.success(this, "修改成功!", 1).show()
AccountPasswordManageKit.getInstance().updateAccountPassword(newPassword)
finish()
}
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.elvishew.xlog.XLog
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import com.miya.fastcashier.R
......@@ -22,9 +23,12 @@ import com.miya.fastcashier.dao.PayDataDao
import com.miya.fastcashier.databinding.ActivitySearchOrderBinding
import com.miya.fastcashier.databinding.FragmentSearchOrderBinding
import com.miya.fastcashier.databinding.ItemSearchOrderListBinding
import com.miya.fastcashier.service.AccountService
import com.miya.fastcashier.service.PrintService
import com.miya.fastcashier.utils.*
import com.miya.fastcashier.viewmodel.SearchOrderViewModel
import com.miya.fastcashier.widget.Divider
import com.tencent.mmkv.MMKV
/**
* 查单列表
......@@ -51,7 +55,6 @@ class SearchOrderActivity : BaseActivity() {
}
}
TabLayoutMediator(
binding.tlIndicator,
binding.vpPage
......@@ -62,9 +65,7 @@ class SearchOrderActivity : BaseActivity() {
else -> tab.text = ""
}
}.attach()
}
}
......@@ -73,8 +74,11 @@ class SearchOrderFragment(val payType: MiYaPayPlantformPayWayEnum.MiyaPayType) :
private lateinit var adapter: SearchOrderListAdapter
private lateinit var vm: SearchOrderViewModel
private var onLoading = false
// private var onLoading = false
private var isEnd = false
private var balanceDate = 0L
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
......@@ -90,7 +94,8 @@ class SearchOrderFragment(val payType: MiYaPayPlantformPayWayEnum.MiyaPayType) :
return
}
isEnd = false
onLoading = false
// onLoading = false
balanceDate = MMKV.defaultMMKV().getLong("balanceDate", 0L)
val act = requireActivity()
binding?.run {
adapter = SearchOrderListAdapter(act, arrayListOf())
......@@ -109,43 +114,43 @@ class SearchOrderFragment(val payType: MiYaPayPlantformPayWayEnum.MiyaPayType) :
}
}
)
rvContent.addOnScrollListener(object : RecyclerView.OnScrollListener() {
//用来标记是否正在向最后一个滑动
var isSlidingToLast = false
override fun onScrollStateChanged(
recyclerView: RecyclerView,
newState: Int
) {
if (isEnd) { //如果已经加载完成,就不处理
return
}
val manager = recyclerView.layoutManager as LinearLayoutManager?
// 当不滚动时
if (manager != null && newState == RecyclerView.SCROLL_STATE_IDLE) {
//获取最后一个完全显示的ItemPosition
val lastVisibleItem = manager.findLastCompletelyVisibleItemPosition()
val totalItemCount = manager.itemCount
// 判断是否滚动到底部,并且是向右滚动
if (!onLoading && totalItemCount > 5 && lastVisibleItem > totalItemCount - 5 && isSlidingToLast) { //滑到最后5条的时候,如果不是列表已经结束,那么就
//加载更多功能的代码
onLoading = true
loadMore(adapter.itemCount)
}
}
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
//dx用来判断横向滑动方向,dy用来判断纵向滑动方向
isSlidingToLast = dy > 0
}
})
// rvContent.addOnScrollListener(object : RecyclerView.OnScrollListener() {
// //用来标记是否正在向最后一个滑动
// var isSlidingToLast = false
//
// override fun onScrollStateChanged(
// recyclerView: RecyclerView,
// newState: Int
// ) {
// if (isEnd) { //如果已经加载完成,就不处理
// return
// }
// val manager = recyclerView.layoutManager as LinearLayoutManager?
// // 当不滚动时
// if (manager != null && newState == RecyclerView.SCROLL_STATE_IDLE) {
// //获取最后一个完全显示的ItemPosition
// val lastVisibleItem = manager.findLastCompletelyVisibleItemPosition()
// val totalItemCount = manager.itemCount
//
// // 判断是否滚动到底部,并且是向右滚动
// if (!onLoading && totalItemCount > 5 && lastVisibleItem > totalItemCount - 5 && isSlidingToLast) { //滑到最后5条的时候,如果不是列表已经结束,那么就
// //加载更多功能的代码
// onLoading = true
// loadMore(adapter.itemCount)
// }
// }
// }
//
// override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
// //dx用来判断横向滑动方向,dy用来判断纵向滑动方向
// isSlidingToLast = dy > 0
// }
// })
}
vm = ViewModelProvider(this).get(SearchOrderViewModel::class.java)
vm.payDataLiveData.observe(act) {
onLoading = false
// onLoading = false
it.onFailure { e ->
CenterToasty.error(act, e.message ?: "", Toast.LENGTH_LONG).show()
}
......@@ -169,7 +174,6 @@ class SearchOrderFragment(val payType: MiYaPayPlantformPayWayEnum.MiyaPayType) :
}
}
initEmptyView()
loadMore(0)
}
......@@ -181,8 +185,9 @@ class SearchOrderFragment(val payType: MiYaPayPlantformPayWayEnum.MiyaPayType) :
private fun loadMore(loadIndex: Int) {
//加载更多
vm.getPayData(payType, loadIndex)
onLoading = true
// vm.getPayData(payType, loadIndex)
vm.getPayDataByTimeAndUser(payType,AccountService.getUserName(), balanceDate)
// onLoading = true
}
override fun onDestroyView() {
......@@ -253,6 +258,45 @@ class SearchOrderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
)
)
}
binding.vBg.setOnLongClickListener {
binding.groupPrinter.visibility = View.VISIBLE
true
}
binding.tvPrinter.setOnClickListener(object : View.OnClickListener {
override fun onClick(p0: View?) {
binding.groupPrinter.visibility = View.GONE
printer(data)
}
})
binding.vPrinter.setOnClickListener(object : View.OnClickListener {
override fun onClick(p0: View?) {
binding.groupPrinter.visibility = View.GONE
}
})
}
fun printer(data: ViewPayOrderData) {
var isRefund: Boolean = data.refundOrderNo != null && data.refundPrice != null
//退款打印
try {
XLog.d("开始打印")
AccountService.getAccountInfo()
?.let {
ViewPayOrderData.transformPayServiceResponse(data)?.let { it1 ->
PrintService.printSearchOrder(
it,
it1,
isRefund
)
}
}
} catch (e: Exception) {
e.printStackTrace()
XLog.d("打印异常${e.message}")
}
}
}
\ No newline at end of file
package com.miya.fastcashier.ui
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Gravity
import com.blankj.utilcode.util.ToastUtils
import com.miya.fastcashier.BaseApplication
import com.miya.fastcashier.R
import com.miya.fastcashier.databinding.ActivitySettingBinding
import com.miya.fastcashier.service.AccountService
import com.miya.fastcashier.ui.dialog.CommonDialog
import com.miya.fastcashier.utils.clickWithTrigger
import com.tencent.mmkv.MMKV
class SettingActivity : BaseActivity() {
private lateinit var viewBinding: ActivitySettingBinding
private var alertDialog: CommonDialog? = null
companion object {
@JvmStatic
fun start(context: Context) {
val intent = Intent(context, SettingActivity::class.java)
context.startActivity(intent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = ActivitySettingBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
init()
}
private fun init() {
viewBinding.llBack.clickWithTrigger { finish() }
viewBinding.vLoginOut.clickWithTrigger { loginOut() }
viewBinding.vUpdatePassword.clickWithTrigger { ResetAuthorizePasswordActivity.start(this) }
}
private fun loginOut() {
if (alertDialog == null || !alertDialog!!.isShowing) {
alertDialog = CommonDialog(this)
alertDialog!!.setCustomMessage(getString(R.string.app_text_login_out))
.setNegativeStr(getString(R.string.cancel))
.setPositiveStr(getString(R.string.text_login_out_sure))
.setMessageGravity(Gravity.CENTER_HORIZONTAL)
.setOnClickListener(object : CommonDialog.OnDialogClickListener {
override fun onNegativeClick() {
alertDialog!!.dismiss()
alertDialog = null
}
override fun onPositiveClick() {
alertDialog!!.dismiss()
alertDialog = null
run {
BaseApplication.getApplication().resetConfig()
LoginActivity.start(
this@SettingActivity,
Intent.FLAG_ACTIVITY_CLEAR_TASK
)
finish()
}
}
})
.show()
}
}
}
\ No newline at end of file
......@@ -20,11 +20,13 @@ import com.miya.fastcashier.R.mipmap.ic_wxpay
import com.miya.fastcashier.databinding.ActivityPayCodeBinding
import com.miya.fastcashier.databinding.ActivityPriceInputBinding
import com.miya.fastcashier.databinding.ActivityWxPayCodeBinding
import com.miya.fastcashier.service.PrintService
import com.miya.fastcashier.ui.dialog.PayChooseDialog
import com.miya.fastcashier.utils.CenterToasty
import com.miya.fastcashier.utils.DateUtils
import com.miya.fastcashier.utils.StringPriceFormat
import com.miya.fastcashier.utils.clickWithTrigger
import com.miya.fastcashier.utils.manage.OrderRecordManageKit
import com.miya.fastcashier.viewmodel.PayViewModel
import com.miya.print.utils.BitmapUtils
import com.sdy.miya.moblie.component.pay.platform.bean.PayServiceResponse
......@@ -83,11 +85,7 @@ class WxPayCodeActivity : AppCompatActivity() {
result.getOrNull().also {
it?.let { it1 ->
//自增流水
val today = DateUtils.format8(Date())
var no = kv.getInt(today,0);
kv.putInt(DateUtils.format8(Date()),++no)
OrderRecordManageKit.setSerialNumber()
val intent = Intent()
intent.setClass(this@WxPayCodeActivity, PayResultActivity::class.java)
......
package com.miya.fastcashier.ui.dialog
import android.content.Context
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import android.view.*
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.DialogFragment
import com.blankj.utilcode.util.ScreenUtils
import com.miya.fastcashier.databinding.DialogAuthorizePasswordInputBinding
import com.miya.fastcashier.ui.BaseActivity
import com.miya.fastcashier.ui.RefundActivity
import com.miya.fastcashier.utils.CenterToasty
import com.miya.fastcashier.utils.dp2px
import com.miya.fastcashier.utils.manage.AccountPasswordManageKit
class AuthorizePasswordInputDialog() : DialogFragment(), View.OnClickListener {
private lateinit var viewBinding: DialogAuthorizePasswordInputBinding
companion object {
fun newInstance(): AuthorizePasswordInputDialog {
return AuthorizePasswordInputDialog()
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewBinding = DialogAuthorizePasswordInputBinding.inflate(inflater)
viewBinding.ivClose.setOnClickListener(this)
viewBinding.tvConfirm.setOnClickListener(this)
viewBinding.etPassword.apply {
afterTextChanged {
viewBinding.tvError.visibility = View.GONE
}
}
viewBinding.tvConfirm.alpha = 0.5f
viewBinding.tvConfirm.isEnabled = false
return viewBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val window = dialog!!.window!!
window.setDimAmount(0.0f)
super.onViewCreated(view, savedInstanceState)
window.setBackgroundDrawable(ColorDrawable(0x191919))
window.setGravity(Gravity.BOTTOM)
window.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
context?.let { dp2px(it, 637f) }!!
)
showView()
}
fun showView() {
dialog!!.window!!.setDimAmount(0.7f)
viewBinding.container.visibility = View.VISIBLE
}
override fun onClick(view: View?) {
when (view) {
viewBinding.ivClose -> dismissAllowingStateLoss()
viewBinding.tvConfirm -> checkAuthorizePassword()
}
}
private fun checkAuthorizePassword() {
val inputPassword = viewBinding.etPassword.text.toString()
if (TextUtils.isEmpty(inputPassword)) {
context?.let { CenterToasty.error(it, "请输入授权密码").show() }
return
}
val accountPassword = AccountPasswordManageKit.getInstance().accountPassword
if (TextUtils.isEmpty(accountPassword)) {
AccountPasswordManageKit.getInstance()
.loadAccountPassword(context as AppCompatActivity?
) {
checkPasswordAndDoNext(it, inputPassword)
}
} else {
checkPasswordAndDoNext(accountPassword, inputPassword)
}
}
private fun checkPasswordAndDoNext(accountPassword: String, password: String) {
if (!accountPassword.equals(password)) {
viewBinding.tvError.visibility = View.VISIBLE
} else {
RefundActivity.start(context as BaseActivity)
dismissAllowingStateLoss()
}
}
private fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
this.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(editable: Editable?) {
afterTextChanged.invoke(editable.toString())
val password = viewBinding.etPassword.text.toString()
if (TextUtils.isEmpty(password)) {
viewBinding.tvConfirm.alpha = 0.5f
viewBinding.tvConfirm.isEnabled = false
} else {
viewBinding.tvConfirm.alpha = 1.0f
viewBinding.tvConfirm.isEnabled = true
}
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
})
}
}
\ No newline at end of file
......@@ -133,6 +133,11 @@ class CommonDialog : Dialog {
return this
}
fun setCustomMessage(contentStr: SpannableString): CommonDialog {
mContentSpanStr = contentStr
return this
}
fun setMessageGravity(gravity: Int): CommonDialog {
mMessageGravity = gravity
return this
......
......@@ -153,6 +153,16 @@ public class DateUtils {
return today;
}
/**
* 得到前一天
*/
public static String getYestedayFormat8() {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, -1);//得到前一天
Date date = calendar.getTime();
return format8(date);
}
/**
* 根据时间的字符串转成Date对象
......
package com.miya.fastcashier.utils
import android.content.Context
import android.content.pm.PackageInfo
import com.miya.fastcashier.utils.LogFileUtils
import android.content.pm.PackageManager
import com.miya.fastcashier.utils.LogFileUtils.DeleteLogTask
import android.os.AsyncTask
import android.os.Environment
import android.util.Log
import java.io.*
import java.lang.Exception
import java.nio.charset.Charset
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.Executors
object LogFileUtils {
private var logFiles //日志文件夹
: File? = null
private var logFile //单个日志文件
: File? = null
private val sExecutor = Executors.newSingleThreadExecutor()
val CACHE_FILE_PATH = Environment
.getExternalStorageDirectory().path +
File.separator +
"miyaterminal" +
File.separator +
"log" +
File.separator
var isProhibitWrite = false //是否禁止写入文件
private var allFileBeanList //所有的文件列表
: MutableList<FileBean>? = null
private var deleteFilePathList //需要删除的文件列表
: MutableList<File>? = null
private const val logSuffix = ".txt"
private const val logLink = "_"
fun writeLog(c: Context, input: String): Boolean {
sExecutor.execute { writeLogToFile(c, input) }
return false
}
private fun writeLogToFile(context: Context, input: String) {
var fos: FileOutputStream? = null
var writer: OutputStreamWriter? = null
try {
logFiles = File(CACHE_FILE_PATH)
if (!logFiles!!.exists()) {
logFiles!!.mkdirs()
}
val logPath = (CACHE_FILE_PATH + getVersionCode(context)
+ "_" + DateUtils.format8(Date()) + ".txt")
logFile = File(logPath)
fos = FileOutputStream(logFile, true)
writer = OutputStreamWriter(fos, Charset.forName("utf-8"))
writer.write(input)
writer.flush()
} catch (e: IOException) {
e.printStackTrace()
} finally {
try {
writer?.close()
} catch (e: IOException) {
e.printStackTrace()
}
try {
fos?.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
private fun getVersionCode(context: Context): String {
val packageManager = context.packageManager
val packageInfo: PackageInfo
var versionCode = ""
try {
packageInfo = packageManager.getPackageInfo(context.packageName, 0)
versionCode = packageInfo.versionCode.toString() + ""
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
}
return versionCode
}
/**
* 自动拼装时间戳的日志
*/
fun writeLogFormat(c: Context, input: String): Boolean {
val calendar = Calendar.getInstance()
calendar.timeInMillis = System.currentTimeMillis()
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
return writeLog(
c, """${sdf.format(calendar.time)} $input
"""
)
}
/**
* 写入throwable
*/
fun writeThrowable(context: Context, throwable: Throwable?): Boolean {
return try {
if (throwable == null) {
return false
}
val stringWriter = StringWriter()
throwable.printStackTrace(PrintWriter(stringWriter))
writeLogFormat(context, stringWriter.toString())
} catch (e: Exception) {
writeLogFormat(
context,
"error occur when writing throwable , error content is:" + e.message
)
false
}
}
/**
* 删除指定天数之前的日志,此处的天数不是精确到小时的,只精确到日
*
* @param days
*/
fun deleteLog(days: Int) {
files
if (deleteFilePathList == null) {
deleteFilePathList = ArrayList()
} else {
deleteFilePathList!!.clear()
}
if (allFileBeanList != null && allFileBeanList!!.size > 0) {
for (i in allFileBeanList!!.indices) {
getDeleteFileList(days, allFileBeanList!![i])
}
}
if (deleteFilePathList != null && deleteFilePathList!!.size > 0) {
val deleteFiles = deleteFilePathList!!.toTypedArray()
DeleteLogTask().execute(*deleteFiles)
}
}
/**
* 执行符合条件的删除日志操作
*
* @param days
* @param fileBean
*/
private fun getDeleteFileList(days: Int, fileBean: FileBean) {
val currentLongTimes = System.currentTimeMillis()
if (fileBean.fileName!!.endsWith(logSuffix)) {
if (fileBean.fileName!!.contains(logLink)) {
try {
val fileNameWithOutSuffix =
fileBean.fileName!!.substring(0, fileBean.fileName!!.indexOf("."))
val fileNameDate = fileNameWithOutSuffix.substring(
fileNameWithOutSuffix.lastIndexOf(
logLink
) + 1
)
val fileNameLongTimes =
DateUtils.stringToLong(fileNameDate, DateUtils.DF_YYYYMMDD)
if (currentLongTimes - fileNameLongTimes >= days * 24L * 60L * 60L * 1000L) { //符合要求,加入删除列表
deleteFilePathList!!.add(File(fileBean.filePath))
}
} catch (e: ParseException) {
e.printStackTrace()
}
}
}
}
/**
* 获得日志文件夹下的文件名和文件路径
*/
private val files: Unit
private get() {
if (allFileBeanList == null) {
allFileBeanList = ArrayList()
} else {
allFileBeanList!!.clear()
}
val files = logFiles!!.listFiles()
if (files != null) {
for (i in files.indices) {
val fileBean = FileBean()
fileBean.fileName = files[i].name
fileBean.filePath = files[i].absolutePath
allFileBeanList!!.add(fileBean)
}
}
}
private fun doDeleteFiles(file: File) {
//flie:要删除的文件夹的所在位置
if (file.isDirectory) {
val files = file.listFiles()
for (i in files.indices) {
val f = files[i]
doDeleteFiles(f)
}
file.delete() //如要保留文件夹,只删除文件,请注释这行
} else if (file.exists()) {
file.delete()
}
}
private class DeleteLogTask : AsyncTask<File, Void?, Boolean>() {
override fun doInBackground(vararg files: File): Boolean {
for (file in files) {
doDeleteFiles(file)
}
return true
}
override fun onPostExecute(aBoolean: Boolean) {
super.onPostExecute(aBoolean)
if (aBoolean) {
Log.i("LogFileUtils", "日志删除成功!")
}
}
}
private class FileBean {
var fileName: String? = null
var filePath: String? = null
}
}
\ No newline at end of file
package com.miya.fastcashier.utils
import android.content.Context
import android.text.SpannableString
import com.miya.fastcashier.utils.WordUtil
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import androidx.core.content.ContextCompat
import android.text.Spanned
import android.text.style.StyleSpan
import android.graphics.Typeface
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.text.style.ClickableSpan
import android.text.TextPaint
import android.text.Html
import android.util.Log
import android.view.View
import java.lang.Exception
import java.util.regex.Pattern
object WordUtil {
/**
* 关键字变色
*
* @param context 上下文
* @param color 变化的色值
* @param text 文字
* @param keyword 文字中的关键字
* @return 结果SpannableString
*/
fun matcherDiscolor(
context: Context?,
color: Int,
text: String,
keyword: String
): SpannableString {
var text = text
var keyword = keyword
val s = SpannableString(text)
keyword = escapeExprSpecialWord(keyword)
text = escapeExprSpecialWord(text)
if (!TextUtils.isEmpty(keyword) && text.contains(keyword)) {
try {
val p = Pattern.compile(keyword)
val m = p.matcher(s)
while (m.find()) {
val start = m.start()
val end = m.end()
//注意:请使用ContextCompat.getColor获取颜色值。
s.setSpan(
ForegroundColorSpan(ContextCompat.getColor(context!!, color)),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
return s
}
fun matcherBold(context: Context?, text: String, keyword: String): SpannableString {
var text = text
var keyword = keyword
val s = SpannableString(text)
keyword = escapeExprSpecialWord(keyword)
text = escapeExprSpecialWord(text)
if (!TextUtils.isEmpty(keyword) && text.contains(keyword)) {
try {
val p = Pattern.compile(keyword)
val m = p.matcher(s)
while (m.find()) {
val start = m.start()
val end = m.end()
s.setSpan(
StyleSpan(Typeface.BOLD),
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
break
}
} catch (e: Exception) {
e.printStackTrace()
}
}
return s
}
/**
* 关键字高亮变色 添加点击链接并跳转
*
* @param context 上下文
* @param color 变化的色值
* @param text 文字
* @param keyword 文字中的关键字
*/
fun setClickableSpanAndLighted(
context: Context,
color: Int,
text: String,
keyword: String,
intent: Intent?
): SpannableString {
var text = text
var keyword = keyword
val s = SpannableString(text)
keyword = escapeExprSpecialWord(keyword)
text = escapeExprSpecialWord(text)
if (!TextUtils.isEmpty(keyword) && text.contains(keyword)) {
try {
val p = Pattern.compile(keyword)
val m = p.matcher(s)
while (m.find()) {
val start = m.start()
val end = m.end()
val clickableSpan: ClickableSpan = object : ClickableSpan() {
override fun onClick(view: View) {
Log.e("setClickableSpan", "点击")
context.startActivity(intent)
}
//设置文字样式
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
ds.isUnderlineText = false
ds.bgColor = Color.WHITE
ds.color = ContextCompat.getColor(context, color)
}
}
s.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
return s
}
/**
* 关键字高亮变色 添加点击链接并跳转
*
* @param context 上下文
* @param color 变化的色值
* @param keyword 文字中的关键字
*/
fun setClickableSpanAndLighted(
context: Context,
color: Int,
s: SpannableString?,
keyword: String,
intent: Intent?
): SpannableString? {
var keyword = keyword
if (s == null) {
return null
}
keyword = escapeExprSpecialWord(keyword)
if (!TextUtils.isEmpty(keyword) && s.toString().contains(keyword)) {
try {
val p = Pattern.compile(keyword)
val m = p.matcher(s)
while (m.find()) {
val start = m.start()
val end = m.end()
val clickableSpan: ClickableSpan = object : ClickableSpan() {
override fun onClick(view: View) {
Log.e("setClickableSpan", "点击")
context.startActivity(intent)
}
//设置文字样式
override fun updateDrawState(ds: TextPaint) {
super.updateDrawState(ds)
ds.isUnderlineText = false
ds.bgColor = Color.WHITE
ds.color = ContextCompat.getColor(context, color)
}
}
s.setSpan(clickableSpan, start, end, 0)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
return s
}
/**
* 转义正则特殊字符 ($()*+.[]?\^{},|)
*
* @param keyword
* @return keyword
*/
fun escapeExprSpecialWord(keyword: String): String {
var keyword = keyword
if (!TextUtils.isEmpty(keyword)) {
val fbsArr =
arrayOf("\\", "$", "(", ")", "*", "+", ".", "[", "]", "?", "^", "{", "}", "|")
for (key in fbsArr) {
if (keyword.contains(key)) {
keyword = keyword.replace(key, "\\" + key)
}
}
}
return keyword
}
/**
* 通过Html.fromHtml方式修改颜色(解决SDK版本问题)
*
* @param html
* @return
*/
fun fromHtml(html: String?): Spanned {
val result: Spanned
result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY)
} else {
Html.fromHtml(html)
}
return result
}
/**
* 字体颜色修改
*
* @param content
* @param color
* @return
*/
fun color(content: String, color: Int): String {
return "<font color=\"#" + Integer.toHexString(color) + "\" >" + content + "</font>"
}
/**
* 加粗字体
*
* @param content
* @return
*/
fun bold(content: String): String {
return "<b>$content</b>"
}
}
\ No newline at end of file
package com.miya.fastcashier.utils.manage;
import android.Manifest;
import android.os.Environment;
import android.text.TextUtils;
import com.blankj.utilcode.util.FileIOUtils;
import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.miya.fastcashier.service.AccountService;
import com.permissionx.guolindev.PermissionX;
import java.util.concurrent.Executors;
import androidx.appcompat.app.AppCompatActivity;
/**
* 类描述:账户管理员密码管理
* 概述:
* 创建人:zpxiang
* 创建时间:2022/4/1
* 修改人:
* 修改时间:
*/
public class AccountPasswordManageKit {
private static final String FileDir = Environment.getExternalStorageDirectory() + "/fastcashier/";
public static final String ACCOUNT_DEFAULT_PASSWORD = "123456";
private static AccountPasswordManageKit sInstance;
private AccountPasswordManageKit() {
}
public interface AccountPasswordManageCallback {
void onPasswordGet(String password);
}
public static AccountPasswordManageKit getInstance() {
if (sInstance == null) {
sInstance = new AccountPasswordManageKit();
}
return sInstance;
}
public void checkAccountPassword(AppCompatActivity context) {
String accountPassword = AccountService.INSTANCE.getAccountPassword();
if (!TextUtils.isEmpty(accountPassword)) return;
PermissionX.init(context)
.permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
.request((allGranted, grantedList, deniedList) -> {
if (allGranted) {
initAccountPassword(context,null);
} else {
ToastUtils.showShort("请检查权限后重试");
}
});
}
public String getCurrentAccountFilePath(){
return FileDir.concat(AccountService.INSTANCE.getUserName());
}
public void initAccountPassword(AppCompatActivity context,AccountPasswordManageCallback callback) {
if (FileUtils.isFileExists(getCurrentAccountFilePath())) {
Executors.newCachedThreadPool().execute(new Runnable() {
@Override
public void run() {
String password = FileIOUtils.readFile2String(getCurrentAccountFilePath());
AccountService.INSTANCE.setAccountPassword(password);
context.runOnUiThread(new Runnable() {
@Override
public void run() {
if (callback != null){
callback.onPasswordGet(password);
}
}
});
}
});
return;
}
AccountService.INSTANCE.setAccountPassword(ACCOUNT_DEFAULT_PASSWORD);
if (callback != null){
callback.onPasswordGet(ACCOUNT_DEFAULT_PASSWORD);
}
if (FileUtils.createOrExistsFile(getCurrentAccountFilePath())) {
Executors.newCachedThreadPool().execute(new Runnable() {
@Override
public void run() {
FileIOUtils.writeFileFromString(getCurrentAccountFilePath(), ACCOUNT_DEFAULT_PASSWORD);
}
});
}
}
public void loadAccountPassword(AppCompatActivity context,AccountPasswordManageCallback callback) {
String accountPassword = AccountService.INSTANCE.getAccountPassword();
if (TextUtils.isEmpty(accountPassword)){
PermissionX.init(context)
.permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
.request((allGranted, grantedList, deniedList) -> {
if (allGranted) {
initAccountPassword(context,callback);
} else {
ToastUtils.showShort("请检查权限后重试");
}
});
}else {
if (callback != null){
callback.onPasswordGet(accountPassword);
}
}
}
public String getAccountPassword() {
return AccountService.INSTANCE.getAccountPassword();
}
public void updateAccountPassword(String password) {
if (TextUtils.isEmpty(password))return;
AccountService.INSTANCE.setAccountPassword(password);
if (FileUtils.isFileExists(getCurrentAccountFilePath())) {
FileUtils.deleteAllInDir(getCurrentAccountFilePath());
}
if (FileUtils.createOrExistsFile(getCurrentAccountFilePath())) {
Executors.newCachedThreadPool().execute(new Runnable() {
@Override
public void run() {
FileIOUtils.writeFileFromString(getCurrentAccountFilePath(), password);
}
});
}
}
}
package com.miya.fastcashier.utils.manage
import com.miya.fastcashier.utils.DateUtils
import com.tencent.mmkv.MMKV
import java.util.*
/**
* 类描述:订单流水记录MMKV管理
*/
class OrderRecordManageKit {
companion object {
private val MMKV_ID = "fastcashier_order"
/**
* 根据本地记录生成流水单号
*/
fun getSerialNumber(): String {
val today = DateUtils.format8(Date())
val no = getOrderMMKV().getInt(today, 0).toString()
var listNo = no
//真实流水单号五位
for (index in 1..(5 - no.length)) {
listNo = "0$listNo"
}
return listNo;
}
/**
* 自增流水序列号,真实流水号需要getSerialNumber()进行拼凑
*/
fun setSerialNumber() {
val today = DateUtils.format8(Date())
var no = getOrderMMKV().getInt(today, 0);
getOrderMMKV().putInt(DateUtils.format8(Date()), ++no)
}
/**
* 根据订单号获取流水号
*/
fun getSerialNoByOrderNo(orderNo: String): String {
return getOrderMMKV().getString(orderNo, "00000").toString()
}
fun setSerialNoByOrderNo(orderNo: String, serialNo: String) {
getOrderMMKV().putString(orderNo, serialNo)
}
/**
* 清除前一天的本地订单流水记录
*/
fun clearOrderDataYeaterday() {
val yeaterdayRecordExist: Boolean = isYeaterdayOrderRecordExist();
if (yeaterdayRecordExist) {
clearByTime(getYesterdayOrderMMKV())
}
}
/**
* 清除全部订单记录
*/
fun clearAll() {
clearByTime(getOrderMMKV())
clearByTime(getYesterdayOrderMMKV())
}
/**
* 清除指定日期记录
*/
fun clearByTime(mmkv: MMKV) {
mmkv.clearAll()
}
/**
* 是否存在前一天的本地订单记录
*/
private fun isYeaterdayOrderRecordExist(): Boolean {
val actualSize = getYesterdayOrderMMKV().actualSize()
return actualSize > 0
}
private fun getOrderMMKV(): MMKV {
val MMKV_ID_WITHDAY = MMKV_ID.plus(DateUtils.format8(Date()))
return MMKV.mmkvWithID(MMKV_ID_WITHDAY)
}
private fun getYesterdayOrderMMKV(): MMKV {
val yesteday = DateUtils.getYestedayFormat8()
val MMKV_ID_YESTERDAY = MMKV_ID.plus(yesteday)
return MMKV.mmkvWithID(MMKV_ID_YESTERDAY)
}
}
}
\ No newline at end of file
......@@ -34,6 +34,9 @@ class PayViewModel : ViewModel() {
val payServiceResponseLiveData: MutableLiveData<Result<PayServiceResponse>> = MutableLiveData()
val payResultLiveData: MutableLiveData<Result<PayServiceResponse>> = MutableLiveData()
/**
* 退款全额
*/
fun refund(payServiceResponse: PayServiceResponse) {
XLog.d("开始退款:${JSON.toJSONString(payServiceResponse)}")
viewModelScope.launch(Dispatchers.IO) {
......@@ -79,8 +82,57 @@ class PayViewModel : ViewModel() {
}
}
/**
* 退款固定数额
*/
fun refund(payServiceResponse: PayServiceResponse, refundPrice: String) {
XLog.d("开始退款:${JSON.toJSONString(payServiceResponse)}")
viewModelScope.launch(Dispatchers.IO) {
//退款
var refundPayServiceResponse: PayServiceResponse? = null
try {
val refundParams = HashMap<String, String>()
refundParams["oriOrderNo"] = payServiceResponse.shopTradeNo;
val refundOrderNo =
AccountService.getAccountInfo()?.shopInfo?.saasid + System.currentTimeMillis()
refundParams["refundOrderNo"] = refundOrderNo
refundParams["refundPrice"] = refundPrice
refundPayServiceResponse = PayRepository.refundByOrderNo(refundParams)
XLog.d("退款成功:${JSON.toJSONString(refundPayServiceResponse)}")
//保存到数据库
ViewPayOrderData.insert(refundPayServiceResponse)
refundLiveData.postValue(Result.success(refundPayServiceResponse))
} catch (e: Exception) {
e.printStackTrace()
XLog.d("退款异常:${e.message}")
refundLiveData.postValue(Result.failure(e))
}
//退款打印
try {
XLog.d("开始退款打印")
AccountService.getAccountInfo()
?.let {
refundPayServiceResponse?.let { it1 ->
PrintService.refundPrint(
it,
it1
)
}
}
} catch (e: Exception) {
e.printStackTrace()
XLog.d("退款打印异常${e.message}")
refundLiveData.postValue(Result.failure(e))
}
}
}
/**
* 生成付款码支付
* payType 只支持微信或者支付宝
* 2是微信 1是支付宝
* price 传进来要是分,整数
......@@ -165,7 +217,7 @@ class PayViewModel : ViewModel() {
/**
* 金额是元,首先要转成分
* 被扫支付,金额是元,首先要转成分
*/
fun pay(price: String, payCode: String) {
XLog.d("被扫开始")
......
package com.miya.fastcashier.viewmodel
import android.text.TextUtils
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.miya.fastcashier.beans.ViewPayOrderData
import com.miya.fastcashier.dao.DatabaseKeeper
import com.miya.fastcashier.utils.DateUtils
import com.miya.fastcashier.utils.MiYaPayPlantformPayWayEnum
import com.miya.fastcashier.utils.isEmpty
import com.sdy.miya.moblie.component.pay.platform.bean.PayServiceResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.lang.Exception
import com.miya.fastcashier.beans.ViewPayOrderData as ViewPayOrderData1
class SearchOrderViewModel : ViewModel() {
val payDataLiveData: MutableLiveData<Result<List<ViewPayOrderData>>> = MutableLiveData()
val payDataLiveData: MutableLiveData<Result<List<ViewPayOrderData1>>> = MutableLiveData()
/**
* 获取
* 获取所有订单,分页处理
*/
fun getPayData(payType: MiYaPayPlantformPayWayEnum.MiyaPayType, currentSize: Int) {
viewModelScope.launch(Dispatchers.IO) {
......@@ -32,4 +35,45 @@ class SearchOrderViewModel : ViewModel() {
}
}
/**
* 根据时间、用户获取订单,不分页
*/
fun getPayDataByTimeAndUser(
payType: MiYaPayPlantformPayWayEnum.MiyaPayType,
userName: String,
limitTime: Long
) {
viewModelScope.launch(Dispatchers.IO) {
try {
val list = DatabaseKeeper.payDatabase.payDataDao()
.queryAllWithTypeAndName(payType = payType.code, userName)
if (limitTime == 0L) {
payDataLiveData.postValue(Result.success(list))
return@launch
}
val destList: MutableList<ViewPayOrderData1> = arrayListOf()
if (!isEmpty(list)) {
for (order in list) {
val tradeDate: String = order.chanelOrderTradeTime
if (!TextUtils.isEmpty(tradeDate) &&
DateUtils.stringToLong(
tradeDate,
DateUtils.DF_YYYY_MM_DDHHMMSS
) > limitTime
) {
destList.add(order)
}
}
}
payDataLiveData.postValue(Result.success(destList))
} catch (e: Exception) {
e.printStackTrace()
payDataLiveData.postValue(Result.failure(e))
}
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/transparent_60" />
<corners android:radius="16dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/white" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_111235" />
<corners
android:radius="8dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners
android:radius="16dp" />
<stroke android:width="2dp"
android:color="@color/color_D1D1DC"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners
android:topRightRadius="16dp"
android:topLeftRadius="16dp"/>
</shape>
\ No newline at end of file
......@@ -50,15 +50,17 @@
<TextView
android:id="@+id/tvStoreName"
android:layout_width="360dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="23dp"
android:layout_marginLeft="26dp"
android:layout_marginTop="23dp"
android:ellipsize="end"
android:maxLines="1"
android:text="匡威-杭州滨江店!"
android:textColor="@color/white"
android:textSize="48sp"
android:textSize="36sp"
app:layout_constraintEnd_toStartOf="@+id/ivSetting"
app:layout_constraintStart_toEndOf="@+id/ivLogo"
app:layout_constraintTop_toTopOf="@+id/ivLogo" />
......@@ -70,8 +72,9 @@
android:layout_marginLeft="26dp"
android:text="ID1274911047"
android:textColor="@color/white"
android:textSize="28sp"
app:layout_constraintBottom_toBottomOf="@+id/ivLogo"
android:textSize="24sp"
app:layout_constraintTop_toBottomOf="@id/tvStoreName"
android:layout_marginTop="8dp"
app:layout_constraintStart_toEndOf="@+id/ivLogo" />
<androidx.appcompat.widget.LinearLayoutCompat
......@@ -223,7 +226,6 @@
</androidx.appcompat.widget.LinearLayoutCompat>
<TextView
android:id="@+id/tvPrintLast"
android:layout_width="624dp"
......@@ -249,15 +251,17 @@
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/ivLoginOut"
android:id="@+id/ivSetting"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:padding="7dp"
android:src="@mipmap/app_main_login_out"
app:layout_constraintBottom_toBottomOf="@+id/tvStoreName"
app:layout_constraintStart_toEndOf="@+id/tvStoreName"
app:layout_constraintTop_toTopOf="@+id/tvStoreName" />
android:layout_marginEnd="41dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:scaleType="centerCrop"
android:src="@mipmap/app_main_setting"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tvStoreName" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -12,7 +12,7 @@
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/llBack"
android:layout_width="200dp"
android:layout_height="87dp"
android:layout_height="88dp"
android:orientation="horizontal"
android:gravity="center_vertical"
app:layout_constraintStart_toStartOf="parent"
......@@ -44,28 +44,45 @@
</androidx.appcompat.widget.LinearLayoutCompat>
<TextView
android:id="@+id/tvTitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_height="88dp"
android:gravity="center"
android:textColor="@color/white"
android:text="收款"
android:textSize="36sp"/>
<TextView
android:id="@+id/tvPriceText"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/llBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="48dp"
android:layout_marginTop="54dp"
android:textColor="@color/white"
android:text="收款金额"
android:textSize="24sp"/>
android:textSize="32sp"/>
<TextView
android:id="@+id/tvRefundPriceTotal"
app:layout_constraintStart_toEndOf="@+id/tvPriceText"
app:layout_constraintTop_toBottomOf="@+id/llBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="54dp"
android:textColor="@color/white"
android:textStyle="bold"
android:visibility="gone"
tools:text="¥319.00"
tools:visibility="visible"
android:textSize="32sp"/>
<ImageView
android:id="@+id/ivRmb"
......@@ -107,13 +124,28 @@
android:layout_marginRight="32dp"
android:gravity="end" />
<TextView
android:id="@+id/tvInvalidRefundPrice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
app:layout_constraintTop_toBottomOf="@+id/vBaseLine"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="16dp"
android:textColor="@color/color_FF4E33"
android:visibility="gone"
android:text="退款金额无效"
tools:visibility="visible"
android:textSize="26sp"/>
<com.miya.fastcashier.widget.DecimalKeyboard
android:id="@+id/numKeyboard"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
app:layout_constraintBottom_toTopOf="@+id/tvScanPayCode"
android:layout_height="637dp"/>
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="130dp"
android:layout_height="637dp" />
<TextView
android:id="@+id/tvScanPayCode"
......@@ -141,6 +173,20 @@
android:background="@drawable/app_paycode_generate"
android:layout_width="0dp"/>
<TextView
android:id="@+id/tvRefund"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_height="130dp"
android:textColor="@color/white"
android:textSize="36sp"
android:text="确认退款"
android:gravity="center"
android:visibility="gone"
android:background="@drawable/app_paycode_generate"
android:layout_width="0dp"/>
<!-- &lt;!&ndash;封装成一个View&ndash;&gt;-->
<!-- <androidx.constraintlayout.widget.ConstraintLayout-->
<!-- android:visibility="gone"-->
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:background="@color/color_F8F8F8"
tools:context=".ui.SettingActivity">
<View
android:id="@+id/v_top"
android:layout_width="match_parent"
android:layout_height="87dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@color/colorPrimary"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_back"
android:layout_width="200dp"
android:layout_height="87dp"
android:orientation="horizontal"
android:gravity="center_vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tvBack"
app:layout_constraintTop_toTopOf="@+id/tvBack"
app:layout_constraintBottom_toBottomOf="@+id/tvBack"
android:layout_width="24dp"
android:layout_height="48dp"
android:layout_marginLeft="32dp"
android:padding="6dp"
android:src="@mipmap/ic_left_arrow"
android:contentDescription="@string/back" />
<androidx.appcompat.widget.AppCompatTextView
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:textColor="@color/white"
android:text="@string/back"
android:textSize="24sp"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="195dp"
android:layout_height="20dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:src="@mipmap/ic_logo_white"
app:layout_constraintBottom_toBottomOf="@+id/ll_back"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/ll_back" />
<View
android:id="@+id/v_origin_password"
android:layout_width="match_parent"
android:layout_height="103dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_top"
android:background="@color/white"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_origin_password_text"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginLeft="32dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:textSize="28sp"
android:gravity="left"
android:textColor="@color/color_333333"
app:layout_constraintStart_toStartOf="@id/v_origin_password"
app:layout_constraintTop_toTopOf="@id/v_origin_password"
app:layout_constraintBottom_toBottomOf="@id/v_origin_password"
android:text="@string/app_setting_origin_password"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_origin_password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:singleLine="true"
android:inputType="numberPassword"
android:layout_marginEnd="32dp"
android:gravity="center_vertical|left"
android:textSize="28sp"
android:textColor="@color/color_333333"
android:textColorHint="@color/color_CCCCCC"
android:hint="请输入原始密码"
android:maxLength="6"
app:layout_constraintLeft_toRightOf="@+id/tv_origin_password_text"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/v_origin_password"
app:layout_constraintBottom_toBottomOf="@id/v_origin_password" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/color_E9E9E9"
android:layout_marginStart="25dp"
android:layout_marginRight="25dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@id/v_origin_password"/>
<View
android:id="@+id/v_new_password"
android:layout_width="match_parent"
android:layout_height="103dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_origin_password"
android:background="@color/white"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_new_password_text"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:text="@string/app_setting_new_password"
android:textColor="@color/color_333333"
android:textSize="28sp"
android:gravity="left"
app:layout_constraintBottom_toBottomOf="@id/v_new_password"
app:layout_constraintStart_toStartOf="@id/v_new_password"
app:layout_constraintTop_toTopOf="@id/v_new_password" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_new_password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:singleLine="true"
android:inputType="numberPassword"
android:layout_marginEnd="32dp"
android:gravity="center_vertical|left"
android:textSize="28sp"
android:textColor="@color/color_333333"
android:textColorHint="@color/color_CCCCCC"
android:hint="请输入新密码"
android:maxLength="6"
app:layout_constraintLeft_toRightOf="@+id/tv_new_password_text"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/v_new_password"
app:layout_constraintBottom_toBottomOf="@id/v_new_password" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/color_E9E9E9"
android:layout_marginStart="25dp"
android:layout_marginRight="25dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@id/v_new_password"/>
<View
android:id="@+id/v_new_password_confirm"
android:layout_width="match_parent"
android:layout_height="103dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_new_password"
android:background="@color/white"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_new_password_confirm_text"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginLeft="32dp"
android:layout_marginStart="32dp"
android:textSize="28sp"
android:gravity="left"
android:textColor="@color/color_333333"
app:layout_constraintStart_toStartOf="@id/v_new_password_confirm"
app:layout_constraintTop_toTopOf="@id/v_new_password_confirm"
app:layout_constraintBottom_toBottomOf="@id/v_new_password_confirm"
android:text="@string/app_setting_confirm_password"/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_new_password_confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:singleLine="true"
android:inputType="numberPassword"
android:layout_marginEnd="32dp"
android:gravity="center_vertical|left"
android:textSize="28sp"
android:textColor="@color/color_333333"
android:textColorHint="@color/color_CCCCCC"
android:hint="请再次输入密码"
android:maxLength="6"
app:layout_constraintLeft_toRightOf="@+id/tv_new_password_confirm_text"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/v_new_password_confirm"
app:layout_constraintBottom_toBottomOf="@id/v_new_password_confirm" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_confirm"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:textSize="32sp"
android:gravity="center"
android:textColor="@color/white"
android:layout_marginBottom="65dp"
android:background="@drawable/shape_111235_radius8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/app_confirm_update"/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:background="@color/color_F8F8F8"
tools:context=".ui.SettingActivity">
<View
android:id="@+id/v_top"
android:layout_width="match_parent"
android:layout_height="87dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@color/colorPrimary"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_back"
android:layout_width="200dp"
android:layout_height="87dp"
android:orientation="horizontal"
android:gravity="center_vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tvBack"
app:layout_constraintTop_toTopOf="@+id/tvBack"
app:layout_constraintBottom_toBottomOf="@+id/tvBack"
android:layout_width="24dp"
android:layout_height="48dp"
android:layout_marginLeft="32dp"
android:padding="6dp"
android:src="@mipmap/ic_left_arrow"
android:contentDescription="@string/back" />
<TextView
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:textColor="@color/white"
android:text="@string/back"
android:textSize="24sp"/>
</androidx.appcompat.widget.LinearLayoutCompat>
<ImageView
android:layout_width="195dp"
android:layout_height="20dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:src="@mipmap/ic_logo_white"
app:layout_constraintBottom_toBottomOf="@+id/ll_back"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/ll_back" />
<View
android:id="@+id/v_update_password"
android:layout_width="match_parent"
android:layout_height="103dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_top"
android:background="@color/white"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="32dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:textSize="28sp"
android:textColor="@color/color_333333"
app:layout_constraintStart_toStartOf="@id/v_update_password"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/v_update_password"
app:layout_constraintBottom_toBottomOf="@id/v_update_password"
android:drawableRight="@mipmap/app_icon_arrow_right_grey"
android:text="@string/text_update_account_password"/>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/color_E9E9E9"
android:layout_marginStart="25dp"
android:layout_marginRight="25dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@id/v_update_password"/>
<View
android:id="@+id/v_login_out"
android:layout_width="match_parent"
android:layout_height="103dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_update_password"
android:background="@color/white"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="32dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:textSize="28sp"
android:textColor="@color/color_333333"
app:layout_constraintStart_toStartOf="@id/v_login_out"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/v_login_out"
app:layout_constraintBottom_toBottomOf="@id/v_login_out"
android:drawableRight="@mipmap/app_icon_arrow_right_grey"
android:text="@string/app_login_out"/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="637dp"
android:background="@drawable/shape_white_top_radius16">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="38dp"
android:layout_marginTop="35dp"
android:scaleType="center"
android:src="@mipmap/app_icon_dialog_authoize_password_close"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="37dp"
android:text="请输入授权密码"
android:textColor="@color/color_141C30"
android:textSize="36sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/v_input"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginTop="160dp"
android:background="@drawable/shape_border_d1d1dc_solid_white_radius16"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_authorize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="27dp"
android:layout_marginEnd="38dp"
android:src="@mipmap/app_icon_dialog_authoize_password"
app:layout_constraintLeft_toLeftOf="@id/v_input"
app:layout_constraintTop_toTopOf="@id/v_input"
app:layout_constraintBottom_toBottomOf="@id/v_input" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:singleLine="true"
android:inputType="numberPassword"
android:layout_marginEnd="19dp"
android:layout_marginStart="19dp"
android:gravity="center_vertical|left"
android:textSize="32sp"
android:textColor="@color/color_333333"
android:textColorHint="@color/color_CCCCCC"
android:hint="请输入默认授权密码"
android:maxLength="6"
app:layout_constraintLeft_toRightOf="@+id/iv_authorize"
app:layout_constraintRight_toRightOf="@id/v_input"
app:layout_constraintTop_toTopOf="@id/v_input"
app:layout_constraintBottom_toBottomOf="@id/v_input" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="36dp"
android:layout_marginTop="16dp"
android:text="密码错误 请重新输入"
android:textColor="@color/color_FF4E33"
android:textSize="22sp"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/v_input" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_confirm"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:textSize="32sp"
android:gravity="center"
android:textColor="@color/white"
android:layout_marginBottom="92dp"
android:background="@drawable/shape_111235_radius8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/app_confirm"/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -16,8 +16,9 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textColor="#323233"
android:textColor="@color/color_323233"
android:textSize="28sp"
android:textStyle="bold"
tools:text="是否确认退款"
android:layout_marginTop="61dp"
android:layout_width="wrap_content"
......
......@@ -14,7 +14,7 @@
android:id="@+id/cpEmptyView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_E5E5E5"
android:background="@color/color_F8F8F8"
app:layout_constraintStart_toStartOf="parent"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
......
......@@ -120,4 +120,36 @@
app:layout_goneMarginEnd="24dp"
tools:text="¥200.99" />
<View
android:id="@+id/vPrinter"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/app_bg_search_order_printer"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvPrinter"
android:layout_width="120dp"
android:layout_height="120dp"
app:layout_constraintTop_toTopOf="@id/vPrinter"
app:layout_constraintBottom_toBottomOf="@id/vPrinter"
app:layout_constraintStart_toStartOf="@id/vPrinter"
app:layout_constraintEnd_toEndOf="@id/vPrinter"
android:text="打印"
android:textStyle="bold"
android:gravity="center"
android:textColor="@color/colorPrimary"
android:textSize="28sp"
android:background="@drawable/app_bg_search_order_printer_btn" />
<androidx.constraintlayout.widget.Group
android:id="@+id/groupPrinter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="tvPrinter,vPrinter"/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -7,6 +7,7 @@
<!--50代表透明度-->
<color name="colorPrimary_50">#80111235</color>
<color name="transparent">#00000000</color>
<color name="transparent_60">#99000000</color>
<color name="green">#06C261</color>
<color name="blue">#2E6CFB</color>
<color name="color_333333">#333333</color>
......@@ -16,4 +17,11 @@
<color name="color_ECECEC">#ECECEC</color>
<color name="color_F8F8F8">#F8F8F8</color>
<color name="color_E5E5E5">#E5E5E5</color>
<color name="color_E9E9E9">#E9E9E9</color>
<color name="color_D83773">#D83773</color>
<color name="color_CCCCCC">#CCCCCC</color>
<color name="color_111235">#111235</color>
<color name="color_141C30">#141C30</color>
<color name="color_D1D1DC">#D1D1DC</color>
<color name="color_323233">#323233</color>
</resources>
\ No newline at end of file
......@@ -21,7 +21,15 @@
<string name="cancel">取消</string>
<string name="sure">确定</string>
<string name="search_order_prompt_text">还没有明细哦~</string>
<string name="app_text_login_out">是否确认退出登录账号</string>
<string name="app_text_login_out">是否确认退出账号</string>
<string name="text_login_out_sure">确认退出</string>
<string name="app_login_out">退出登录</string>
<string name="text_refund_amount">退款金额¥%s,是否确认退款</string>
<string name="text_update_account_password">修改授权密码</string>
<string name="app_setting_origin_password">原始密码</string>
<string name="app_setting_new_password">新密码</string>
<string name="app_setting_confirm_password">确认密码</string>
<string name="app_confirm_update">确认修改</string>
<string name="app_confirm">确认</string>
</resources>
\ No newline at end of file
......@@ -7,7 +7,7 @@ buildscript {
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......
# 版本历史
## tag 2022.04.6
#### v2.1.0
-添加管理员密码权限
-修改密码,退款密码校验
-优化订单流水相关,统一管理,修改存储无上限为每日清除前一天记录
## tag 2022.03.26
#### v2.1.0
-退款流程修改:允许多次退款
## tag 2022.03.24以前
#### v1.0 v2.0
-登录,登出
-收款,退款,主扫,被扫
-查询订单,打印,结算
100% — FF
95% — F2
90% — E6
85% — D9
80% — CC
75% — BF
70% — B3
65% — A6
60% — 99
55% — 8C
50% — 80
45% — 73
40% — 66
35% — 59
30% — 4D
25% — 40
20% — 33
15% — 26
10% — 1A
5% — 0D
0% — 00
\ No newline at end of file
......@@ -19,4 +19,7 @@ android.useAndroidX=true
kotlin.code.style=official
android.enableJetifier=true
android.jetifier.blacklist=miya-print
android.useDeprecatedNdk=true
\ No newline at end of file
android.useDeprecatedNdk=true
#区别品牌
channel=CONVERSE
\ No newline at end of file
ext {
VERSION_CODE = 24
VERSION_NAME = '2.1.3'
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment