diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7f6dab4..2881c43 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -21,7 +21,7 @@ android { useSupportLibrary = true } ndk { - abiFilters.addAll(listOf("armeabi", "armeabi-v7a", "x86", "arm64-v8a")) + abiFilters.add("arm64-v8a") } } @@ -37,7 +37,8 @@ android { buildTypes { release { - isMinifyEnabled = false + isMinifyEnabled = true + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" @@ -69,6 +70,10 @@ android { jniLibs.srcDirs("libs") } } + + lint { + disable += "ExpiredTargetSdkVersion" + } } kotlin { @@ -80,8 +85,6 @@ kotlin { dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar")))) - implementation("com.google.guava:guava:33.6.0-jre") - implementation("androidx.core:core-ktx:1.18.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.10.0") implementation("androidx.activity:activity-compose:1.13.0") @@ -111,7 +114,6 @@ dependencies { implementation("com.squareup.retrofit2:converter-gson:3.0.0") implementation("com.google.dagger:hilt-android:2.59.2") ksp("com.google.dagger:hilt-android-compiler:2.59.2") - implementation("com.github.devnied.emvnfccard:library:3.1.0") implementation("com.xhinliang:LunarCalendar:4.0.7") implementation("io.coil-kt.coil3:coil-compose:3.4.0") @@ -126,17 +128,15 @@ dependencies { implementation("androidx.camera:camera-compose:$cameraXVersion") implementation("androidx.camera:camera-camera2:$cameraXVersion") implementation("androidx.camera:camera-lifecycle:$cameraXVersion") - implementation("androidx.camera:camera-video:$cameraXVersion") implementation("androidx.camera:camera-view:$cameraXVersion") - implementation("androidx.camera:camera-mlkit-vision:$cameraXVersion") - implementation("androidx.camera:camera-extensions:$cameraXVersion") - api("com.licheedev:android-serialport:2.1.5") implementation("com.google.zxing:core:3.5.4") implementation("com.google.mlkit:face-detection:16.1.7") implementation("com.aliyun.dpa:oss-android-sdk:2.9.21") - implementation("com.aliyun:ocr_api20210707:3.1.3") - implementation("com.github.mik3y:usb-serial-for-android:3.8.1") + implementation("com.aliyun:ocr_api20210707:3.1.3") { + exclude(group = "pull-parser", module = "pull-parser") + exclude(group = "xpp3", module = "xpp3") + } implementation("com.github.commandiron:WheelPickerCompose:1.1.11") implementation("io.github.ehsannarmani:compose-charts:0.2.5") diff --git a/app/libs/adrcplib-1.1.jar b/app/libs/adrcplib-1.1.jar deleted file mode 100644 index d7c0584..0000000 Binary files a/app/libs/adrcplib-1.1.jar and /dev/null differ diff --git a/app/libs/arm64-v8a/libLZO.so b/app/libs/arm64-v8a/libLZO.so deleted file mode 100644 index a8b7a72..0000000 Binary files a/app/libs/arm64-v8a/libLZO.so and /dev/null differ diff --git a/app/libs/arm64-v8a/libwlt2bmp.so b/app/libs/arm64-v8a/libwlt2bmp.so deleted file mode 100644 index 24bf99b..0000000 Binary files a/app/libs/arm64-v8a/libwlt2bmp.so and /dev/null differ diff --git a/app/libs/arm64-v8a/libzkserialport.so b/app/libs/arm64-v8a/libzkserialport.so deleted file mode 100644 index 08f7511..0000000 Binary files a/app/libs/arm64-v8a/libzkserialport.so and /dev/null differ diff --git a/app/libs/arm64-v8a/libzkwltdecode.so b/app/libs/arm64-v8a/libzkwltdecode.so deleted file mode 100644 index 2a6b265..0000000 Binary files a/app/libs/arm64-v8a/libzkwltdecode.so and /dev/null differ diff --git a/app/libs/arm64-v8a/libzyapi_common.so b/app/libs/arm64-v8a/libzyapi_common.so deleted file mode 100644 index d56aa63..0000000 Binary files a/app/libs/arm64-v8a/libzyapi_common.so and /dev/null differ diff --git a/app/libs/armeabi-v7a/libLZO.so b/app/libs/armeabi-v7a/libLZO.so deleted file mode 100644 index ffd0aeb..0000000 Binary files a/app/libs/armeabi-v7a/libLZO.so and /dev/null differ diff --git a/app/libs/armeabi-v7a/libmsc.so b/app/libs/armeabi-v7a/libmsc.so deleted file mode 100644 index 84579e0..0000000 Binary files a/app/libs/armeabi-v7a/libmsc.so and /dev/null differ diff --git a/app/libs/armeabi-v7a/libwlt2bmp.so b/app/libs/armeabi-v7a/libwlt2bmp.so deleted file mode 100644 index d36c600..0000000 Binary files a/app/libs/armeabi-v7a/libwlt2bmp.so and /dev/null differ diff --git a/app/libs/armeabi-v7a/libzkserialport.so b/app/libs/armeabi-v7a/libzkserialport.so deleted file mode 100644 index a785cfc..0000000 Binary files a/app/libs/armeabi-v7a/libzkserialport.so and /dev/null differ diff --git a/app/libs/armeabi-v7a/libzkwltdecode.so b/app/libs/armeabi-v7a/libzkwltdecode.so deleted file mode 100644 index a6c6543..0000000 Binary files a/app/libs/armeabi-v7a/libzkwltdecode.so and /dev/null differ diff --git a/app/libs/armeabi-v7a/libzyapi_common.so b/app/libs/armeabi-v7a/libzyapi_common.so deleted file mode 100644 index 5602e49..0000000 Binary files a/app/libs/armeabi-v7a/libzyapi_common.so and /dev/null differ diff --git a/app/libs/armeabi/libLZO.so b/app/libs/armeabi/libLZO.so deleted file mode 100644 index 53cee5a..0000000 Binary files a/app/libs/armeabi/libLZO.so and /dev/null differ diff --git a/app/libs/lzo_V1.0.jar b/app/libs/lzo_V1.0.jar deleted file mode 100644 index f438905..0000000 Binary files a/app/libs/lzo_V1.0.jar and /dev/null differ diff --git a/app/libs/mips/libLZO.so b/app/libs/mips/libLZO.so deleted file mode 100644 index 02c3838..0000000 Binary files a/app/libs/mips/libLZO.so and /dev/null differ diff --git a/app/libs/mips64/libLZO.so b/app/libs/mips64/libLZO.so deleted file mode 100644 index 2896f0b..0000000 Binary files a/app/libs/mips64/libLZO.so and /dev/null differ diff --git a/app/libs/myRfid.jar b/app/libs/myRfid.jar deleted file mode 100644 index f5a037b..0000000 Binary files a/app/libs/myRfid.jar and /dev/null differ diff --git a/app/libs/my_adsiolib-1.51.jar b/app/libs/my_adsiolib-1.51.jar deleted file mode 100644 index 2059860..0000000 Binary files a/app/libs/my_adsiolib-1.51.jar and /dev/null differ diff --git a/app/libs/rfid18 b/app/libs/rfid18 deleted file mode 100644 index 32a1cd4..0000000 Binary files a/app/libs/rfid18 and /dev/null differ diff --git a/app/libs/x86/libLZO.so b/app/libs/x86/libLZO.so deleted file mode 100644 index 4f13511..0000000 Binary files a/app/libs/x86/libLZO.so and /dev/null differ diff --git a/app/libs/x86_64/libLZO.so b/app/libs/x86_64/libLZO.so deleted file mode 100644 index c8abbd3..0000000 Binary files a/app/libs/x86_64/libLZO.so and /dev/null differ diff --git a/app/libs/zkandroidcore.jar b/app/libs/zkandroidcore.jar deleted file mode 100644 index df507bf..0000000 Binary files a/app/libs/zkandroidcore.jar and /dev/null differ diff --git a/app/libs/zkandroididcardreader.jar b/app/libs/zkandroididcardreader.jar deleted file mode 100644 index 17bc9de..0000000 Binary files a/app/libs/zkandroididcardreader.jar and /dev/null differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..0c8e522 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,4 +18,29 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile + +# Hardware and vendor SDKs rely on JNI, reflection, or callback names. +-keep class com.alibaba.sdk.android.oss.** { *; } +-keep class com.aliyun.** { *; } +-keep class com.caysn.autoreplyprint.** { *; } +-keep class com.cpcl.** { *; } +-keep class com.iflytek.** { *; } +-keep class com.inuker.bluetooth.** { *; } +-keep class com.qhscale.** { *; } +-keep class com.sun.jna.** { *; } +-keep class cpcl.** { *; } + +-keepclasseswithmembernames class * { + native ; +} + +-dontwarn com.alibaba.sdk.android.oss.** +-dontwarn com.aliyun.** +-dontwarn com.caysn.autoreplyprint.** +-dontwarn com.cpcl.** +-dontwarn com.iflytek.** +-dontwarn com.inuker.bluetooth.** +-dontwarn com.qhscale.** +-dontwarn com.sun.jna.** +-dontwarn cpcl.** diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 06299e0..cb0f076 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,11 +1,6 @@ - - - @@ -49,10 +44,6 @@ - - @@ -85,13 +76,6 @@ - - - - - @@ -138,4 +122,4 @@ android:value="true" /> - \ No newline at end of file + diff --git a/app/src/main/assets/RasterImage/blackwhite.png b/app/src/main/assets/RasterImage/blackwhite.png deleted file mode 100644 index c82faca..0000000 Binary files a/app/src/main/assets/RasterImage/blackwhite.png and /dev/null differ diff --git a/app/src/main/assets/RasterImage/iu.jpeg b/app/src/main/assets/RasterImage/iu.jpeg deleted file mode 100644 index fddb552..0000000 Binary files a/app/src/main/assets/RasterImage/iu.jpeg and /dev/null differ diff --git a/app/src/main/assets/RasterImage/yellowmen.png b/app/src/main/assets/RasterImage/yellowmen.png deleted file mode 100644 index 90601cf..0000000 Binary files a/app/src/main/assets/RasterImage/yellowmen.png and /dev/null differ diff --git a/app/src/main/java/android/zyapi/CommonApi.java b/app/src/main/java/android/zyapi/CommonApi.java deleted file mode 100644 index 1685cd8..0000000 --- a/app/src/main/java/android/zyapi/CommonApi.java +++ /dev/null @@ -1,30 +0,0 @@ -package android.zyapi; - - -public class CommonApi { - - private static CommonApi mMe = null; - - public CommonApi() { - } - - // gpio - public native int setGpioMode(int pin, int mode); - public native int setGpioDir(int pin, int dir); - public native int setGpioPullEnable(int pin, int enable); - public native int setGpioPullSelect(int pin, int select); - public native int setGpioOut(int pin, int out); - public native int getGpioIn(int pin); - //serialport - public native int openCom(String port, int baudrate, int bits, char event, int stop); - public native int openComEx(String port, int baudrate, int bits, char event, int stop, int flags); - public native int writeCom(int fd, byte[] buf, int sizes); - public native int readCom(int fd, byte[] buf, int sizes); - public native int readComEx(int fd, byte[] buf, int sizes, int sec, int usec); - public native void closeCom(int fd); - - static { - System.loadLibrary("zyapi_common"); - } - -} diff --git a/app/src/main/java/android_serialport_api/NFC/NdefMessageParser.java b/app/src/main/java/android_serialport_api/NFC/NdefMessageParser.java deleted file mode 100644 index 1137fda..0000000 --- a/app/src/main/java/android_serialport_api/NFC/NdefMessageParser.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android_serialport_api.NFC; - -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.List; - -import android.nfc.NdefMessage; -import android.nfc.NdefRecord; - -/** - * Utility class for creating {@link ParsedNdefMessage}s. - */ -public class NdefMessageParser { - - // Utility class - private NdefMessageParser() { - - } - - /** Parse an NdefMessage */ - public static List parse(NdefMessage message) { - return getRecords(message.getRecords()); - } - - public static List getRecords(NdefRecord[] records) { - List elements = new ArrayList(); - for (final NdefRecord record : records) { - if (UriRecord.isUri(record)) { - elements.add(UriRecord.parse(record)); - } else if (TextRecord.isText(record)) { - elements.add(TextRecord.parse(record)); - } else if (SmartPoster.isPoster(record)) { - elements.add(SmartPoster.parse(record)); - } else { -// String temp =""; -// temp = new String(record.getPayload()); -// temp = bytesToHexString(record.getPayload(),true); - elements.add(new ParsedNdefRecord() { - @Override - public String getViewText() { - String temp = new String(record.getPayload()) + "\n"; - return temp; - } - }); - } - } - return elements; - } - - private static String hexString="0123456789ABCDEF"; - public static String decode(String bytes) { - ByteArrayOutputStream baos = new ByteArrayOutputStream( - bytes.length() / 2); - for (int i = 0; i < bytes.length(); i += 2) - baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString - .indexOf(bytes.charAt(i + 1)))); - return new String(baos.toByteArray()); - } - - - private static String bytesToHexString(byte[] src, boolean isPrefix) { - StringBuilder stringBuilder = new StringBuilder(); - if (isPrefix == true) { - stringBuilder.append("0x"); - } - if (src == null || src.length <= 0) { - return null; - } - char[] buffer = new char[2]; - for (int i = 0; i < src.length; i++) { - buffer[0] = Character.toUpperCase(Character.forDigit( - (src[i] >>> 4) & 0x0F, 16)); - buffer[1] = Character.toUpperCase(Character.forDigit(src[i] & 0x0F, - 16)); - System.out.println(buffer); - stringBuilder.append(buffer); - } - return stringBuilder.toString(); - } -} diff --git a/app/src/main/java/android_serialport_api/NFC/ParsedNdefRecord.java b/app/src/main/java/android_serialport_api/NFC/ParsedNdefRecord.java deleted file mode 100644 index e72128e..0000000 --- a/app/src/main/java/android_serialport_api/NFC/ParsedNdefRecord.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android_serialport_api.NFC; - -public interface ParsedNdefRecord { - - /** - * Returns a view to display this record. - */ - public String getViewText(); - -} diff --git a/app/src/main/java/android_serialport_api/NFC/SmartPoster.java b/app/src/main/java/android_serialport_api/NFC/SmartPoster.java deleted file mode 100644 index 0c98b09..0000000 --- a/app/src/main/java/android_serialport_api/NFC/SmartPoster.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android_serialport_api.NFC; - -import java.util.Arrays; -import java.util.NoSuchElementException; - -import android.nfc.FormatException; -import android.nfc.NdefMessage; -import android.nfc.NdefRecord; - -import com.google.common.base.Charsets; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; - -/** - * A representation of an NFC Forum "Smart Poster". - */ -public class SmartPoster implements ParsedNdefRecord { - - /** - * NFC Forum Smart Poster Record Type Definition section 3.2.1. - * - * "The Title record for the service (there can be many of these in - * different languages, but a language MUST NOT be repeated). This record is - * optional." - */ - private final TextRecord mTitleRecord; - - /** - * NFC Forum Smart Poster Record Type Definition section 3.2.1. - * - * "The URI record. This is the core of the Smart Poster, and all other - * records are just metadata about this record. There MUST be one URI record - * and there MUST NOT be more than one." - */ - private final UriRecord mUriRecord; - - /** - * NFC Forum Smart Poster Record Type Definition section 3.2.1. - * - * "The Action record. This record describes how the service should be - * treated. For example, the action may indicate that the device should save - * the URI as a bookmark or open a browser. The Action record is optional. - * If it does not exist, the device may decide what to do with the service. - * If the action record exists, it should be treated as a strong suggestion; - * the UI designer may ignore it, but doing so will induce a different user - * experience from device to device." - */ - private final RecommendedAction mAction; - - /** - * NFC Forum Smart Poster Record Type Definition section 3.2.1. - * - * "The Type record. If the URI references an external entity (e.g., via a - * URL), the Type record may be used to declare the MIME type of the entity. - * This can be used to tell the mobile device what kind of an object it can - * expect before it opens the connection. The Type record is optional." - */ - private final String mType; - - private SmartPoster(UriRecord uri, TextRecord title, RecommendedAction action, String type) { - mUriRecord = Preconditions.checkNotNull(uri); - mTitleRecord = title; - mAction = Preconditions.checkNotNull(action); - mType = type; - } - - public UriRecord getUriRecord() { - return mUriRecord; - } - - /** - * Returns the title of the smart poster. This may be {@code null}. - */ - public TextRecord getTitle() { - return mTitleRecord; - } - - public static SmartPoster parse(NdefRecord record) { - Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN); - Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_SMART_POSTER)); - try { - NdefMessage subRecords = new NdefMessage(record.getPayload()); - return parse(subRecords.getRecords()); - } catch (FormatException e) { - throw new IllegalArgumentException(e); - } - } - - public static SmartPoster parse(NdefRecord[] recordsRaw) { - try { - Iterable records = NdefMessageParser.getRecords(recordsRaw); - UriRecord uri = Iterables.getOnlyElement(Iterables.filter(records, UriRecord.class)); - TextRecord title = getFirstIfExists(records, TextRecord.class); - RecommendedAction action = parseRecommendedAction(recordsRaw); - String type = parseType(recordsRaw); - return new SmartPoster(uri, title, action, type); - } catch (NoSuchElementException e) { - throw new IllegalArgumentException(e); - } - } - - public static boolean isPoster(NdefRecord record) { - try { - parse(record); - return true; - } catch (IllegalArgumentException e) { - return false; - } - } - - - /** - * Returns the first element of {@code elements} which is an instance of - * {@code type}, or {@code null} if no such element exists. - */ - private static T getFirstIfExists(Iterable elements, Class type) { - Iterable filtered = Iterables.filter(elements, type); - T instance = null; - if (!Iterables.isEmpty(filtered)) { - instance = Iterables.get(filtered, 0); - } - return instance; - } - - private enum RecommendedAction { - UNKNOWN((byte) -1), DO_ACTION((byte) 0), SAVE_FOR_LATER((byte) 1), OPEN_FOR_EDITING( - (byte) 2); - - private static final ImmutableMap LOOKUP; - static { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (RecommendedAction action : RecommendedAction.values()) { - builder.put(action.getByte(), action); - } - LOOKUP = builder.build(); - } - - private final byte mAction; - - private RecommendedAction(byte val) { - this.mAction = val; - } - - private byte getByte() { - return mAction; - } - } - - private static NdefRecord getByType(byte[] type, NdefRecord[] records) { - for (NdefRecord record : records) { - if (Arrays.equals(type, record.getType())) { - return record; - } - } - return null; - } - - private static final byte[] ACTION_RECORD_TYPE = new byte[] {'a', 'c', 't'}; - - private static RecommendedAction parseRecommendedAction(NdefRecord[] records) { - NdefRecord record = getByType(ACTION_RECORD_TYPE, records); - if (record == null) { - return RecommendedAction.UNKNOWN; - } - byte action = record.getPayload()[0]; - if (RecommendedAction.LOOKUP.containsKey(action)) { - return RecommendedAction.LOOKUP.get(action); - } - return RecommendedAction.UNKNOWN; - } - - private static final byte[] TYPE_TYPE = new byte[] {'t'}; - - private static String parseType(NdefRecord[] records) { - NdefRecord type = getByType(TYPE_TYPE, records); - if (type == null) { - return null; - } - return new String(type.getPayload(), Charsets.UTF_8); - } - - @Override - public String getViewText() { - if (mTitleRecord != null) { - return mTitleRecord.getText(); - } - return mTitleRecord.getText(); - } -} diff --git a/app/src/main/java/android_serialport_api/NFC/TextRecord.java b/app/src/main/java/android_serialport_api/NFC/TextRecord.java deleted file mode 100644 index 9c84e58..0000000 --- a/app/src/main/java/android_serialport_api/NFC/TextRecord.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android_serialport_api.NFC; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.Arrays; - -import android.app.Activity; -import android.nfc.NdefRecord; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.google.common.base.Preconditions; - -/** - * An NFC Text Record - */ -public class TextRecord implements ParsedNdefRecord{ - - /** ISO/IANA language code */ - private final String mLanguageCode; - - private final String mText; - - private TextRecord(String languageCode, String text) { - mLanguageCode = Preconditions.checkNotNull(languageCode); - mText = Preconditions.checkNotNull(text); - } - - @Override - public String getViewText() { - return mText; - } - - public String getText() { - return mText; - } - - /** - * Returns the ISO/IANA language code associated with this text element. - */ - public String getLanguageCode() { - return mLanguageCode; - } - - // TODO: deal with text fields which span multiple NdefRecords - public static TextRecord parse(NdefRecord record) { - Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN); - Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)); - try { - byte[] payload = record.getPayload(); - /* - * payload[0] contains the "Status Byte Encodings" field, per the - * NFC Forum "Text Record Type Definition" section 3.2.1. - * - * bit7 is the Text Encoding Field. - * - * if (Bit_7 == 0): The text is encoded in UTF-8 if (Bit_7 == 1): - * The text is encoded in UTF16 - * - * Bit_6 is reserved for future use and must be set to zero. - * - * Bits 5 to 0 are the length of the IANA language code. - */ - - if (payload.length <= 0) { - payload = record.getType(); - return null; - } - String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16"; - int languageCodeLength = payload[0] & 0077; - String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII"); - String text = - new String(payload, languageCodeLength + 1, - payload.length - languageCodeLength - 1, textEncoding); - return new TextRecord(languageCode, text); - } catch (UnsupportedEncodingException e) { - // should never happen unless we get a malformed tag. - throw new IllegalArgumentException(e); - } - } - - public static boolean isText(NdefRecord record) { - try { - parse(record); - return true; - } catch (IllegalArgumentException e) { - return false; - } - } -} diff --git a/app/src/main/java/android_serialport_api/NFC/UriRecord.java b/app/src/main/java/android_serialport_api/NFC/UriRecord.java deleted file mode 100644 index 1e53dc8..0000000 --- a/app/src/main/java/android_serialport_api/NFC/UriRecord.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android_serialport_api.NFC; - -import java.nio.charset.Charset; -import java.util.Arrays; -import android.net.Uri; -import android.nfc.NdefRecord; -import com.google.common.base.Preconditions; -import com.google.common.collect.BiMap; -import com.google.common.collect.ImmutableBiMap; -import com.google.common.primitives.Bytes; - -/** - * A parsed record containing a Uri. - */ -public class UriRecord implements ParsedNdefRecord { - - private static final String TAG = "UriRecord"; - - public static final String RECORD_TYPE = "UriRecord"; - - /** - * NFC Forum "URI Record Type Definition" - * - * This is a mapping of "URI Identifier Codes" to URI string prefixes, - * per section 3.2.2 of the NFC Forum URI Record Type Definition document. - */ - private static final BiMap URI_PREFIX_MAP = ImmutableBiMap.builder() - .put((byte) 0x00, "") - .put((byte) 0x01, "http://www.") - .put((byte) 0x02, "https://www.") - .put((byte) 0x03, "http://") - .put((byte) 0x04, "https://") - .put((byte) 0x05, "tel:") - .put((byte) 0x06, "mailto:") - .put((byte) 0x07, "ftp://anonymous:anonymous@") - .put((byte) 0x08, "ftp://ftp.") - .put((byte) 0x09, "ftps://") - .put((byte) 0x0A, "sftp://") - .put((byte) 0x0B, "smb://") - .put((byte) 0x0C, "nfs://") - .put((byte) 0x0D, "ftp://") - .put((byte) 0x0E, "dav://") - .put((byte) 0x0F, "news:") - .put((byte) 0x10, "telnet://") - .put((byte) 0x11, "imap:") - .put((byte) 0x12, "rtsp://") - .put((byte) 0x13, "urn:") - .put((byte) 0x14, "pop:") - .put((byte) 0x15, "sip:") - .put((byte) 0x16, "sips:") - .put((byte) 0x17, "tftp:") - .put((byte) 0x18, "btspp://") - .put((byte) 0x19, "btl2cap://") - .put((byte) 0x1A, "btgoep://") - .put((byte) 0x1B, "tcpobex://") - .put((byte) 0x1C, "irdaobex://") - .put((byte) 0x1D, "file://") - .put((byte) 0x1E, "urn:epc:id:") - .put((byte) 0x1F, "urn:epc:tag:") - .put((byte) 0x20, "urn:epc:pat:") - .put((byte) 0x21, "urn:epc:raw:") - .put((byte) 0x22, "urn:epc:") - .put((byte) 0x23, "urn:nfc:") - .build(); - - private final Uri mUri; - - private UriRecord(Uri uri) { - this.mUri = Preconditions.checkNotNull(uri); - } - - public String getViewText(){ - return mUri.toString(); - } - - public Uri getUri() { - return mUri; - } - - /** - * Convert {@link android.nfc.NdefRecord} into a {@link android.net.Uri}. - * This will handle both TNF_WELL_KNOWN / RTD_URI and TNF_ABSOLUTE_URI. - * - * @throws IllegalArgumentException if the NdefRecord is not a record - * containing a URI. - */ - public static UriRecord parse(NdefRecord record) { - short tnf = record.getTnf(); - if (tnf == NdefRecord.TNF_WELL_KNOWN) { - return parseWellKnown(record); - } else if (tnf == NdefRecord.TNF_ABSOLUTE_URI) { - return parseAbsolute(record); - } - throw new IllegalArgumentException("Unknown TNF " + tnf); - } - - /** Parse and absolute URI record */ - private static UriRecord parseAbsolute(NdefRecord record) { - byte[] payload = record.getPayload(); - Uri uri = Uri.parse(new String(payload, Charset.forName("UTF-8"))); - return new UriRecord(uri); - } - - /** Parse an well known URI record */ - private static UriRecord parseWellKnown(NdefRecord record) { - Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_URI)); - byte[] payload = record.getPayload(); - /* - * payload[0] contains the URI Identifier Code, per the - * NFC Forum "URI Record Type Definition" section 3.2.2. - * - * payload[1]...payload[payload.length - 1] contains the rest of - * the URI. - */ - String prefix = URI_PREFIX_MAP.get(payload[0]); - byte[] fullUri = - Bytes.concat(prefix.getBytes(Charset.forName("UTF-8")), Arrays.copyOfRange(payload, 1, - payload.length)); - Uri uri = Uri.parse(new String(fullUri, Charset.forName("UTF-8"))); - return new UriRecord(uri); - } - - public static boolean isUri(NdefRecord record) { - try { - parse(record); - return true; - } catch (IllegalArgumentException e) { - return false; - } - } - - private static final byte[] EMPTY = new byte[0]; -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/base/BaseList.kt b/app/src/main/java/com/bbitcn/f8/pad/base/BaseList.kt index b18e99c..3b0054e 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/base/BaseList.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/base/BaseList.kt @@ -71,7 +71,6 @@ import com.bbitcn.f8.pad.ui.theme.MyColors import com.cyberecho.ui.screen.JumpToBottomThreshold import com.cyberecho.ui.view.JumpToBottom import com.cyberecho.ui.view.JumpToTop -import com.google.common.collect.Multimaps.index import kotlinx.coroutines.launch import kotlin.collections.map diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/MainActivity.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/MainActivity.kt index 7624725..13fab9b 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/MainActivity.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/MainActivity.kt @@ -43,9 +43,6 @@ import com.bbitcn.f8.pad.ui.screen.dialog.LoadingDialog import com.bbitcn.f8.pad.ui.screen.dialog.TipsDialog import com.bbitcn.f8.pad.ui.screen.view.drawer.DrawerViewModel import com.bbitcn.f8.pad.ui.screen.secondFunc.AddUserScreen -import com.bbitcn.f8.pad.ui.screen.secondFunc.DryCocoonAirScreen -import com.bbitcn.f8.pad.ui.screen.secondFunc.DryCocoonInScreen -import com.bbitcn.f8.pad.ui.screen.secondFunc.DryCocoonOutScreen import com.bbitcn.f8.pad.ui.screen.secondFunc.PayScreen import com.bbitcn.f8.pad.ui.screen.secondFunc.WeightScreen import com.bbitcn.f8.pad.ui.screen.view.Toasty @@ -59,7 +56,6 @@ import com.bbitcn.f8.pad.ui.viewmodel.UpdateViewModel import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleBT import com.bbitcn.f8.pad.utils.externalModules.devices.printer.PrinterBT import com.bbitcn.f8.pad.utils.externalModules.devices.water.WaterCutMeterBT -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.nfc.NFCUtils /** * @@ -76,7 +72,6 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) setFullScreen(true) // 初始化NfcAdapter - NFCUtils.initActivity(this) PrinterBT.init() WaterCutMeterBT.init() ScaleBT.init() @@ -211,26 +206,6 @@ class MainActivity : ComponentActivity() { backStackEntry.arguments?.getString("czSysId") ?: "" PayScreen(czSysId) } - composable("dryCoonOperateIn/{sysId}") { backStackEntry -> - topInfoViewmodel.toScreen("dryCoonOperateIn") - var sysId = - backStackEntry.arguments?.getString("sysId") ?: "" -// sysId = "3d51438a-c835-401d-bb6c-1c045363298f" - DryCocoonInScreen(sysId) - } - composable("dryCoonOperateAir/{sysId}") { backStackEntry -> - topInfoViewmodel.toScreen("dryCoonOperateAir") - var sysId = - backStackEntry.arguments?.getString("sysId") ?: "" - DryCocoonAirScreen(sysId) - } - composable("dryCoonOperateOut/{sysId}") { backStackEntry -> - topInfoViewmodel.toScreen("dryCoonOperateOut") - var sysId = - backStackEntry.arguments?.getString("sysId") ?: "" -// sysId = "3d51438a-c835-401d-bb6c-1c045363298f" - DryCocoonOutScreen(sysId) - } } } MyBottomSheet( diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/MainViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/MainViewModel.kt index b74a3d5..b20ffc7 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/MainViewModel.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/MainViewModel.kt @@ -7,16 +7,12 @@ import com.bbitcn.f8.pad.base.BaseViewModel import com.bbitcn.f8.pad.ui.screen.view.Toasty import com.bbitcn.f8.pad.utils.MMKVUtil import com.bbitcn.f8.pad.utils.PollingTask -import com.bbitcn.f8.pad.utils.externalModules.devices.light.Light_ import com.bbitcn.f8.pad.utils.externalModules.devices.printer.PrinterBT import com.bbitcn.f8.pad.utils.externalModules.devices.printer.JTPrinterUSB -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG20R import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleBT import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleSerial import com.bbitcn.f8.pad.utils.externalModules.manager.bluetooth.MyBlueTooth import com.bbitcn.f8.pad.utils.externalModules.manager.serial.SerialDeviceConnector -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.SerialDeviceConnector2 import com.bbitcn.f8.pad.utils.externalModules.manager.usb.UsbDeviceConnector import com.bbitcn.f8.pad.utils.global.Global import com.bbitcn.f8.pad.utils.log.MyLog @@ -86,33 +82,18 @@ class MainViewModel : BaseViewModel(), RecognizerListener { PollingTask.getInstance().startDelayedTask("AutoConnect", delaySeconds = 5) { doInIoThreadNoDialog { val devices = listOf( - // 串口 称 ScaleSerial, - // 串口 灯具 - Light_, - // 串口 读卡器 - UHFReaderG06M_G25M, - UHFReaderG20R, - // USB 打印机 JTPrinterUSB, - // 蓝牙 打印机 PrinterBT, - // 蓝牙 称 ScaleBT, ) devices.forEach { if (it.getAutoConnectOnStartUp()) { if (it is SerialDeviceConnector) { - // 串口称 串口读卡器 it.connect(it.getPort(), it.getBaudRate()) - } else if (it is SerialDeviceConnector2) { - // 串口 灯具 - it.connect(it.getRDeviceName(), it.getBaudRate()) } else if (it is UsbDeviceConnector) { - // USB 打印机 it.connect(it.getVId(), it.getPId()) } else if (it is MyBlueTooth) { - // 蓝牙设备 it.startScan() } } @@ -120,7 +101,6 @@ class MainViewModel : BaseViewModel(), RecognizerListener { } } } - fun refreshMenuPermission() { doInIoThread("正在加载菜单") { val menuPermission = apiService.getMenuPermission() diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopBar.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopBar.kt index 219647e..3665cc7 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopBar.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopBar.kt @@ -52,7 +52,6 @@ import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleBT import com.bbitcn.f8.pad.utils.externalModules.devices.printer.PrinterBT import com.bbitcn.f8.pad.utils.externalModules.devices.printer.JTPrinterUSB import com.bbitcn.f8.pad.utils.externalModules.devices.water.WaterCutMeterBT -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.nfc.NFCUtils import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleSerial /** @@ -178,15 +177,6 @@ fun MyTopBar( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically ) { - if (NFCUtils.isEnable()) { - Image( - modifier = M - .padding(end = 5.dp) - .size(25.dp), - painter = painterResource(id = R.drawable.nfc), - contentDescription = "NFC", - ) - } if (isBluetoothEnabled()) { Image( modifier = M diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopInfoViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopInfoViewModel.kt index f0b631f..be3a434 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopInfoViewModel.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopInfoViewModel.kt @@ -66,9 +66,6 @@ class TopInfoViewModel : BaseViewModel() { "weight" -> Pair(R.drawable.back, title("称重")) to 1 "pay" -> Pair(R.drawable.back, title("支付")) to 1 "camera" -> Pair(R.drawable.back, title("相机预览")) to 1 - "dryCoonOperateIn" -> Pair(R.drawable.back, title("干茧入库")) to 1 - "dryCoonOperateOut" -> Pair(R.drawable.back, title("干茧出库")) to 1 - "dryCoonOperateAir" -> Pair(R.drawable.back, title("摊晾计划")) to 1 else -> Pair(R.drawable.logo_white, _title.value) to 0 } } diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/AddTicketDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/AddTicketDialog.kt index 58a0a5e..2b4e632 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/AddTicketDialog.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/AddTicketDialog.kt @@ -3,17 +3,13 @@ package com.bbitcn.f8.pad.ui.screen.dialog import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -21,62 +17,41 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.viewmodel.compose.viewModel import androidx.paging.compose.collectAsLazyPagingItems import com.bbitcn.f8.pad.M import com.bbitcn.f8.pad.R -import com.bbitcn.f8.pad.base.BaseDialogFrame -import com.bbitcn.f8.pad.base.BigButton -import com.bbitcn.f8.pad.base.MyAnimatedVisibility import com.bbitcn.f8.pad.base.MyCard import com.bbitcn.f8.pad.base.MyDialog import com.bbitcn.f8.pad.base.MyRefreshTable -import com.bbitcn.f8.pad.base.MyTable import com.bbitcn.f8.pad.base.MyTableData import com.bbitcn.f8.pad.base.MyTextField -import com.bbitcn.f8.pad.base.TableHeadLine import com.bbitcn.f8.pad.base.VerticalTabPages import com.bbitcn.f8.pad.ui.screen.mainFunc.UserViewModel -import com.bbitcn.f8.pad.ui.screen.secondFunc.AddUserViewModel import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.theme.MyColors data class AddTicketDialogData( val showDialog: Boolean = false, val onDismiss: () -> Unit = {}, - val navToWeight: (String) -> Unit = {}, - - val cardReaderForUserCard: () -> Unit = {}, - val cardReaderForIdCard: () -> Unit = {}, - val cardReaderForBankCard: () -> Unit = {}, - val ocrForIdCard: () -> Unit = {}, val ocrForBankCard: () -> Unit = {}, - val faceRecognition: () -> Unit = {}, ) @Preview(showBackground = true, widthDp = 1280, heightDp = 800) @Composable fun AddTicketDialogPreview() { - AddTicketDialog(AddTicketDialogData(showDialog = true) { - - }) + AddTicketDialog(AddTicketDialogData(showDialog = true)) } @Composable -fun AddTicketDialog( - info: AddTicketDialogData -) { - var successBtnName by remember { mutableStateOf("确定") } +fun AddTicketDialog(info: AddTicketDialogData) { + var successBtnName by remember { mutableStateOf("") } var currentTab by remember { mutableStateOf(0) } MyDialog( "选择查询方式", @@ -85,24 +60,15 @@ fun AddTicketDialog( successBtnName, onClickOK = { when (currentTab) { - 1 -> info.cardReaderForUserCard() - 2 -> info.cardReaderForIdCard() - 3 -> info.ocrForIdCard() - 4 -> info.cardReaderForBankCard() - 5 -> info.ocrForBankCard() - 6 -> info.faceRecognition() + 1 -> info.ocrForIdCard() + 2 -> info.ocrForBankCard() + 3 -> info.faceRecognition() } info.onDismiss() }, ) { VerticalTabPages( - tabs = listOf( - "直接搜索", "刷农户卡", - "刷身份证", "拍身份证", - "刷银行卡", "拍银行卡", - "人脸识别", - /** "随意拍"**/ - ), + tabs = listOf("直接搜索", "拍身份证", "拍银行卡", "人脸识别"), ) { currentTab = it when (it) { @@ -116,46 +82,25 @@ fun AddTicketDialog( 1 -> { successBtnName = "确定" - ReadCard("农户卡") + OCRCard("身份证") } 2 -> { successBtnName = "确定" - ReadCard("身份证") + OCRCard("银行卡") } 3 -> { - successBtnName = "确定" - OCRCard("身份证") - } - - 4 -> { - successBtnName = "确定" - ReadCard("银行卡") - } - - 5 -> { - successBtnName = "确定" - OCRCard("银行卡") - } - - 6 -> { successBtnName = "确定" OCRCard("人脸识别") } - - 7 -> { - // 随意拍 - } } } } } @Composable -fun UserSearch( - onSuccess: (String) -> Unit -) { +fun UserSearch(onSuccess: (String) -> Unit) { Column { var input by rememberSaveable { mutableStateOf("") } MyTextField(modifier = M.padding(vertical = 10.dp), value = input, hint = "用户信息") { @@ -190,30 +135,6 @@ fun UserSearch( } } -@Composable -fun ReadCard(cardName: String) { - MyCard(elevation = 0.dp) { - Box(modifier = M.fillMaxSize(), contentAlignment = Alignment.Center) { - Column( - modifier = M.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Image( - painter = painterResource(id = R.drawable.icon_read_card), - contentDescription = "card", - modifier = M.size(200.dp) - ) - Text( - modifier = M.padding(top = 20.dp), - text = "使用读卡器识别${cardName}", - fontWeight = FontWeight.Bold, - fontSize = MaterialTheme.typography.bodyLarge.fontSize - ) - } - } - } -} - @Composable fun OCRCard(cardName: String) { MyCard(elevation = 0.dp) { @@ -229,11 +150,11 @@ fun OCRCard(cardName: String) { ) Text( modifier = M.padding(top = 20.dp), - text = "拍照识别${cardName}", + text = "拍照识别$cardName", fontWeight = FontWeight.Bold, fontSize = MaterialTheme.typography.bodyLarge.fontSize ) } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/ScanDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/ScanDialog.kt deleted file mode 100644 index f310e59..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/ScanDialog.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.R -import com.bbitcn.f8.pad.base.MyDialog -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.idcard.IDCardUtils -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.nfc.NFCUtils - -data class ScanDialogData( - val showDialog: Boolean = false, - val isNFC: Boolean = false, - val onDismiss: () -> Unit = {} -) - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun ScanPreview() { - ScanDialog(ScanDialogData()) -} - -@Composable -fun ScanDialog(info: ScanDialogData) { - val nfcState by NFCUtils.state.collectAsState() - val idCardState by IDCardUtils.state.collectAsState() - val state = if (info.isNFC) nfcState else idCardState - MyDialog( - if (info.isNFC) "NFC读卡" else "身份证读卡", - info.showDialog, - onDismissRequest = info.onDismiss - ) { - Column( - modifier = M.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - if (state == 0) { - CircularProgressIndicator( - modifier = M.size(80.dp) - ) - } - Image( - painter = painterResource( - id = when (state) { - -1 -> R.drawable.error - else -> R.drawable.success - } - ), - contentDescription = null, - modifier = M - .size(80.dp) - .padding(16.dp) - ) - Text( - text = if (state == 0) { - "正在初始化读卡模块中..." - } else if (state == -1) { - "读卡模块初始化失败,请检查读卡器是否开启" - } else { - "读卡器准备就绪\n" + if (info.isNFC) "请将卡片靠近NFC刷卡模块" else "请将身份证靠近身份证刷卡模块" - }, - modifier = M.padding(16.dp) - ) - } - } -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketAirDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketAirDialog.kt deleted file mode 100644 index ff41434..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketAirDialog.kt +++ /dev/null @@ -1,188 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog.drycocoon - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MyDialog -import com.bbitcn.f8.pad.base.MyTextField -import com.bbitcn.f8.pad.model.net.request.AddDryAirRequest -import com.bbitcn.f8.pad.model.net.response.DryCocoonInType -import com.bbitcn.f8.pad.model.net.response.QueryAllStoreInfoResponse -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.common.CombinedDropdownMenu - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -data class AddDryCocoonTicketAirDialogData( - val showDialog: Boolean = false, - - val SSC: List = listOf(),// 仓库 蚕季 茧别 三级联动数据 - - var cocoonTypeList :List = listOf(), // 蚕品种 - val areaList: List = listOf(), - // 入库包装类型 - val onClickOK: (request: AddDryAirRequest) -> Unit = { _ -> }, - val onDismiss: () -> Unit = {} -) - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun AddDryCocoonTicketAirDialogPreview() { - AddDryCocoonTicketAirDialog(AddDryCocoonTicketAirDialogData(showDialog = true)) -} - -@Composable -fun AddDryCocoonTicketAirDialog(info: AddDryCocoonTicketAirDialogData) { - var request by remember { mutableStateOf(AddDryAirRequest()) } - MyDialog("新增摊晾计划", - info.showDialog, - onDismissRequest = { info.onDismiss() }, - clickOKStr = "确定", - onClickOK = { - if (request.gjcksysid.isEmpty() - || request.cjsysid.isEmpty() - || request.jiantypesysid.isEmpty() - || request.plantime.isEmpty() - ) { - Toasty.showTipsDialog("请填写完整信息") - return@MyDialog - } - info.onClickOK(request) - info.onDismiss() - } - ) { - LaunchedEffect(Unit) { - request = AddDryAirRequest() - } - var season by remember { mutableStateOf("") } - var store by remember { mutableStateOf("") } - var cocoonLevel by remember { mutableStateOf("") } - var cocoonType by remember { mutableStateOf("") } - var seasonList by remember { mutableStateOf(listOf()) } - var cocoonLevelList by remember { mutableStateOf(listOf()) } - val scope = rememberCoroutineScope() - - Row(modifier = M.fillMaxSize()) { - Column( - modifier = M.weight(1f), - verticalArrangement = Arrangement.spacedBy(15.dp) - ) { - CombinedDropdownMenu( - hint = "仓库", - options = info.SSC.map { it.ckname }.distinct(), // 仓库列表 - value = store - ) { sel -> // 当选择仓库时触发 - scope.launch { - withContext(Dispatchers.IO) { - store = sel - // 获取选择的仓库的gjcksysid和ckcode - val selectedStore = info.SSC.find { it.ckname == sel } - // 更新请求数据 - request.gjcksysid = selectedStore?.gjcksysid ?: "" - request.gjckcode = selectedStore?.ckcode ?: "" - - // 更新下级列表 - season = "" - cocoonLevel = "" - seasonList = info.SSC.filter { it.gjcksysid == request.gjcksysid } - .map { it.cjname } - .distinct() - cocoonLevelList = emptyList() - } - } - } - CombinedDropdownMenu( - hint = "蚕季", - options = seasonList, // 动态生成的蚕季列表 - value = season - ) { sel -> // 当选择蚕季时触发 - scope.launch { - withContext(Dispatchers.IO) { - season = sel - - // 获取选择了仓库和蚕季的数据 - val selectedSeason = - info.SSC.find { it.cjname == sel && it.gjcksysid == request.gjcksysid } - request.cjsysid = selectedSeason?.cjsysid ?: "" - - // 更新茧别列表 - cocoonLevel = "" - cocoonLevelList = - info.SSC.filter { - it.gjcksysid == request.gjcksysid && // 筛选仓库 - it.cjsysid == selectedSeason?.cjsysid // 筛选蚕季 - } - .map { it.jiantypename } - .distinct() - } - } - } - CombinedDropdownMenu( - hint = "茧别", - options = cocoonLevelList, // 动态生成的茧别列表 - value = cocoonLevel - ) { sel -> // 当选择茧别时触发 - cocoonLevel = sel - val selectedCocoonLevel = - info.SSC.find { it.jiantypename == sel && it.gjcksysid == request.gjcksysid && it.cjsysid == request.cjsysid } - request.jiantypesysid = selectedCocoonLevel?.jiantypesysid ?: "" - request.jiantype = selectedCocoonLevel?.jiantypename ?: "" - } - CombinedDropdownMenu( - hint = "蚕品种", - options = info.cocoonTypeList.map { it.name }, - value = cocoonType - ) { sel -> // 当选择茧别时触发 - cocoonType = sel - request.canpinzhong = sel - } - } - VerticalDivider( - modifier = M - .fillMaxHeight() - .padding(horizontal = 10.dp), - ) - Column( - modifier = M.weight(1f), - verticalArrangement = Arrangement.spacedBy(15.dp) - ) { - var operater by remember { mutableStateOf("") } - var time by remember { mutableStateOf("") } - var area by remember { mutableStateOf("") } - CombinedDropdownMenu( - hint = "区域", - options = info.areaList.map { it }, - value = area - ) { sel -> - area = sel - request.xiangzhen = sel - } - MyTextField(hint = "摊晾人", value = operater) { - operater = it - request.tanliangren = it - } - MyTextField(hint = "计划摊晾时间", value = time, isSelectDate = true,) { - time = it - request.plantime = it - } - } - } - } -} - diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketInDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketInDialog.kt deleted file mode 100644 index 52c4a08..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketInDialog.kt +++ /dev/null @@ -1,206 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog.drycocoon - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MyCheckBox -import com.bbitcn.f8.pad.base.MyDialog -import com.bbitcn.f8.pad.base.MyTextField -import com.bbitcn.f8.pad.model.net.request.AddDryInRequest -import com.bbitcn.f8.pad.model.net.response.DryCocoonAreaResponse -import com.bbitcn.f8.pad.model.net.response.DryCocoonInLevel -import com.bbitcn.f8.pad.model.net.response.DryCocoonInPackageType -import com.bbitcn.f8.pad.model.net.response.DryCocoonSeason -import com.bbitcn.f8.pad.model.net.response.DryCocoonInStore -import com.bbitcn.f8.pad.model.net.response.DryCocoonInType -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.common.CombinedDropdownMenu - - -data class AddDryCocoonTicketInDialogData( - val showDialog: Boolean = false, - - val defaultStoreName: String = "", - - val season: List = listOf(), - val store: List = listOf(), - val cocoonType: List = listOf(), - val cocoonLevel: List = listOf(), - val packageType: List = listOf(), - - val areaList: List = listOf(), - - // 入库包装类型 - val onClickOK: (request: AddDryInRequest, cocoonLevel: String, store: String, cocoonType: String) -> Unit = { _, _, _, _ -> }, - val onDismiss: () -> Unit = {} -) - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun AddDryCocoonTicketDialogPreview() { - AddDryCocoonTicketInDialog(AddDryCocoonTicketInDialogData(showDialog = true)) -} - -@Composable -fun AddDryCocoonTicketInDialog(info: AddDryCocoonTicketInDialogData) { - var request by remember { mutableStateOf(AddDryInRequest()) } - var cocoonType by remember { mutableStateOf("") } - var cocoonLevel by remember { mutableStateOf("") } - var store by remember { mutableStateOf("") } - var season by remember { mutableStateOf("") } - MyDialog( - "新增入库单据", - info.showDialog, - onDismissRequest = { info.onDismiss() }, - clickOKStr = "确定", - onClickOK = { - if (cocoonLevel.isEmpty() - || store.isEmpty() - || request.bagtype.isEmpty() - || request.rukutype == -1 - || request.canpinzhong.isEmpty() - ) { - Toasty.showTipsDialog("请填写完整信息") - return@MyDialog - } - info.onClickOK(request, cocoonLevel, store, cocoonType) - info.onDismiss() - } - ) { - LaunchedEffect(Unit) { - request = AddDryInRequest() - cocoonLevel = "" - - // 默认仓库 - val sel = info.store.find { it.cangkuname == info.defaultStoreName } - request.gjcksysid = sel?.sysid ?: "" - request.gjckcode = sel?.cangkucode ?: "" - store = info.defaultStoreName - - // 默认蚕季 - val defSeason = info.season.firstOrNull { it.def == 1 } - season = defSeason?.batchname ?: "" - request.cjsysid = defSeason?.sysid ?: "" - cocoonType = "" - } - var packageType by remember { mutableStateOf("") } - var inType by remember { mutableStateOf("") } - var isStandard by remember { mutableStateOf(true) } - var operatorName by remember { mutableStateOf("") } - var dryingPersonName by remember { mutableStateOf("") } - var area by remember { mutableStateOf("") } - Row(modifier = M.fillMaxSize()) { - Column( - modifier = M.weight(1f), - verticalArrangement = Arrangement.spacedBy(15.dp) - ) { - CombinedDropdownMenu( - hint = "仓库", - options = info.store.map { it.cangkuname }, - value = store - ) { sel -> - store = sel - request.gjcksysid = info.store.find { it.cangkuname == sel }?.sysid ?: "" - request.gjckcode = info.store.find { it.cangkuname == sel }?.cangkucode ?: "" - } - CombinedDropdownMenu( - hint = "蚕季", - options = info.season.map { it.batchname }, - value = season - ) { sel -> - season = sel - request.cjsysid = info.season.find { it.batchname == sel }?.sysid ?: "" - } - CombinedDropdownMenu( - hint = "茧别", - options = info.cocoonLevel.map { it.name }, - value = cocoonLevel - ) { sel -> - cocoonLevel = sel - val selCocoonLevel = info.cocoonLevel.find { it.name == sel } - request.jiantypesysid = selCocoonLevel?.sysid ?: "" - request.jiantype = selCocoonLevel?.name ?: "" - } - CombinedDropdownMenu( - hint = "包装", - options = info.packageType.map { it.name }, - value = packageType - ) { sel -> - packageType = sel - request.bagtype = info.packageType.find { it.name == sel }?.name ?: "" - request.bagzhongliang = info.packageType.find { it.name == sel }?.weight ?: 0.0 - } - CombinedDropdownMenu( - hint = "入库类型", - options = listOf("烘茧入库", "翻包摊晾", "出库盈余"), - value = inType - ) { sel -> - inType = sel - request.rukutype = when (sel) { - "烘茧入库" -> 0 - "翻包摊晾" -> 1 - "出库盈余" -> 2 - else -> 0 - } - } - MyCheckBox("采用标准包", isStandard) { - isStandard = it - request.standardtype = if (isStandard) 1 else -1 - } - } - VerticalDivider( - modifier = M - .fillMaxHeight() - .padding(horizontal = 10.dp), - ) - Column( - modifier = M.weight(1f), - verticalArrangement = Arrangement.spacedBy(15.dp) - ) { - CombinedDropdownMenu( - hint = "蚕品种", - options = info.cocoonType.map { it.name }, - value = cocoonType - ) { sel -> - cocoonType = sel - request.canpinzhong = sel - } - CombinedDropdownMenu( - hint = "区域", - options = info.areaList.map { it }, - value = area - ) { sel -> - area = sel - request.xiangzhen = sel - } - MyTextField(hint = "烘茧人", value = dryingPersonName) { - dryingPersonName = it - request.hongjianren = it - } - CombinedDropdownMenu( - hint = "审批人", - options = listOf(), - isEditable = true, - value = operatorName - ) { input -> - operatorName = input - request.rukuren = input - } - } - } - } -} - diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketOutDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketOutDialog.kt deleted file mode 100644 index 7badd2a..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/AddDryCocoonTicketOutDialog.kt +++ /dev/null @@ -1,228 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog.drycocoon - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MyDialog -import com.bbitcn.f8.pad.base.MyTextField -import com.bbitcn.f8.pad.model.net.request.AddDryOutRequest -import com.bbitcn.f8.pad.model.net.response.DryCocoonAreaResponse -import com.bbitcn.f8.pad.model.net.response.DryCocoonDealObjectResponse -import com.bbitcn.f8.pad.model.net.response.DryCocoonInPackageType -import com.bbitcn.f8.pad.model.net.response.DryCocoonInType -import com.bbitcn.f8.pad.model.net.response.QueryAllStoreInfoResponse -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.common.CombinedDropdownMenu - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -data class AddDryCocoonTicketOutDialogData( - val showDialog: Boolean = false, - - val SSC: List = listOf(),// 仓库 蚕季 茧别 三级联动数据 - - val packageType: List = listOf(), - val dealObject: List = listOf(), - - var cocoonTypeList: List = listOf(), // 蚕品种 - var areaList: List = listOf(), // 区域 - - // 入库包装类型 - val onClickOK: (request: AddDryOutRequest) -> Unit = { _ -> }, - val onDismiss: () -> Unit = {} -) - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun AddDryCocoonTicketOutDialogPreview() { - AddDryCocoonTicketOutDialog(AddDryCocoonTicketOutDialogData(showDialog = true)) -} - -@Composable -fun AddDryCocoonTicketOutDialog(info: AddDryCocoonTicketOutDialogData) { - var request by remember { mutableStateOf(AddDryOutRequest()) } - MyDialog( - "新增出库单据", - info.showDialog, - onDismissRequest = { info.onDismiss() }, - clickOKStr = "确定", - onClickOK = { - if (request.gjcksysid.isEmpty() - || request.cjsysid.isEmpty() - || request.jiantypesysid.isEmpty() - || request.wldwsysid.isEmpty() - || request.bagtype.isEmpty() - ) { - Toasty.showTipsDialog("请填写完整信息") - return@MyDialog - } - info.onClickOK(request) - info.onDismiss() - } - ) { - LaunchedEffect(Unit) { - request = AddDryOutRequest() - } - var season by remember { mutableStateOf("") } - var store by remember { mutableStateOf("") } - var cocoonLevel by remember { mutableStateOf("") } - var packageType by remember { mutableStateOf("") } - var cocoonType by remember { mutableStateOf("") } - var area by remember { mutableStateOf("") } - var dealObject by remember { mutableStateOf("") } - - var seasonList by remember { mutableStateOf(listOf()) } - var cocoonLevelList by remember { mutableStateOf(listOf()) } - - val scope = rememberCoroutineScope() - - Row(modifier = M.fillMaxSize()) { - Column( - modifier = M.weight(1f), - verticalArrangement = Arrangement.spacedBy(15.dp) - ) { - CombinedDropdownMenu( - hint = "仓库", - options = info.SSC.map { it.ckname }.distinct(), // 仓库列表 - value = store - ) { sel -> // 当选择仓库时触发 - scope.launch { - withContext(Dispatchers.IO) { - store = sel - // 获取选择的仓库的gjcksysid和ckcode - val selectedStore = info.SSC.find { it.ckname == sel } - // 更新请求数据 - request.gjcksysid = selectedStore?.gjcksysid ?: "" - request.gjckcode = selectedStore?.ckcode ?: "" - - // 更新下级列表 - season = "" - cocoonLevel = "" - seasonList = info.SSC.filter { it.gjcksysid == request.gjcksysid } - .map { it.cjname } - .distinct() - cocoonLevelList = emptyList() - } - } - } - CombinedDropdownMenu( - hint = "蚕季", - options = seasonList, // 动态生成的蚕季列表 - value = season - ) { sel -> // 当选择蚕季时触发 - scope.launch { - withContext(Dispatchers.IO) { - season = sel - - // 获取选择了仓库和蚕季的数据 - val selectedSeason = - info.SSC.find { it.cjname == sel && it.gjcksysid == request.gjcksysid } - request.cjsysid = selectedSeason?.cjsysid ?: "" - - // 更新茧别列表 - cocoonLevel = "" - cocoonLevelList = - info.SSC.filter { - it.gjcksysid == request.gjcksysid && // 筛选仓库 - it.cjsysid == selectedSeason?.cjsysid // 筛选蚕季 - } - .map { it.jiantypename } - .distinct() - } - } - } - CombinedDropdownMenu( - hint = "茧别", - options = cocoonLevelList, // 动态生成的茧别列表 - value = cocoonLevel - ) { sel -> // 当选择茧别时触发 - cocoonLevel = sel - val selectedCocoonLevel = - info.SSC.find { it.jiantypename == sel && it.gjcksysid == request.gjcksysid && it.cjsysid == request.cjsysid } - request.jiantypesysid = selectedCocoonLevel?.jiantypesysid ?: "" - request.jiantype = selectedCocoonLevel?.jiantypename ?: "" - } - CombinedDropdownMenu( - hint = "蚕品种", - options = info.cocoonTypeList.map { it.name }, - value = cocoonType - ) { sel -> - cocoonType = sel - request.canpinzhong = sel - } - CombinedDropdownMenu( - hint = "区域", - options = info.areaList.map { it }, - value = area - ) { sel -> - area = sel - request.xiangzhen = sel - } - } - VerticalDivider( - modifier = M - .fillMaxHeight() - .padding(horizontal = 10.dp), - ) - Column( - modifier = M.weight(1f), - verticalArrangement = Arrangement.spacedBy(15.dp) - ) { - CombinedDropdownMenu( - hint = "往来单位", - options = info.dealObject.map { it.name }, - value = dealObject - ) { sel -> - dealObject = sel - request.wldwsysid = info.dealObject.find { it.name == sel }?.sysid ?: "" - } - CombinedDropdownMenu( - hint = "包装", - options = info.packageType.map { it.name }, - value = packageType - ) { sel -> - packageType = sel - request.bagtype = info.packageType.find { it.name == sel }?.name ?: "" - request.bagzhongliang = info.packageType.find { it.name == sel }?.weight ?: 0.0 - } - var pickUpPerson by remember { mutableStateOf("") } - var licensePlate by remember { mutableStateOf("") } - var shipper by remember { mutableStateOf("") } - var remark by remember { mutableStateOf("") } - MyTextField(hint = "车牌号", value = licensePlate) { - licensePlate = it - request.carpaihao = it - } - MyTextField(hint = "提货人", value = pickUpPerson) { - pickUpPerson = it - request.tihuoren = it - } - MyTextField(hint = "出库人", value = shipper) { - shipper = it - request.chukuren = it - } - MyTextField(hint = "备注", value = remark) { - remark = it - request.memo = it - } - } - } - } -} - diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonFilterDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonFilterDialog.kt deleted file mode 100644 index fddf31a..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonFilterDialog.kt +++ /dev/null @@ -1,131 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog.drycocoon - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.material3.VerticalDivider -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MyButton -import com.bbitcn.f8.pad.base.MyDialog -import com.bbitcn.f8.pad.ui.screen.secondFunc.AddDryCocoonBaseViewModel -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -import com.bbitcn.f8.pad.ui.theme.MyColors -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import kotlinx.coroutines.flow.flowOf - - -data class DryCocoonFilterDialogData( - val showDialog: Boolean = false, - val viewModel: AddDryCocoonBaseViewModel, - val myCardReaderShowViewModel: MyCardReaderShowViewModel, - val onDismiss: () -> Unit = {} -) - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun DryCocoonFilterDialogPreview() { - DryCocoonFilterDialog(DryCocoonFilterDialogData(showDialog = true, viewModel(), viewModel())) -} - -@Composable -fun DryCocoonFilterDialog( - info: DryCocoonFilterDialogData, -) { - val curReader by info.myCardReaderShowViewModel.curDevice.collectAsState() - val tagIds by (curReader?.tagList - ?: flowOf(emptyList())).collectAsState(initial = emptyList()) - MyDialog( - "茧包过滤", - info.showDialog, - onDismissRequest = { - info.onDismiss() - }, "添加到过滤列表", { - info.viewModel.confirmTagIds(tagIds) { - info.myCardReaderShowViewModel.clearList() - } - } - ) { - LaunchedEffect(Unit) { - info.myCardReaderShowViewModel.clearList() - } - Row { - LazyColumn( - modifier = M - .weight(1f) - .fillMaxHeight() - .padding(start = 10.dp), - ) { - item { - Row( - modifier = M - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text("当前茧包") - MyButton( text = "重新检测") { - info.myCardReaderShowViewModel.clearList() - } - } - HorizontalDivider(modifier = M.padding(vertical = 5.dp)) - if (curReader == null) { - Text( - "未检测到读卡器", - color = MyColors.Red, - fontSize = MaterialTheme.typography.bodyMedium.fontSize - ) - } - } - items(tagIds.toList()) { - PackageLossInfo(M, it) - } - } - VerticalDivider(modifier = M.padding(horizontal = 5.dp)) - val forceItems by info.viewModel.forceFilterTags.collectAsState() - LazyColumn( - modifier = M - .weight(1f) - .fillMaxHeight() - .padding(end = 10.dp), - ) { - item { - Row( - modifier = M - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text("过滤列表") - MyButton( - text = "删除列表", - modifier = M.padding(end = 10.dp) - ) { - info.viewModel.clearForceHadHandleTagIds() - } - } - HorizontalDivider(modifier = M.padding(vertical = 5.dp)) - } - items(forceItems.toList()) { - PackageLossInfo(M, it) - } - } - } - } -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonInfoQueryDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonInfoQueryDialog.kt deleted file mode 100644 index c491098..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonInfoQueryDialog.kt +++ /dev/null @@ -1,142 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog.drycocoon - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.InfoText -import com.bbitcn.f8.pad.base.MyButton -import com.bbitcn.f8.pad.base.MyCard -import com.bbitcn.f8.pad.base.MyDialog -import com.bbitcn.f8.pad.model.net.response.SearchOutDetailByRFIDResponse -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -import com.bbitcn.f8.pad.ui.theme.MyColors -import kotlinx.coroutines.flow.flowOf - - -data class DryCocoonInfoQueryDialogData( - val showDialog: Boolean = false, - val cjsysid: String = "", - val jiantypesysid: String = "", - val gjcksysid: String = "", - val printTicket: (sysId: String) -> Unit = {}, - val onDismiss: () -> Unit = {} -) - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun DryCocoonInfoQueryDialogPreview() { - DryCocoonInfoQueryDialog(DryCocoonInfoQueryDialogData(showDialog = true)) -} - -@Composable -fun DryCocoonInfoQueryDialog( - info: DryCocoonInfoQueryDialogData, -) { - MyDialog( - "查询茧包信息", - info.showDialog, - onDismissRequest = { - info.onDismiss() - } - ) { - val myCardReaderShowViewModel: MyCardReaderShowViewModel = viewModel() - val viewModel: DryCocoonInfoQueryViewModel = viewModel() - - val curReader by myCardReaderShowViewModel.curDevice.collectAsState() - val tagIds by (curReader?.tagList - ?: flowOf(emptyList())).collectAsState(initial = emptyList()) - val items by viewModel.list.collectAsState() - LaunchedEffect(Unit) { - myCardReaderShowViewModel.clearList() - viewModel.clearRfidInfo() - } - LaunchedEffect(tagIds) { - viewModel.refreshRfidInfo(tagIds, info) - } - LazyColumn( - modifier = M - .fillMaxSize() - .padding(10.dp), - ) { - item { - Row( - modifier = M - .padding(bottom = 5.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - if (curReader == null) { - Text( - "未检测到读卡器", - color = MyColors.Red, - fontSize = MaterialTheme.typography.bodyMedium.fontSize - ) - } else { - Text("检测到的茧包芯片:") - MyButton(text = "重新检测茧包") { - viewModel.clearRfidInfo() - myCardReaderShowViewModel.clearList() - } - } - } - } - items(items) { - PackageLossInfoS(it) { - info.printTicket(it) - } - } - } - } -} - -@Composable -fun PackageLossInfoS( - info: Pair, - printTicket: (sysId: String) -> Unit, -) { - MyCard(modifier = M.padding(10.dp)) { - Row(modifier = M.padding(5.dp), verticalAlignment = Alignment.CenterVertically) { - Column( - modifier = M - .weight(1f) - .padding(5.dp) - ) { - Row(verticalAlignment = Alignment.CenterVertically) { - InfoText("茧包芯片", info.first, M.weight(2f), true) - InfoText("包码", info.second.code, M.weight(2f), true) - } - Row(verticalAlignment = Alignment.CenterVertically) { - InfoText("毛重", info.second.maozhong.toString(), M.weight(1f), true) - InfoText("皮重", info.second.pizhong.toString(), M.weight(1f), true) - InfoText("净重", info.second.jingzhong.toString(), M.weight(1f), true) - InfoText( - "已出库", - if (info.second.ischuku == 1) "是" else "否", - M.weight(1f), - true - ) - } - } - MyButton(text = "补打茧票") { - printTicket(info.second.sysid) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonInfoQueryViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonInfoQueryViewModel.kt deleted file mode 100644 index 2b038a3..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonInfoQueryViewModel.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog.drycocoon - -import com.bbitcn.f8.pad.base.BaseViewModel -import com.bbitcn.f8.pad.model.net.request.SearchOutDetailByRFIDRequest -import com.bbitcn.f8.pad.model.net.response.SearchOutDetailByRFIDResponse -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update - -class DryCocoonInfoQueryViewModel : BaseViewModel() { - - private val _list = MutableStateFlow>>(emptyList()) - val list = _list.asStateFlow() - - // 已经请求过的tagId - private val fetchedIds = mutableSetOf() - - fun refreshRfidInfo(ids: List, info: DryCocoonInfoQueryDialogData) { - doInIoThreadNoDialog { - val newIds = ids.filterNot { fetchedIds.contains(it) } - newIds.forEach { id -> - fetchedIds.add(id) - val searchResponse = apiService.searchOutDetailByRFID( - SearchOutDetailByRFIDRequest( - rfid = id, - cjsysid = info.cjsysid, - jiantypesysid = info.jiantypesysid, - gjcksysid = info.gjcksysid - ) - ) - if (searchResponse.code != 1) { - Toasty.showTipsDialog(searchResponse.msg) - } else { - _list.update { it + (id to searchResponse.data) } - } - } - } - } - - fun clearRfidInfo() { - doInIoThreadNoDialog { - fetchedIds.clear() - _list.value = emptyList() - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonLossDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonLossDialog.kt deleted file mode 100644 index a5226f4..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonLossDialog.kt +++ /dev/null @@ -1,174 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog.drycocoon - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.bbitcn.f8.pad.IS_DEBUG_DRYCOCOON -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MyButton -import com.bbitcn.f8.pad.base.MyCard -import com.bbitcn.f8.pad.base.MyDialog -import com.bbitcn.f8.pad.model.net.response.DryCocoonSeason -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.common.CombinedDropdownMenu -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -import com.bbitcn.f8.pad.ui.theme.MyColors -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial -import kotlinx.coroutines.flow.flowOf - - -data class DryCocoonLossDialogData( - val showDialog: Boolean = false, - val seasonList: List = listOf(), - val onLossPackage: (rfids: List, seasonSysId: String, onFinished: () -> Unit) -> Unit = { _, _, _ -> }, - val onDismiss: () -> Unit = {} -) - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun DryCocoonLossDialogPreview() { - DryCocoonLossDialog(DryCocoonLossDialogData(showDialog = true)) -} - -@Composable -fun DryCocoonLossDialog( - info: DryCocoonLossDialogData, - myCardReaderShowViewModel: MyCardReaderShowViewModel = viewModel(), -) { - val curReader by myCardReaderShowViewModel.curDevice.collectAsState() - val tagIds by (curReader?.tagList - ?: flowOf(emptyList())).collectAsState(initial = emptyList()) - var season by remember { mutableStateOf("") } - MyDialog( - "空包释放-出库", - info.showDialog, - onDismissRequest = { - info.onDismiss() - // 关闭弹窗后关闭超高频读卡器 - UHFReaderForSerial.stopAllScan() - }, - "全部释放", { - if (tagIds.isEmpty()) { - Toasty.showTipsDialog("未检测到茧包") - } else if (season.isEmpty()) { - Toasty.showTipsDialog("请先选择空包所属蚕季") - } else { - val seasonSysId = info.seasonList.first { it.batchname == season }.sysid - info.onLossPackage(tagIds, seasonSysId) { - myCardReaderShowViewModel.clearList() - } - } - } - ) { - LaunchedEffect(Unit) { - myCardReaderShowViewModel.clearList() - UHFReaderForSerial.startAllScan() - } - LazyColumn( - modifier = M - .fillMaxSize() - .padding(10.dp), - ) { - item { - Row( - modifier = M.padding(bottom = 10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text("空包所属蚕季:") - CombinedDropdownMenu( - hint = "蚕季", - options = info.seasonList.map { it.batchname }, // 动态生成的蚕季列表 - value = season - ) { sel -> // 当选择蚕季时触发 - season = sel - } - } - if (IS_DEBUG_DRYCOCOON) { - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton(text = "增加随机芯片") { - UHFReaderG06M_G25M.testXP() - } - MyButton(text = "测试增加芯片1") { - UHFReaderG06M_G25M.testXP("521323232") - } - } - } - Row( - modifier = M - .padding(bottom = 5.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - if (curReader == null) { - Text( - "未检测到读卡器", - color = MyColors.Red, - fontSize = MaterialTheme.typography.bodyMedium.fontSize - ) - } else { - Text("检测到的茧包芯片:") - MyButton(text = "重新检测茧包") { - myCardReaderShowViewModel.clearList() - } - } - } - } - items(tagIds, key = { it }) { tag -> - PackageLossInfo(M,tag) - } - } - } -} - -@Composable -fun PackageLossInfo(modifier: Modifier, rfid: String) { - MyCard(modifier = modifier.padding(10.dp)) { - Column( - modifier = M - .fillMaxWidth() - .padding(5.dp) - ) { - Row( - modifier = M - .padding(vertical = 3.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = "茧包芯片:", - color = MyColors.Gray, - fontSize = MaterialTheme.typography.bodyMedium.fontSize - ) - Text( - modifier = M.padding(start = 5.dp), - text = rfid, - fontSize = MaterialTheme.typography.bodyMedium.fontSize - ) - } - } - } -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonLossDialogInOut.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonLossDialogInOut.kt deleted file mode 100644 index bcaddd4..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonLossDialogInOut.kt +++ /dev/null @@ -1,127 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.dialog.drycocoon - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.bbitcn.f8.pad.IS_DEBUG_DRYCOCOON -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MyButton -import com.bbitcn.f8.pad.base.MyCard -import com.bbitcn.f8.pad.base.MyDialog -import com.bbitcn.f8.pad.model.net.response.DryCocoonSeason -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.common.CombinedDropdownMenu -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -import com.bbitcn.f8.pad.ui.theme.MyColors -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial -import kotlinx.coroutines.flow.flowOf - - -data class DryCocoonLossDialogInOutData( - val showDialog: Boolean = false, - val onLossPackage: (rfids: List, onFinished: () -> Unit) -> Unit = { _, _ -> }, - val onDismiss: () -> Unit = {} -) - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun DryCocoonLossDialogInOutPreview() { - DryCocoonLossDialogInOut(DryCocoonLossDialogInOutData(showDialog = true)) -} - -@Composable -fun DryCocoonLossDialogInOut( - info: DryCocoonLossDialogInOutData, - myCardReaderShowViewModel: MyCardReaderShowViewModel = viewModel(), -) { - val curReader by myCardReaderShowViewModel.curDevice.collectAsState() - val tagIds by (curReader?.tagList - ?: flowOf(emptyList())).collectAsState(initial = emptyList()) - MyDialog( - "空包释放-出库", - info.showDialog, - onDismissRequest = { - info.onDismiss() - // 关闭弹窗后关闭超高频读卡器 - UHFReaderForSerial.stopAllScan() - }, - "全部释放", { - if (tagIds.isEmpty()) { - Toasty.showTipsDialog("未检测到茧包") - } else { - info.onLossPackage(tagIds) { - myCardReaderShowViewModel.clearList() - } - } - } - ) { - LaunchedEffect(Unit) { - myCardReaderShowViewModel.clearList() - UHFReaderForSerial.startAllScan() - } - LazyColumn( - modifier = M - .fillMaxSize() - .padding(10.dp), - ) { - item { - Row( - modifier = M - .padding(bottom = 5.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - if (curReader == null) { - Text( - "未检测到读卡器", - color = MyColors.Red, - fontSize = MaterialTheme.typography.bodyMedium.fontSize - ) - } else { - Text("检测到的茧包芯片:") - MyButton(text = "重新检测茧包") { - myCardReaderShowViewModel.clearList() - } - } - } - if (IS_DEBUG_DRYCOCOON) { - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton(text = "增加随机芯片") { - UHFReaderG06M_G25M.testXP() - } - MyButton(text = "测试增加芯片1") { - UHFReaderG06M_G25M.testXP("521323232") - } - } - } - } - items(tagIds, key = { it }) { tag -> - PackageLossInfo(M, tag) - } - } - } -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonRefreshDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonRefreshDialog.kt deleted file mode 100644 index 63b03be..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/drycocoon/DryCocoonRefreshDialog.kt +++ /dev/null @@ -1,186 +0,0 @@ -//package com.bbitcn.f8.pad.ui.screen.dialog -// -//import androidx.compose.foundation.layout.Arrangement -//import androidx.compose.foundation.layout.Column -//import androidx.compose.foundation.layout.Row -//import androidx.compose.foundation.layout.fillMaxSize -//import androidx.compose.foundation.layout.fillMaxWidth -//import androidx.compose.foundation.layout.padding -//import androidx.compose.runtime.Composable -//import androidx.compose.runtime.LaunchedEffect -//import androidx.compose.runtime.collectAsState -//import androidx.compose.runtime.getValue -//import androidx.compose.runtime.mutableStateOf -//import androidx.compose.runtime.saveable.rememberSaveable -//import androidx.compose.runtime.setValue -//import androidx.compose.ui.Alignment -//import androidx.compose.ui.tooling.preview.Preview -//import androidx.compose.ui.unit.dp -//import androidx.lifecycle.viewmodel.compose.viewModel -//import com.bbitcn.f8.pad.M -//import com.bbitcn.f8.pad.base.InfoText -//import com.bbitcn.f8.pad.base.MyButton -//import com.bbitcn.f8.pad.base.MyCard -//import com.bbitcn.f8.pad.base.MyDialog -//import com.bbitcn.f8.pad.model.net.request.DryCocoonRefreshStartRequest -//import com.bbitcn.f8.pad.model.net.request.DryCocoonRefreshStopRequest -//import com.bbitcn.f8.pad.ui.screen.mainFunc.DryCocoonViewModel -//import com.bbitcn.f8.pad.ui.screen.secondFunc.DryCocoonInfo -//import com.bbitcn.f8.pad.ui.screen.view.Toasty -//import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -//import com.bbitcn.f8.pad.ui.screen.view.deviceManager.scale.MyWeightShow -//import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial -//import kotlinx.coroutines.flow.flowOf -// -// -//data class DryCocoonRefreshDialogData( -// val showDialog: Boolean = false, -// // 包装类型 -//// val packageType: List = listOf(), -// val onDismiss: () -> Unit = {} -//) -// -//@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -//@Composable -//fun DryCocoonRefreshDialogPreview() { -// DryCocoonRefreshDialog(DryCocoonRefreshDialogData(showDialog = true)) -//} -// -//@Composable -//fun DryCocoonRefreshDialog( -// info: DryCocoonRefreshDialogData, -// dryCocoonViewModel: DryCocoonViewModel = viewModel(), -// myCardReaderShowViewModel: MyCardReaderShowViewModel = viewModel(), -//) { -// var grossWeight by rememberSaveable { mutableStateOf(0.0) } -// val curReader by myCardReaderShowViewModel.curDevice.collectAsState() -// -// val tagIds by (curReader?.tagList -// ?: flowOf(emptyList())).collectAsState(initial = emptyList()) -// var weightErrorMsg = "" -// val tagErrorMsg = if (curReader == null) "未检测到读卡器" -// else if (tagIds.isEmpty()) "未检测到麻袋" -// else if (tagIds.size > 1) "检测到多个麻袋" -// else "" -// val allErrorMsg = if (tagErrorMsg.isNotEmpty()) tagErrorMsg + "\n" else "" + -// if (weightErrorMsg.isNotEmpty()) weightErrorMsg + "\n" else "" -// -// val tagIdTemp = if (tagIds.isNotEmpty()) tagIds[0] else "" -// var tagId by rememberSaveable { mutableStateOf("") } -// -// val state by dryCocoonViewModel.curPackageState.collectAsState() -// -// val ticketInfo by dryCocoonViewModel.ticketInfo.collectAsState() -// MyDialog("翻包摊晾", -// info.showDialog,{ -// info.onDismiss() -// // 关闭弹窗后关闭超高频读卡器 -// UHFReaderForSerial.stopAllScan() -// }, -// state, { -// if (allErrorMsg.isEmpty()) { -// if (state == "开始翻包") { -// dryCocoonViewModel.onRefreshStart( -// DryCocoonRefreshStartRequest( -// code = ticketInfo.code, -// kcmaozhong = ticketInfo.kcmaozhong, -// maozhong = grossWeight.toString(), -// rfid = tagId, -// rkitemsysid = ticketInfo.sysid -// ) -// ) { -// myCardReaderShowViewModel.clearList() -// } -// } else { -// dryCocoonViewModel.onRefreshStop( -// DryCocoonRefreshStopRequest( -// maozhong = grossWeight.toString(), -// rfid = tagId -// ) -// ) { -// myCardReaderShowViewModel.clearList() -// } -// } -// } else { -// Toasty.showTipsDialog(allErrorMsg) -// } -// } -// ) { -// LaunchedEffect(Unit) { -// // 修复刚进入页面时,tagIdTemp不为空,但tagId为空进而触发刷新getPackageInfo的问题 -// tagId = tagIdTemp -// myCardReaderShowViewModel.clearList() -// UHFReaderForSerial.startAllScan() -// } -// // 只有在弹窗打开时才检测 -// LaunchedEffect(tagIdTemp) { -// if (tagIdTemp.isNotEmpty() && tagIdTemp != tagId) { -// // 检测到新芯片 -// tagId = tagIdTemp -// dryCocoonViewModel.getPackageInfo(tagId) -// } else { -// // 清空数据 -// tagId = tagIdTemp -// dryCocoonViewModel.clearPackageInfo() -// } -// } -// Row( -// modifier = M -// .fillMaxSize() -// .padding(10.dp), -// horizontalArrangement = Arrangement.spacedBy(10.dp) -// ) { -// MyCard( -// modifier = M -// .weight(1f), -// elevation = 2.dp -// ) { -// Column( -// modifier = M -// .fillMaxSize() -// .padding(10.dp), -// verticalArrangement = Arrangement.spacedBy(10.dp), -// horizontalAlignment = Alignment.End -// ) { -// MyWeightShow(onErrorMsg = { -// weightErrorMsg = it -// }) { -// grossWeight = it -// } -// val showTagId = if (tagId == "") "" -// else "${tagId.take(2)}...${tagId.takeLast(4)}" -// DryCocoonInfo("麻袋ID", showTagId, tagErrorMsg) -// MyButton(modifier = M.fillMaxWidth(), text = "重新检测茧包") { -// tagId = "" -// myCardReaderShowViewModel.clearList() -// } -// } -// } -// MyCard( -// modifier = M -// .weight(1f), -// elevation = 2.dp -// ) { -// Column( -// modifier = M -// .fillMaxSize() -// .padding(20.dp), -// horizontalAlignment = Alignment.Start, -// verticalArrangement = Arrangement.spacedBy(10.dp) -// ) { -// InfoText("包码:", ticketInfo.code) -// InfoText("蚕季:", ticketInfo.cjname) -// InfoText("仓库:", ticketInfo.ckname) -// InfoText("茧别:", ticketInfo.jiantypename) -// InfoText("包装:", ticketInfo.bagtype) -// val packageWeight = -// if (ticketInfo.bagzhongliang == 0.0) "" else ticketInfo.bagzhongliang.toString() -// InfoText("包装重量(kg):", packageWeight) -// val storeWeight = -// if (ticketInfo.kcmaozhong == 0.0) "" else ticketInfo.kcmaozhong.toString() -// InfoText("库存重量(kg):", storeWeight) -// } -// } -// } -// } -//} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/DryCoCoonScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/DryCoCoonScreen.kt index 4023b9e..2707694 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/DryCoCoonScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/DryCoCoonScreen.kt @@ -28,7 +28,6 @@ import androidx.paging.compose.collectAsLazyPagingItems import com.bbitcn.f8.pad.M import com.bbitcn.f8.pad.base.DateRangePickTextFiled import com.bbitcn.f8.pad.base.MainFuncFrame -import com.bbitcn.f8.pad.base.MyButton import com.bbitcn.f8.pad.base.MyCard import com.bbitcn.f8.pad.base.MyRefreshTable import com.bbitcn.f8.pad.base.MyScrollableTabRow @@ -42,11 +41,7 @@ import com.bbitcn.f8.pad.model.net.response.DryCocoonOutListResponse import com.bbitcn.f8.pad.model.net.response.DryCocoonAirListResponse import com.bbitcn.f8.pad.model.net.response.DryStoreListRequest import com.bbitcn.f8.pad.model.net.response.DryStoreListResponse -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.AddDryCocoonTicketAirDialog -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.AddDryCocoonTicketInDialog -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.AddDryCocoonTicketOutDialog import com.bbitcn.f8.pad.ui.screen.dialog.DateRangeSelectDialog -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.DryCocoonLossDialog import com.bbitcn.f8.pad.ui.screen.view.drawer.DrawerViewModel import com.bbitcn.f8.pad.ui.theme.MyColors import com.bbitcn.f8.pad.utils.log.MyLog @@ -65,32 +60,25 @@ fun DryCoonScreen( drawerViewModel: DrawerViewModel, dryCocoonViewModel: DryCocoonViewModel = viewModel() ) { - val addDryCocoonTicketDialogInData by dryCocoonViewModel.addDryCocoonTicketInDialogData.collectAsState() - val addDryCocoonTicketDialogOutData by dryCocoonViewModel.AddDryCocoonTicketOutDialogData.collectAsState() - val addDryCocoonTicketAirDialogData by dryCocoonViewModel.addDryCocoonTicketAirDialogData.collectAsState() -// val dryCocoonLossDialogData by dryCocoonViewModel.dryCocoonLossDialogData.collectAsState() val dateRangeSelectDialogData by dryCocoonViewModel.dateRangeSelectDialogData.collectAsState() val tabs = listOf("入库", "出库", "库存", "摊晾") var curPager by rememberSaveable { mutableStateOf(0) } val queryInput by dryCocoonViewModel.queryInput.collectAsState() + val dateRange by dryCocoonViewModel.dateRange.collectAsState() - // 入库 val dryIn = dryCocoonViewModel.dryCocoonInPager.collectAsLazyPagingItems() val myInPager = dryCocoonViewModel.dryCocoonInMyPager - // 出库 val dryOut = dryCocoonViewModel.dryCocoonOutPager.collectAsLazyPagingItems() val myOutPager = dryCocoonViewModel.dryCocoonOutMyPager - // 库存 val store = dryCocoonViewModel.storePager.collectAsLazyPagingItems() val myStore = dryCocoonViewModel.storeMyPager - // 摊晾计划 val packagePager = dryCocoonViewModel.packagePager.collectAsLazyPagingItems() val myPackagePager = dryCocoonViewModel.packageMyPager - val refreshDryIn= { + val refreshDryIn = { dryCocoonViewModel.refreshInStatistics() dryIn.refresh() } @@ -98,17 +86,21 @@ fun DryCoonScreen( dryCocoonViewModel.refreshOutStatistics() dryOut.refresh() } - - val onFilterLikeChanged: (String) -> Unit = onFilterLikeChanged@{ query -> - dryCocoonViewModel.refreshLike(curPager, queryInput) { - when (curPager) { - 0 -> refreshDryIn() - 1 -> refreshDryOut() - 2 -> store.refresh() - 3 -> packagePager.refresh() - } + val refreshCurrent = { + when (curPager) { + 0 -> refreshDryIn() + 1 -> refreshDryOut() + 2 -> store.refresh() + 3 -> packagePager.refresh() } } + + val onFilterLikeChanged: (String) -> Unit = { query -> + dryCocoonViewModel.refreshLike(curPager, query) { + refreshCurrent() + } + } + MainFuncFrame { MyCard { Column(modifier = M.padding(15.dp)) { @@ -119,7 +111,6 @@ fun DryCoonScreen( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, ) { - val dateRange by dryCocoonViewModel.dateRange.collectAsState() MyScrollableTabRow( M .weight(1f) @@ -129,43 +120,6 @@ fun DryCoonScreen( dryCocoonViewModel.switchMode(curPager) onFilterLikeChanged("") } -// AssistChipFilter("筛选:", queryInput, onFilterLikeChanged) -// Spacer(modifier = M.weight(1f)) - when (curPager) { - 0 -> { - MyButton( - text = "新增入库单" - ) { - dryCocoonViewModel.showAddDryCocoonTicketInDialog { sysId -> - navController.navigate("dryCoonOperateIn/${sysId}") - } - } - } - - 1 -> { - MyButton( - text = "新增出库单" - ) { - dryCocoonViewModel.showAddDryCocoonTicketOutDialog { sysId -> - navController.navigate("dryCoonOperateOut/${sysId}") - } - } -// MyButton( -// modifier = M.padding(start = 5.dp), -// text = "空包出库" -// ) { -// dryCocoonViewModel.showLossPackageForOut() -// } - } - - 3 -> { - MyButton(text = "新增摊晾计划") { - dryCocoonViewModel.showDryCocoonAirDialog { sysId -> - navController.navigate("dryCoonOperateAir/${sysId}") - } - } - } - } if (curPager != 2) { DateRangePickTextFiled( M @@ -174,12 +128,7 @@ fun DryCoonScreen( dateRange = dateRange ) { dryCocoonViewModel.showDateRangeSelectDialog(curPager) { - when (curPager) { - 0 -> refreshDryIn() - 1 -> refreshDryOut() - 2 -> store.refresh() - 3 -> packagePager.refresh() - } + refreshCurrent() } } } @@ -202,43 +151,26 @@ fun DryCoonScreen( ) when (curPager) { 0 -> DryCoonInScreen(dryCocoonViewModel, dryIn, myInPager) { info -> - drawerViewModel.openDryCocoonInDetailDrawer(navController, info) { - dryCocoonViewModel.deleteInTicket(info.sysid) { - refreshDryIn() - } - } + drawerViewModel.openDryCocoonInDetailDrawer(navController, info) } 1 -> DryCoonOutScreen(dryCocoonViewModel, dryOut, myOutPager) { info -> - drawerViewModel.openDryCocoonOutDetailDrawer(navController, info) { - dryCocoonViewModel.deleteOutTicket(info.sysid) { - refreshDryOut() - } - } + drawerViewModel.openDryCocoonOutDetailDrawer(navController, info) } - 2 -> StoreScreen(dryCocoonViewModel, store, myStore){ + 2 -> StoreScreen(dryCocoonViewModel, store, myStore) { drawerViewModel.openDryCocoonStoreDetailDrawer(it) } 3 -> AirScreen(packagePager, myPackagePager) { - drawerViewModel.openDryCocoonAirDetailDrawer(navController, it) { - dryCocoonViewModel.deleteAirTicket(it.sysid) { - packagePager.refresh() - } - } + drawerViewModel.openDryCocoonAirDetailDrawer(navController, it) } } } } } - AddDryCocoonTicketInDialog(addDryCocoonTicketDialogInData) - AddDryCocoonTicketOutDialog(addDryCocoonTicketDialogOutData) - AddDryCocoonTicketAirDialog(addDryCocoonTicketAirDialogData) -// DryCocoonLossDialog(dryCocoonLossDialogData) DateRangeSelectDialog(dateRangeSelectDialogData) } - @Composable fun DryCoonInScreen( dryCocoonViewModel: DryCocoonViewModel, diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/DryCocoonViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/DryCocoonViewModel.kt index 8e0cae8..1009e35 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/DryCocoonViewModel.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/DryCocoonViewModel.kt @@ -2,25 +2,18 @@ package com.bbitcn.f8.pad.ui.screen.mainFunc import androidx.lifecycle.viewModelScope import com.bbitcn.f8.pad.base.BaseViewModel -import com.bbitcn.f8.pad.model.net.request.DryCocoonQueryListRequest -import com.bbitcn.f8.pad.model.net.request.DryCocoonOutListRequest import com.bbitcn.f8.pad.model.net.request.DryCocoonAirListRequest -import com.bbitcn.f8.pad.model.net.request.DryCocoonPackageForOutLossRequest -import com.bbitcn.f8.pad.model.net.response.* -import com.bbitcn.f8.pad.ui.screen.dialog.* -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.AddDryCocoonTicketAirDialogData -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.AddDryCocoonTicketInDialogData -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.AddDryCocoonTicketOutDialogData -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.DryCocoonLossDialogData +import com.bbitcn.f8.pad.model.net.request.DryCocoonOutListRequest +import com.bbitcn.f8.pad.model.net.request.DryCocoonQueryListRequest +import com.bbitcn.f8.pad.model.net.response.DryCocoonInStatisticsResponse +import com.bbitcn.f8.pad.model.net.response.DryCocoonOutStatisticsResponse +import com.bbitcn.f8.pad.model.net.response.DryStoreListRequest +import com.bbitcn.f8.pad.ui.screen.dialog.DateRangeSelectDialogData import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.utils.MMKVUtil import com.bbitcn.f8.pad.utils.TimeUtils -import com.bbitcn.f8.pad.utils.global.Global -import com.bbitcn.f8.pad.utils.log.MyLog - +import com.bbitcn.f8.pad.utils.pager.DryCocoonAirPagingSource import com.bbitcn.f8.pad.utils.pager.DryCocoonInPagingSource import com.bbitcn.f8.pad.utils.pager.DryCocoonOutPagingSource -import com.bbitcn.f8.pad.utils.pager.DryCocoonAirPagingSource import com.bbitcn.f8.pad.utils.pager.DryCocoonStorePagingSource import com.bbitcn.f8.pad.utils.pager.MyPager import kotlinx.coroutines.flow.MutableStateFlow @@ -30,10 +23,8 @@ import java.util.Date class DryCocoonViewModel : BaseViewModel() { - // —————————————————————————————————————————————————————————————————————全局————————————————————————————————————————————————————————————————————————————— + val initDateRange = Pair(TimeUtils.getRecentDaysDate(20), TimeUtils.getEndOfDay(Date())) - - val initDateRange = Pair(TimeUtils.getRecentDaysDate(20), TimeUtils.getEndOfDay(Date())) // 初始化时间范围为半个月前到当日晚上 private val _queryInput = MutableStateFlow("") val queryInput = _queryInput.asStateFlow() @@ -43,11 +34,51 @@ class DryCocoonViewModel : BaseViewModel() { private val _dateRangeOut = MutableStateFlow(Pair(Date(), Date())) private val _dateRangeAir = MutableStateFlow(Pair(Date(), Date())) + private val _dateRangeSelectDialogData = MutableStateFlow(DateRangeSelectDialogData()) + val dateRangeSelectDialogData = _dateRangeSelectDialogData.asStateFlow() + + private val _inStatisticsInfo = MutableStateFlow(DryCocoonInStatisticsResponse.Data()) + val inStatisticsInfo = _inStatisticsInfo.asStateFlow() + + private val _outStatisticsInfo = MutableStateFlow(DryCocoonOutStatisticsResponse.Data()) + val outStatisticsInfo = _outStatisticsInfo.asStateFlow() + + val dryCocoonInMyPager = MyPager( + pagingSourceFactory = { DryCocoonInPagingSource(it) }, + initialRequestData = DryCocoonQueryListRequest( + starttime = TimeUtils.formatDateTime(initDateRange.first), + endtime = TimeUtils.formatDateTime(initDateRange.second) + ) + ) + val dryCocoonInPager = dryCocoonInMyPager.createPager(viewModelScope) + + val dryCocoonOutMyPager = MyPager( + pagingSourceFactory = { DryCocoonOutPagingSource(it) }, + initialRequestData = DryCocoonOutListRequest( + starttime = TimeUtils.formatDateTime(initDateRange.first), + endtime = TimeUtils.formatDateTime(initDateRange.second) + ) + ) + val dryCocoonOutPager = dryCocoonOutMyPager.createPager(viewModelScope) + + val storeMyPager = MyPager( + pagingSourceFactory = { DryCocoonStorePagingSource(it) }, + initialRequestData = DryStoreListRequest() + ) + val storePager = storeMyPager.createPager(viewModelScope) + + val packageMyPager = MyPager( + pagingSourceFactory = { DryCocoonAirPagingSource(it) }, + initialRequestData = DryCocoonAirListRequest( + starttime = TimeUtils.formatDateTime(initDateRange.first), + endtime = TimeUtils.formatDateTime(initDateRange.second) + ) + ) + val packagePager = packageMyPager.createPager(viewModelScope) + init { doInIoThreadNoDialog { - // 获取半个月前的日期 _dateRange.value = initDateRange - // 初始化入库|出库|摊晾的时间范围 _dateRangeIn.value = initDateRange _dateRangeOut.value = initDateRange _dateRangeAir.value = initDateRange @@ -55,7 +86,6 @@ class DryCocoonViewModel : BaseViewModel() { } fun switchMode(curPager: Int) { - // 切换模块 val date = when (curPager) { 0 -> _dateRangeIn.value 1 -> _dateRangeOut.value @@ -71,9 +101,6 @@ class DryCocoonViewModel : BaseViewModel() { refreshRequest(curPager, onFinish) } - /** - * 刷新入库|出库|摊晾的时间范围 - */ fun refreshRequest(curPager: Int, onFinish: () -> Unit) { doInIoThreadNoDialog { when (curPager) { @@ -111,12 +138,6 @@ class DryCocoonViewModel : BaseViewModel() { } } - /** - * 筛选时间范围弹窗 - */ - private val _dateRangeSelectDialogData = MutableStateFlow(DateRangeSelectDialogData()) - val dateRangeSelectDialogData = _dateRangeSelectDialogData.asStateFlow() - fun showDateRangeSelectDialog(curPager: Int, onFinish: () -> Unit) { doInIoThreadNoDialog { _dateRangeSelectDialogData.value = DateRangeSelectDialogData( @@ -126,14 +147,12 @@ class DryCocoonViewModel : BaseViewModel() { _dateRangeSelectDialogData.update { it.copy(showDialog = false) } }, onClickRangeDay = { dateStrStart, dateStrEnd -> - // 切换时间范围 - val temp = - TimeUtils.getStartOfDay(dateStrStart) to TimeUtils.getEndOfDay(dateStrEnd) - _dateRange.value = temp + val range = TimeUtils.getStartOfDay(dateStrStart) to TimeUtils.getEndOfDay(dateStrEnd) + _dateRange.value = range when (curPager) { - 0 -> _dateRangeIn.value = temp - 1 -> _dateRangeOut.value = temp - 3 -> _dateRangeAir.value = temp + 0 -> _dateRangeIn.value = range + 1 -> _dateRangeOut.value = range + 3 -> _dateRangeAir.value = range } refreshRequest(curPager, onFinish) } @@ -141,24 +160,6 @@ class DryCocoonViewModel : BaseViewModel() { } } - // —————————————————————————————————————————————————————————————————————————入库————————————————————————————————————————————————————————————————————————— - - private val _addDryCocoonTicketInDialogData = MutableStateFlow(AddDryCocoonTicketInDialogData()) - val addDryCocoonTicketInDialogData = _addDryCocoonTicketInDialogData.asStateFlow() - - private val _inStatisticsInfo = MutableStateFlow(DryCocoonInStatisticsResponse.Data()) - val inStatisticsInfo = _inStatisticsInfo.asStateFlow() - - // 创建 Pager - val dryCocoonInMyPager = MyPager( - pagingSourceFactory = { DryCocoonInPagingSource(it) }, - initialRequestData = DryCocoonQueryListRequest( - starttime = TimeUtils.formatDateTime(initDateRange.first), - endtime = TimeUtils.formatDateTime(initDateRange.second) - ), // 传入初始的请求数据 - ) - val dryCocoonInPager = dryCocoonInMyPager.createPager(viewModelScope) - fun refreshInStatistics() { doInIoThreadNoDialog { refreshInStatisticsApi() @@ -180,110 +181,6 @@ class DryCocoonViewModel : BaseViewModel() { } } - fun showAddDryCocoonTicketInDialog( - navToDryCoonOperateIn: (sysId: String) -> Unit - ) { - doInIoThread("正在加载入库单据新增信息") { - //入库相关参数 - // 入库蚕季 - val season: DryCocoonSeason = apiService.getDryCoonSeason() - if (season.code != 1) { - Toasty.showTipsDialog(season.msg) - return@doInIoThread - } - // 入库仓库 - val store: DryCocoonInStore = apiService.getDryCoonInStore() - if (store.code != 1) { - Toasty.showTipsDialog(store.msg) - return@doInIoThread - } - // 入库茧别 - val cocoonLevel: DryCocoonInLevel = apiService.getDryCoonInLevel() - if (cocoonLevel.code != 1) { - Toasty.showTipsDialog(cocoonLevel.msg) - return@doInIoThread - } - // 入库包装类型 - val packageType: DryCocoonInPackageType = apiService.getDryCocoonPackageType() - if (packageType.code != 1) { - Toasty.showTipsDialog(packageType.msg) - return@doInIoThread - } - // 蚕品种 - val cocoonType = apiService.getDryCocoonType() - if (cocoonType.code != 1) { - Toasty.showTipsDialog(cocoonType.msg) - return@doInIoThread - } - // 区域 - val area = apiService.getCocoonArea() - if (area.code != 1) { - Toasty.showTipsDialog(area.msg) - return@doInIoThread - } - _addDryCocoonTicketInDialogData.value = - AddDryCocoonTicketInDialogData( - true, - store.data.firstOrNull { it.depsysid == MMKVUtil.get(Global.DEP_SYS_ID) }?.cangkuname - ?: "", - season.data, - store.data, - cocoonType.data, - cocoonLevel.data, - packageType.data, - area.data, - { request, cocoonLevelT, storeT, cocoonTypeT -> - doInIoThreadThenUI("正在添加入库单据", onIO = { - apiService.addDryCocoonInTicket(request) - }) { response -> - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - navToDryCoonOperateIn(response.data.toString()) - } - } - } - ) { - _addDryCocoonTicketInDialogData.update { it.copy(showDialog = false) } - } - } - } - - fun deleteInTicket(sysid: String, onFinish: () -> Unit) { - doInIoThread("正在删除入库单") { - // 删除入库单 - val response = apiService.deleteDryCocoonInTicket(sysid) - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("删除成功") - onFinish() - } - } - } - - // ————————————————————————————————————————————————————————————————————————出库—————————————————————————————————————————————————————————————————————————— - - private val _addDryCocoonTicketOutDialogData: MutableStateFlow = - MutableStateFlow(AddDryCocoonTicketOutDialogData()) - val AddDryCocoonTicketOutDialogData = _addDryCocoonTicketOutDialogData.asStateFlow() - - /** - * 出库统计信息 - */ - private val _outStatisticsInfo = MutableStateFlow(DryCocoonOutStatisticsResponse.Data()) - val outStatisticsInfo = _outStatisticsInfo.asStateFlow() - - // 创建 Pager - val dryCocoonOutMyPager = MyPager( - pagingSourceFactory = { DryCocoonOutPagingSource(it) }, - initialRequestData = DryCocoonOutListRequest( - starttime = TimeUtils.formatDateTime(initDateRange.first), - endtime = TimeUtils.formatDateTime(initDateRange.second) - ), // 传入初始的请求数据 - ) - val dryCocoonOutPager = dryCocoonOutMyPager.createPager(viewModelScope) - fun refreshOutStatistics() { doInIoThreadNoDialog { refreshOutStatisticsApi() @@ -291,12 +188,11 @@ class DryCocoonViewModel : BaseViewModel() { } suspend fun refreshOutStatisticsApi() { - // 出库统计 val result = apiService.getDryCocoonOutStatistics( DryCocoonQueryListRequest( like = _queryInput.value, - starttime = TimeUtils.formatDateTime(_dateRangeIn.value.first), - endtime = TimeUtils.formatDateTime(_dateRangeIn.value.second) + starttime = TimeUtils.formatDateTime(_dateRangeOut.value.first), + endtime = TimeUtils.formatDateTime(_dateRangeOut.value.second) ) ) if (result.code == 1) { @@ -306,129 +202,6 @@ class DryCocoonViewModel : BaseViewModel() { } } - fun showAddDryCocoonTicketOutDialog( - navToDryCoonOperateOut: (infoStr: String) -> Unit - ) { - doInIoThread("正在加载出库单据新增信息") { - //入库相关参数 - // 入库蚕季 仓库 茧别 三级联 - val info = apiService.getDryCocoonOutAddInfo() - if (info.code != 1) { - Toasty.showTipsDialog(info.msg) - return@doInIoThread - } - // 出库包装类型 - val packageType: DryCocoonInPackageType = apiService.getDryCocoonPackageType() - if (packageType.code != 1) { - Toasty.showTipsDialog(packageType.msg) - return@doInIoThread - } - // 出库对象 - val dealObject: DryCocoonDealObjectResponse = apiService.getDryCocoonDealObject() - if (dealObject.code != 1) { - Toasty.showTipsDialog(dealObject.msg) - return@doInIoThread - } - // 蚕品种 - val cocoonType = apiService.getDryCocoonType() - if (cocoonType.code != 1) { - Toasty.showTipsDialog(cocoonType.msg) - return@doInIoThread - } - // 区域 - val area = apiService.getCocoonArea() - if (area.code != 1) { - Toasty.showTipsDialog(cocoonType.msg) - return@doInIoThread - } - // 显示新增出库弹窗 - _addDryCocoonTicketOutDialogData.value = AddDryCocoonTicketOutDialogData( - true, info.data, packageType.data, dealObject.data, cocoonType.data, area.data, - onClickOK = { request -> - doInIoThreadThenUI("正在添加出库单据", onIO = { - apiService.addDryCocoonOutTicket(request) - }) { response -> - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - navToDryCoonOperateOut(response.data.toString()) - } - } - } - ) { - _addDryCocoonTicketOutDialogData.update { it.copy(showDialog = false) } - } - } - } - - fun deleteOutTicket(sysId: String, onFinish: () -> Unit) { - doInIoThread("正在删除出库单") { - // 删除出库单 - val response = apiService.deleteDryCocoonOutTicket(sysId) - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("删除成功") - onFinish() - } - } - } - -// /** -// * 出库-空包释放 -// */ -// private val _dryCocoonLossDialogData: MutableStateFlow = -// MutableStateFlow(DryCocoonLossDialogData()) -// val dryCocoonLossDialogData = _dryCocoonLossDialogData.asStateFlow() -// -// fun showLossPackageForOut() { -// doInIoThread { -// // 查询蚕季 -// val season: DryCocoonSeason = apiService.getDryCoonSeason("10") -// if (season.code != 1) { -// Toasty.showTipsDialog(season.msg) -// return@doInIoThread -// } -// _dryCocoonLossDialogData.value = -// DryCocoonLossDialogData( -// true, -// seasonList = season.data, -// onLossPackage = { rfids, seasonSysId, onFinish -> -// doInIoThread("正在释放空包") { -// rfids.forEach { -// // 释放空包 -// val response = apiService.onLossPackageForOut( -// DryCocoonPackageForOutLossRequest( -// it, -// TimeUtils.getStringTime(), -// seasonSysId -// ) -// ) -// if (response.code != 1) { -// Toasty.showTipsDialog(response.msg) -// } else { -// Toasty.showToast("释放成功") -// onFinish() -// } -// } -// } -// }, -// onDismiss = { -// _dryCocoonLossDialogData.update { it.copy(showDialog = false) } -// } -// ) -// } -// } - - // ————————————————————————————————————————————————————————————————————————库存—————————————————————————————————————————————————————————————————————————— - - // 创建 Pager - val storeMyPager = MyPager( - pagingSourceFactory = { DryCocoonStorePagingSource(it) }, - initialRequestData = DryStoreListRequest(), // 传入初始的请求数据 - ) - val storePager = storeMyPager.createPager(viewModelScope) - fun switchStoreEmpty(sysid: String, isEmpty: Int, onSuccess: () -> Unit) { doInIoThread("正在" + if (isEmpty == 1) "标记" else "取消标记") { val response = apiService.switchStoreEmpty(sysid, isEmpty) @@ -439,72 +212,4 @@ class DryCocoonViewModel : BaseViewModel() { } } } - - // —————————————————————————————————————————————————————————————————————————摊晾————————————————————————————————————————————————————————————————————————— - - private val _addDryCocoonTicketAirDialogData: MutableStateFlow = - MutableStateFlow(AddDryCocoonTicketAirDialogData()) - val addDryCocoonTicketAirDialogData = _addDryCocoonTicketAirDialogData.asStateFlow() - - // 创建 Pager - val packageMyPager = MyPager( - pagingSourceFactory = { DryCocoonAirPagingSource(it) }, - initialRequestData = DryCocoonAirListRequest( - starttime = TimeUtils.formatDateTime(initDateRange.first), - endtime = TimeUtils.formatDateTime(initDateRange.second) - ), // 传入初始的请求数据 - ) - val packagePager = packageMyPager.createPager(viewModelScope) - - fun showDryCocoonAirDialog( - navToDryCoonOperateAir: (infoStr: String) -> Unit - ) { - doInIoThread("正在加载摊晾计划新增信息") { - //蚕季 仓库 茧别 三级联 - val info = apiService.getDryCocoonOutAddInfo() - if (info.code != 1) { - Toasty.showTipsDialog(info.msg) - return@doInIoThread - } - // 蚕品种 - val cocoonType = apiService.getDryCocoonType() - if (cocoonType.code != 1) { - Toasty.showTipsDialog(cocoonType.msg) - return@doInIoThread - } - // 区域 - val area = apiService.getCocoonArea() - if (area.code != 1) { - Toasty.showTipsDialog(cocoonType.msg) - return@doInIoThread - } - _addDryCocoonTicketAirDialogData.value = AddDryCocoonTicketAirDialogData( - true, info.data, cocoonType.data, area.data, onClickOK = { request -> - doInIoThreadThenUI("正在添加摊晾计划", onIO = { - apiService.addDryCocoonAirTicket(request) - }) { response -> - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - navToDryCoonOperateAir(response.data.toString()) - } - } - }) { - _addDryCocoonTicketAirDialogData.update { it.copy(showDialog = false) } - } - } - } - - fun deleteAirTicket(sysid: String, onSuccess: () -> Unit) { - doInIoThread("正在删除摊晾计划") { - val response = apiService.deleteDryCocoonAirTicket(sysid) - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("删除成功") - onSuccess() - } - } - } - -} \ No newline at end of file +} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseScreen.kt index b89acc3..fa8b1e1 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseScreen.kt @@ -74,7 +74,6 @@ import com.bbitcn.f8.pad.ui.screen.dialog.DateRangeSelectDialog import com.bbitcn.f8.pad.ui.screen.dialog.FaceDialog import com.bbitcn.f8.pad.ui.screen.dialog.OCRDialog import com.bbitcn.f8.pad.ui.screen.dialog.PriceDialog -import com.bbitcn.f8.pad.ui.screen.dialog.ScanDialog import com.bbitcn.f8.pad.ui.screen.dialog.TareDialog import com.bbitcn.f8.pad.ui.screen.dialog.TicketMoreDialog import com.bbitcn.f8.pad.ui.screen.view.drawer.DrawerViewModel @@ -276,7 +275,6 @@ private fun PurchaseDialogs(purchaseViewModel: PurchaseViewModel) { val ticketMoreDialogData by purchaseViewModel.ticketMoreDialogData.collectAsState() val priceDialogData by purchaseViewModel.priceDialogData.collectAsState() val tareDialogData by purchaseViewModel.tareDialogData.collectAsState() - val scanDialogData by purchaseViewModel.scanDialogData.collectAsState() val ocrDialogData by purchaseViewModel.ocrDialogData.collectAsState() val faceDialogData by purchaseViewModel.faceDialogData.collectAsState() val dateRangeSelectDialogData by purchaseViewModel.dateRangeSelectDialogData.collectAsState() @@ -285,7 +283,6 @@ private fun PurchaseDialogs(purchaseViewModel: PurchaseViewModel) { PriceDialog(priceDialogData) TareDialog(tareDialogData) TicketMoreDialog(ticketMoreDialogData) - ScanDialog(scanDialogData) OCRDialog(ocrDialogData) FaceDialog(faceDialogData) DateRangeSelectDialog(dateRangeSelectDialogData) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseViewModel.kt index e62091c..cdc57b8 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseViewModel.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseViewModel.kt @@ -12,7 +12,6 @@ import com.bbitcn.f8.pad.ui.screen.dialog.DateRangeSelectDialogData import com.bbitcn.f8.pad.ui.screen.dialog.FaceDialogData import com.bbitcn.f8.pad.ui.screen.dialog.OCRDialogData import com.bbitcn.f8.pad.ui.screen.dialog.PriceDialogData -import com.bbitcn.f8.pad.ui.screen.dialog.ScanDialogData import com.bbitcn.f8.pad.ui.screen.dialog.TareDialogData import com.bbitcn.f8.pad.ui.screen.dialog.TicketMoreDialogData import com.bbitcn.f8.pad.ui.screen.view.Toasty @@ -20,8 +19,6 @@ import com.bbitcn.f8.pad.utils.MMKVUtil import com.bbitcn.f8.pad.utils.MyUtil import com.bbitcn.f8.pad.utils.TimeUtils import com.bbitcn.f8.pad.utils.TimeUtils.getRecentMonthsDate -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.idcard.IDCardUtils -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.nfc.NFCUtils import com.bbitcn.f8.pad.utils.global.Global import com.bbitcn.f8.pad.utils.pager.MyPager import com.bbitcn.f8.pad.utils.pager.PurchaseInfoPagingSource @@ -36,10 +33,6 @@ class PurchaseViewModel : BaseViewModel() { private val _addTicketDialog = MutableStateFlow(AddTicketDialogData()) val addTicketDialog: StateFlow = _addTicketDialog.asStateFlow() - - private val _scanDialogData = MutableStateFlow(ScanDialogData()) - val scanDialogData = _scanDialogData.asStateFlow() - private val _ocrDialogData = MutableStateFlow(OCRDialogData()) val ocrDialogData = _ocrDialogData.asStateFlow() @@ -90,51 +83,7 @@ class PurchaseViewModel : BaseViewModel() { }, navToWeight = { sysId -> navController.navigate("weight/${sysId}") - }, - cardReaderForUserCard = { - doInIoThread { - _scanDialogData.value = ScanDialogData(showDialog = true, isNFC = true, - onDismiss = { - closeScanDialog() - } - ) - NFCUtils.init(isPayCard = false) { - getFarmerInfoByICCardAndToWeight(navController, it) { - closeScanDialog() - } - } - } - }, - cardReaderForIdCard = { - doInIoThread { - _scanDialogData.value = ScanDialogData(showDialog = true, isNFC = false, - onDismiss = { - closeScanDialog() - } - ) - // 初始化身份证读卡模块 - IDCardUtils.openGPIO() - IDCardUtils.openDevice { - getFarmerInfoByIdCardAndToWeight(navController, it.id) { - closeScanDialog() - } - } - } - }, - cardReaderForBankCard = { - doInIoThread { - _scanDialogData.value = ScanDialogData(showDialog = true, isNFC = true, - onDismiss = { - closeScanDialog() - } - ) - NFCUtils.init(isPayCard = true) { - getFarmerInfoByBankCardAndToWeight(navController, it) { - closeScanDialog() - } - } - } - }, + } , ocrForIdCard = { doInIoThread { _ocrDialogData.value = OCRDialogData( @@ -215,38 +164,6 @@ class PurchaseViewModel : BaseViewModel() { } } - fun getFarmerInfoByICCardAndToWeight( - navController: NavController, - icCard: String, - onSuccess: () -> Unit - ) { - doInIoThreadThenUI("正在根据农户卡获取农户信息", onIO = { - apiService.getFarmersInfoByUserCard(icCard) - }) { userInfo -> - if (userInfo.code == 1) { - onSuccess() - _scanDialogData.update { it.copy(showDialog = false) } - navController.navigate("weight/${userInfo.data.sysid}") - } else { - _scanDialogData.update { it.copy(showDialog = false) } - Toasty.error(userInfo.msg) - } - } - } - - fun closeScanDialog() { - doInIoThreadNoDialog { - _scanDialogData.update { it.copy(showDialog = false) } - if (_scanDialogData.value.isNFC) { - // 关闭NFC Reader Mode - NFCUtils.disableReaderMode() - } else { - // 关闭身份证读卡模块 - IDCardUtils.closeGPIO() - } - } - } - fun showPriceDialog(data: PurchaseDataResponse.Data,onSuccess: () -> Unit) { doInIoThread { _priceDialogData.value = PriceDialogData(showDialog = true,data = data, diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonAirScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonAirScreen.kt deleted file mode 100644 index e261f7b..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonAirScreen.kt +++ /dev/null @@ -1,303 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.secondFunc - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.paging.compose.collectAsLazyPagingItems -import com.bbitcn.f8.pad.IS_DEBUG_DRYCOCOON -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MainFuncFrame -import com.bbitcn.f8.pad.base.MyButton -import com.bbitcn.f8.pad.base.MyCard - -import com.bbitcn.f8.pad.base.MyRefreshTable -import com.bbitcn.f8.pad.base.MyTableData -import com.bbitcn.f8.pad.model.net.request.DryCocoonPackageLossRequest -import com.bbitcn.f8.pad.model.net.request.StartDryCocoonAirDetailRequest -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.scale.MyWeightShow -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -import com.bbitcn.f8.pad.ui.viewmodel.factory.AddDryCocoonAirViewModelFactory -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import com.bbitcn.f8.pad.utils.log.MyLog -import kotlinx.coroutines.flow.flowOf - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun DryCocooAirScreenPreview() { - DryCocoonAirScreen("1123") -} - -@Composable -fun DryCocoonAirScreen( - sysId: String, - myCardReaderShowViewModel: MyCardReaderShowViewModel = viewModel() -) { - LaunchedEffect(Unit) { - MyLog.test("第一次进入,清空tagId缓存") - myCardReaderShowViewModel.clearList() - } - val addDryCocoonAirViewModel = viewModel( - factory = AddDryCocoonAirViewModelFactory(sysId) - ) - val info by addDryCocoonAirViewModel.info.collectAsState() - val myPager = addDryCocoonAirViewModel.dryCocoonAirDetailMyPager - val dryAir = - addDryCocoonAirViewModel.dryCocoonAirDetailPager.collectAsLazyPagingItems() - val isRefreshing by myPager.listIsRefreshing.collectAsState() - MainFuncFrame { - Row( - modifier = M - .fillMaxWidth() - ) { - MyCard( - modifier = M - .fillMaxSize() - .weight(2f) - ) { - Column( - modifier = M - .weight(2f) - .padding(10.dp) - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = M - .padding(10.dp) - .fillMaxWidth() - ) { - VerticalInfo("仓库", info.ckname) - VerticalInfo("蚕季", info.cjname) - VerticalInfo("茧别", info.jiantype) - VerticalInfo("品种", info.canpinzhong) - VerticalInfo("区域", info.xiangzhen) - VerticalInfo("总包数", info.baoshu.toString()) - VerticalInfo("摊晾中", info.tanliangingbaoshu.toString()) - VerticalInfo("空包释放", info.releaseBaoshu.toString()) -// VerticalInfo("摊晾人", info.tanliangren) // 按需求去掉2025年6月4日 - } - MyRefreshTable( - modifier = M - .fillMaxWidth() - .weight(1f), - isRefreshing = isRefreshing, - info = dryAir, - key = { it.sysid }, - onFinishRefresh = { - myPager.setListIsRefreshClose() - }, - onLongClick = { - Toasty.showConfirmDialog("是否删除<${it.code}>摊晾记录") { - addDryCocoonAirViewModel.deleteDryCocoonAirDetail(it.sysid) { - dryAir.refresh() - } - } - }, - items = listOf( - MyTableData("包码", 2, { ".." + it.code.takeLast(11) }), - MyTableData("状态", 2, { it.status }), - MyTableData("开始时间", 3, { it.starttime }), - MyTableData("结束时间", 3, { it.endtime }), -// MyTableData("毛重", 1, { it.chayizhongliang.toString() }), -// MyTableData("库存毛重", 2, { it.kcmaozhong.toString() }),// 按需求去掉2025年6月6日 - MyTableData("开始重量", 2, { it.fbstartmaozhong.toString() }), - MyTableData("结束重量", 2, { it.fbendmaozhong.toString() }), - MyTableData("空包释放", 1, { it.bagrelease }), - ), - scrollToTopOnRefresh = true, - ) - } - } - var grossWeight by rememberSaveable { mutableStateOf(0.0) } - val curReader by myCardReaderShowViewModel.curDevice.collectAsState() - val deviceTagIds by (curReader?.tagList - ?: flowOf(emptyList())).collectAsState(initial = emptyList()) - val tagIds by addDryCocoonAirViewModel.tagIds.collectAsState() - var weightStableSeconds by rememberSaveable { mutableStateOf(0) } - var targetStableWeight by rememberSaveable { mutableStateOf(0.0) } - var hasBecomeZero by rememberSaveable { mutableStateOf(true) } - var isAutoOperateStart by rememberSaveable { mutableStateOf(false) } - var isAutoOperateEnd by rememberSaveable { mutableStateOf(false) } - LaunchedEffect(deviceTagIds) { - addDryCocoonAirViewModel.filterTagIds(deviceTagIds) - } - MyCard( - modifier = M - .weight(1f) - .padding(start = 10.dp), - ) { - Column( - modifier = M.padding(10.dp), - verticalArrangement = Arrangement.spacedBy(5.dp), - horizontalAlignment = Alignment.End - ) { - var weightErrorMsg by rememberSaveable { mutableStateOf("") } - val tagErrorMsg by remember(tagIds, curReader) { - derivedStateOf { - if (curReader == null) "未检测到读卡器" - else if (tagIds.isEmpty()) "未检测到麻袋" - else if (tagIds.size > 1) "检测到多个麻袋" - else "" - } - } - MyWeightShow(targetStableWeight = targetStableWeight, onErrorMsg = { - weightErrorMsg = it - }, onStableTimeChanged = { - weightStableSeconds = it - }) { - grossWeight = it - if (it == 0.0) { - hasBecomeZero = true - } - } - DryCocoonInfo( - "麻袋ID", - if (tagIds.isNotEmpty()) "${tagIds[0].take(2)}...${tagIds[0].takeLast(4)}" else "", - tagErrorMsg - ) - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton(modifier = M.fillMaxWidth(), text = "重新检测茧包") { - myCardReaderShowViewModel.clearList() - } - } - if (IS_DEBUG_DRYCOCOON) { - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton(text = "增加随机芯片") { - UHFReaderG06M_G25M.testXP() - } - MyButton(text = "测试增加芯片1") { - UHFReaderG06M_G25M.testXP("521323232") - } - } - } - Spacer(modifier = M.weight(1f)) - val allErrorMsg by remember(tagErrorMsg, weightErrorMsg) { - derivedStateOf { - if (tagErrorMsg.isNotEmpty()) tagErrorMsg + "\n" else "" + - if (weightErrorMsg.isNotEmpty()) weightErrorMsg + "\n" else "" - } - } - val onSaveStart = { onFinish: () -> Unit -> - addDryCocoonAirViewModel.startDryCocoonAirDetail( - tagIds[0], - StartDryCocoonAirDetailRequest( - maozhong = grossWeight, - ), onSuccess = { - dryAir.refresh() - myCardReaderShowViewModel.clearList() - }, onFinish = onFinish - ) - } - val onSaveEnd = { onFinish: () -> Unit -> - addDryCocoonAirViewModel.stopDryCocoonAirDetail( - tagIds[0], grossWeight, onSuccess = { - dryAir.refresh() - myCardReaderShowViewModel.clearList() - }, onFinish = onFinish - ) - } - Column( - modifier = M.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(5.dp) - ) { - AutoOperate( - "自动开始摊晾", - tagIds, - -1.0, - weightStableSeconds, - addDryCocoonAirViewModel, - hasBecomeZero, autoOperate = isAutoOperateStart, onAutoOperate = { - targetStableWeight = 0.0 - isAutoOperateStart = it - isAutoOperateEnd = false - } - ) { - hasBecomeZero = false - onSaveStart(it) - } - AutoOperate( - "自动结束摊晾", - tagIds, - grossWeight, - weightStableSeconds, - addDryCocoonAirViewModel, - hasBecomeZero, autoOperate = isAutoOperateEnd, onAutoOperate = { - targetStableWeight = - addDryCocoonAirViewModel.standardPackageWeight.value - isAutoOperateEnd = it - isAutoOperateStart = false - } - ) { - hasBecomeZero = false - onSaveEnd(it) - } - MyWeightButton( - text = "开始摊晾", - isEnable = allErrorMsg.isEmpty(), - ) { - // 增加本包摊晾 - if (allErrorMsg.isEmpty()) { - onSaveStart { } - } else { - Toasty.showTipsDialog(allErrorMsg) - } - } - MyWeightButton( - text = "结束摊晾", - isEnable = allErrorMsg.isEmpty(), - ) { - // 结束摊晾 - if (allErrorMsg.isEmpty()) { - onSaveEnd {} - } else { - Toasty.showTipsDialog(allErrorMsg) - } - } - MyWeightButton( - text = "空包释放", - isEnable = allErrorMsg.isEmpty(), - ) { - // 空包释放 - if (allErrorMsg.isEmpty()) { - addDryCocoonAirViewModel.lossDryCocoonAir( - DryCocoonPackageLossRequest( - rfid = tagIds[0], - tlsysid = info.sysid, - ) - ) { - dryAir.refresh() - myCardReaderShowViewModel.clearList() - } - } else { - Toasty.showTipsDialog(allErrorMsg) - } - } - } - } - } - } - } -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonAirViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonAirViewModel.kt deleted file mode 100644 index f6cc115..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonAirViewModel.kt +++ /dev/null @@ -1,174 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.secondFunc - -import androidx.lifecycle.viewModelScope -import com.bbitcn.f8.pad.R -import com.bbitcn.f8.pad.model.net.request.DryCocoonPackageLossRequest -import com.bbitcn.f8.pad.model.net.request.StartDryCocoonAirDetailRequest -import com.bbitcn.f8.pad.model.net.request.StopDryCocoonAirDetailRequest -import com.bbitcn.f8.pad.model.net.response.DryCocoonAirDetailResponse -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.utils.AudioPlayer -import com.bbitcn.f8.pad.utils.TimeUtils -import com.bbitcn.f8.pad.utils.pager.DryCocoonAirDetailPagingSource -import com.bbitcn.f8.pad.utils.pager.MyPager -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow - - -class AddDryCocoonAirViewModel(val outSystemId: String) : AddDryCocoonBaseViewModel() { - - private val _info = MutableStateFlow(DryCocoonAirDetailResponse.Data()) - val info = _info.asStateFlow() - - init { - refreshDryCocoonAirDetail(true) - } - - /** - * 刷新摊晾详情 - */ - fun refreshDryCocoonAirDetail(needDialog: Boolean = false) { - doInIoThreadWith(needDialog, "正在刷新摊晾详情") { - val info = apiService.getCocoonAirDetail(outSystemId) - if (info.code != 1) { - Toasty.showTipsDialog("请求错误,请尝试退出重新进入:${info.msg}") - } else { - _info.value = info.data - } - } - } - - /** - * 摊晾详情 - */ - val dryCocoonAirDetailMyPager = MyPager( - pagingSourceFactory = { DryCocoonAirDetailPagingSource(outSystemId) }, - initialRequestData = "", // 传入初始的请求数据 - ) - val dryCocoonAirDetailPager = dryCocoonAirDetailMyPager.createPager(viewModelScope) - - fun stopDryCocoonAirDetail( - rfid: String,grossWeight: Double, - onSuccess: () -> Unit, - onFinish: () -> Unit - ) { - doInIoThread("正在结束本包摊晾记录", onFinish = onFinish,onError = { - AudioPlayer.playAudioOnce(R.raw.network_disconnect) -// TTSManager.speak("操作失败,请检查网络连接") - }) { - // 根据RFID查询包码 - val searchResponse = apiService.searchAirDetailByRFID(_info.value.cjsysid, rfid) - if (searchResponse.code != 1) { -// TTSManager.speak("操作失败," + searchResponse.msg) - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_air_start_failed) - Toasty.showTipsDialog(searchResponse.msg) - } else { - val request = StopDryCocoonAirDetailRequest( - rfid = rfid, - tlsysid = _info.value.sysid, - maozhong = grossWeight, - time = TimeUtils.getStringTime() - ) - val response = - apiService.stopDryCocoonAirDetail(request) - if (response.code != 1) { -// TTSManager.speak("操作失败" + response.msg) - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_air_stop_failed) - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("结束成功") - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_air_stop_success) -// TTSManager.speak("已结束摊晾") - addHadHandleTagIds(searchResponse.data.sysid, rfid) - onSuccess() - refreshDryCocoonAirDetail(false) - } - } - } - } - - fun startDryCocoonAirDetail( - rfid: String, - dryCocoonSaveAirDetail: StartDryCocoonAirDetailRequest, - onSuccess: () -> Unit, - onFinish: () -> Unit - ) { - doInIoThread("正在保存本包摊晾记录", onFinish = onFinish,onError = { -// TTSManager.speak("操作失败,请检查网络连接") - AudioPlayer.playAudioOnce(R.raw.network_disconnect) - }) { - val temp = _info.value - // 根据RFID查询包码 - val searchResponse = apiService.searchAirDetailByRFID(temp.cjsysid, rfid) - if (searchResponse.code != 1) { -// TTSManager.speak("操作失败," + searchResponse.msg) - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_air_start_failed) - Toasty.showTipsDialog(searchResponse.msg) - } else { - // 保存摊晾记录 - val response = - apiService.saveDryCocoonAirDetail( - dryCocoonSaveAirDetail.copy( - tlsysid = temp.sysid, - cjsysid = temp.cjsysid, - rkitemsysid = searchResponse.data.sysid, - code = searchResponse.data.code, - rfid = rfid, - time = TimeUtils.getStringTime(), - kcmaozhong = searchResponse.data.kcmaozhong, - ) - ) - if (response.code != 1) { - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_air_start_failed) -// TTSManager.speak("操作失败," + response.msg) - Toasty.showTipsDialog(response.msg) - } else { - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_air_start_success) -// TTSManager.speak("已开始摊晾") - Toasty.success("保存成功") - addHadHandleTagIds(searchResponse.data.sysid, rfid) - onSuccess() - refreshDryCocoonAirDetail(false) - } - } - } - } - - fun deleteDryCocoonAirDetail(itemsysid: String, onSuccess: () -> Unit) { - doInIoThread("正在删除本包摊晾记录") { - val response = apiService.deleteDryCocoonAirDetail(itemsysid) - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("删除成功") - onSuccess() - // 删除已处理的RFID 必须在成功后删除 - deleteHadHandleTagIds(itemsysid) - refreshDryCocoonAirDetail(false) - } - } - } - - fun lossDryCocoonAir( - request: DryCocoonPackageLossRequest, - onSuccess: () -> Unit - ) { - Toasty.showConfirmDialog("确定要释放该麻袋吗") { - doInIoThread("正在释放空包中") { - val response = - apiService.onLossPackage(request.copy(time = TimeUtils.getStringTime())) - if (response.code != 1) { - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_air_loss_failed) - Toasty.showTipsDialog(response.msg) - } else { - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_air_loss_success) - Toasty.success("释放成功") - onSuccess() - refreshDryCocoonAirDetail(false) - } -// TTSManager.speak("释放" + if (response.code == 1) "成功" else "失败", true) - } - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonBase.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonBase.kt deleted file mode 100644 index 1e2c77f..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonBase.kt +++ /dev/null @@ -1,225 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.secondFunc - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.background -import androidx.compose.foundation.border -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.widthIn -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.DebouncedEffect -import com.bbitcn.f8.pad.base.MyCard -import com.bbitcn.f8.pad.base.MyCheckBox -import com.bbitcn.f8.pad.ui.theme.MyColors -import com.bbitcn.f8.pad.utils.externalModules.devices.light.Light_ -import com.bbitcn.f8.pad.utils.externalModules.devices.light.Light_.closeLight -import com.bbitcn.f8.pad.utils.externalModules.devices.light.Light_.openGreenLight -import com.bbitcn.f8.pad.utils.externalModules.devices.light.Light_.openRedLight -import com.bbitcn.f8.pad.utils.externalModules.devices.light.Light_.openYellowLight -import com.bbitcn.f8.pad.utils.log.MyLog - - -@Composable -fun AutoOperate( - title: String, - tagIds: List, - grossWeight: Double, - weightStableSeconds: Int, - viewModel: AddDryCocoonBaseViewModel, - hasBecomeZero: Boolean = false, - autoOperate: Boolean = false, - onAutoOperate: (Boolean) -> Unit = {}, - onSucc: (onFinish: () -> Unit) -> Unit = {} -) { - // 标准包重量 - val standardPackageWeight by viewModel.standardPackageWeight.collectAsState() - val weightStableTime by viewModel.weightAutoWaitTime.collectAsState() - Column(modifier = M.fillMaxWidth()) { - Row( - modifier = M.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.End - ) { - if (autoOperate) { - Box( - // 黑色外边框 - modifier = M - .border(BorderStroke(1.dp, MyColors.Black)) - ) { - Column( - // 黑色外边框 - modifier = M - .padding(5.dp) - ) { - // 条件1 - val succ1 = tagIds.size == 1 - // 条件2类型: 0:小于标准包重量 1:等于标准包重量 2:大于标准包重量 - val succ2Type = when { - grossWeight < standardPackageWeight -> 0 - grossWeight == standardPackageWeight -> 1 - else -> 2 - } - // 条件3:称稳定时间 - val succ3 by remember(grossWeight, weightStableSeconds, weightStableTime) { - derivedStateOf { grossWeight != 0.0 && weightStableSeconds >= weightStableTime } - } - ConditionText(succ1, "检测到新麻袋") - ConditionText( - hasBecomeZero, - "称重前置零" - ) - if (grossWeight != -1.0) { - // 不使用标准包重量 - ConditionText( - succ2Type == 1, - "符合标准包重量:${standardPackageWeight}kg" - ) - } - ConditionText( - (grossWeight == -1.0 || succ2Type == 1) && succ3, - "称稳定${weightStableTime}秒" + if (weightStableSeconds >= weightStableTime) "符合" else ":当前${weightStableSeconds}s" - ) - LaunchedEffect(succ2Type) { - viewModel.launchTaskNewFirst("干茧-灯光切换") { - when (succ2Type) { - 0 -> openYellowLight() - 1 -> openGreenLight() - 2 -> openRedLight() - else -> closeLight() - } - } - } - LaunchedEffect(succ1, succ2Type, succ3, hasBecomeZero) { - if (succ1 && (grossWeight == -1.0 || succ2Type == 1) && succ3 && hasBecomeZero) { - viewModel.launchTaskOldFirst("干茧-自动操作") { onFinish -> - onSucc(onFinish) - } - } - } - } - } - } - MyCheckBox( - modifier = M.padding(end = 10.dp), - title = title, - value = autoOperate - ) { - onAutoOperate(it) - if (!it) { - Light_.closeLight() - } - } - } - } -} - - -@Composable -fun MyWeightButton( - text: String, - isEnable: Boolean, - onClick: () -> Unit -) { - MyCard { - Box( - modifier = M - .fillMaxWidth() - .heightIn(45.dp) - .background( - Brush.verticalGradient( - colors = listOf( - if (isEnable) MyColors.BlueGreen else MyColors.Gray, - if (isEnable) MyColors.LightBlueGreen else MyColors.LightGray - ), - startY = 0f, - ) - ) - .clickable { onClick() }, - contentAlignment = Alignment.Center - ) { - Text( - text = text, - color = if (!isEnable) MyColors.White else MyColors.Black, - fontWeight = FontWeight.Bold, - fontSize = MaterialTheme.typography.headlineMedium.fontSize - ) - } - } -} - -@Composable -fun DryCocoonInfo(title: String, content: String, errorMsg: String) { - MyCard( - modifier = M - .fillMaxWidth(), - border = BorderStroke(1.dp, MyColors.BlueGreen) - ) { - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = M - .weight(1f) - .background(color = MyColors.LightBlueGreen) - ) { - Text( - text = title, - color = MyColors.Black, - textAlign = TextAlign.Center, - fontSize = MaterialTheme.typography.titleLarge.fontSize, - modifier = M - .padding(vertical = 10.dp) - .fillMaxWidth(), - ) - } - Row( - modifier = M - .weight(2f) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - modifier = M.padding(start = 10.dp), - text = errorMsg, - color = MyColors.Red, - fontWeight = FontWeight.Bold, - fontSize = MaterialTheme.typography.titleSmall.fontSize, - ) - Text( - modifier = M - .padding(end = 10.dp) - .widthIn(max = 150.dp), - text = content, - maxLines = 1, - overflow = TextOverflow.Ellipsis, // 超出部分显示省略号 - fontSize = MaterialTheme.typography.headlineLarge.fontSize, - fontWeight = FontWeight.Bold - ) - } - } - } -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonBaseViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonBaseViewModel.kt deleted file mode 100644 index b79f322..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonBaseViewModel.kt +++ /dev/null @@ -1,92 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.secondFunc - -import com.bbitcn.f8.pad.base.BaseViewModel -import com.bbitcn.f8.pad.utils.MMKVUtil -import com.bbitcn.f8.pad.utils.externalModules.devices.light.Light_ -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial -import com.bbitcn.f8.pad.utils.global.Global -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlin.collections.mutableListOf -import kotlin.collections.mutableSetOf - - -open class AddDryCocoonBaseViewModel : BaseViewModel() { - - private val _standardPackageWeight = MutableStateFlow(0.0) - val standardPackageWeight = _standardPackageWeight.asStateFlow() - - private val _weightAutoWaitTime = MutableStateFlow(0) - val weightAutoWaitTime = _weightAutoWaitTime.asStateFlow() - - /** - * 已处理的茧包ID 防止重复处理 - * key: 系统ID - * value: 茧包ID - */ - private val _hadHandleTagIds = mutableMapOf() - - // 临时存储需要过滤的茧包ID -// private val _tempTags = MutableStateFlow>(emptySet()) -// val tempTags = _tempTags.asStateFlow() - // 最终需要过滤的茧包ID - private val _forceFilterTags = MutableStateFlow>(emptySet()) - var forceFilterTags = _forceFilterTags.asStateFlow() - - private val _tagIds = MutableStateFlow>(emptyList()) - val tagIds = _tagIds.asStateFlow() - - init { - doInIoThreadNoDialog { - _standardPackageWeight.value = MMKVUtil.get(Global.STANDARD_PACKAGE_WEIGHT, 3.0) - _weightAutoWaitTime.value = MMKVUtil.get(Global.WEIGHT_AUTO_WAIT_TIME, 3) - // 如果已经连接读卡器,则开启 - UHFReaderForSerial.startAllScan() - } - } - - override fun onCleared() { - // 如果已经连接读卡器,则关闭 - UHFReaderForSerial.stopAllScan() - // 关闭指示灯 - Light_.closeLight() - super.onCleared() - } - - fun deleteHadHandleTagIds(sysId: String) { - doInIoThreadNoDialog { - _hadHandleTagIds.remove(sysId) - } - } - - fun addHadHandleTagIds(sysId: String, tagId: String) { - doInIoThreadNoDialog { - // 只保留最新的 - _hadHandleTagIds.clear() - _hadHandleTagIds[sysId] = tagId - } - } - - fun confirmTagIds(tagIds:List,onFinished: () -> Unit) { - _forceFilterTags.update { it + tagIds.toMutableSet() } - onFinished() - } - - fun clearForceHadHandleTagIds() { - _forceFilterTags.value = emptySet() - } - - fun filterTagIds(deviceTagIds: List) { - doInIoThreadNoDialog { - val temp = mutableListOf() - deviceTagIds.forEach { - if (!_forceFilterTags.value.contains(it) && !_hadHandleTagIds.containsValue(it)) { - temp.add(it) - } - } - _tagIds.value = temp - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonInScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonInScreen.kt deleted file mode 100644 index 2e7242a..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonInScreen.kt +++ /dev/null @@ -1,358 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.secondFunc - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.widthIn -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Cancel -import androidx.compose.material.icons.filled.Check -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.paging.compose.collectAsLazyPagingItems -import com.bbitcn.f8.pad.IS_DEBUG_DRYCOCOON -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MainFuncFrame -import com.bbitcn.f8.pad.base.MyButton -import com.bbitcn.f8.pad.base.MyCard -import com.bbitcn.f8.pad.base.MyCheckBox -import com.bbitcn.f8.pad.base.MyRefreshTable -import com.bbitcn.f8.pad.base.MyTableData -import com.bbitcn.f8.pad.model.net.request.DryCocoonSaveInDetailRequest -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.DryCocoonFilterDialog -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.DryCocoonInfoQueryDialog -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.scale.MyWeightShow -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -import com.bbitcn.f8.pad.ui.theme.MyColors -import com.bbitcn.f8.pad.ui.viewmodel.factory.AddDryCocoonInViewModelFactory -import com.bbitcn.f8.pad.utils.MyUtil - -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.printer.Page.MyLabelPrintDialog -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.printer.PrintState -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import kotlinx.coroutines.flow.flowOf - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun DryCocoonScreenPreview() { - DryCocoonInScreen("123") -} - -@Composable -fun DryCocoonInScreen( - sysId: String, - myCardReaderShowViewModel: MyCardReaderShowViewModel = viewModel(), -) { - val addDryCocoonInViewModel = viewModel( - factory = AddDryCocoonInViewModelFactory(sysId) - ) - val info by addDryCocoonInViewModel.info.collectAsState() - LaunchedEffect(Unit) { - myCardReaderShowViewModel.clearList() - } - val myPager = addDryCocoonInViewModel.dryCocoonInDetailMyPager - val dryIn = addDryCocoonInViewModel.dryCocoonInDetailPager.collectAsLazyPagingItems() - val isRefreshing by myPager.listIsRefreshing.collectAsState() - var needPrintLabel by rememberSaveable { mutableStateOf(false) } - var hasBecomeZero by rememberSaveable { mutableStateOf(true) } - val dryCocoonInfoQueryDialogData by addDryCocoonInViewModel.dryCocoonInfoQueryDialogData.collectAsState() - val dryCocoonFilterDialog by addDryCocoonInViewModel.dryCocoonFilterDialog.collectAsState() - MainFuncFrame { - Row( - modifier = M - .fillMaxWidth() - ) { - MyCard( - modifier = M - .fillMaxSize() - .weight(2f) - ) { - Column( - modifier = M - .fillMaxSize() - .padding(10.dp) - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = M - .padding(horizontal = 10.dp) - .fillMaxWidth() - ) { - Text( - modifier = M.padding(vertical = 5.dp), - text = info.code, - maxLines = 1, - color = MyColors.Orange, - fontSize = MaterialTheme.typography.headlineSmall.fontSize, - fontWeight = FontWeight.Bold - ) - VerticalInfo("茧站", info.depname) - VerticalInfo("仓库", info.ckname) - VerticalInfo("品种", info.cpzname) - VerticalInfo("茧别", info.jiantype) - VerticalInfo("区域", info.xiangzhen) - BigVerticalInfo("总包数", info.baoshu.toString()) - } - MyRefreshTable( - modifier = M - .fillMaxWidth() - .padding() - .weight(1f), - isRefreshing = isRefreshing, - info = dryIn, - key = { it.sysid }, - onFinishRefresh = { - myPager.setListIsRefreshClose() - }, - onLongClick = { - Toasty.showConfirmDialog("是否删除<${it.code}>茧包") { - addDryCocoonInViewModel.deleteDryCocoonInDetail(it.sysid) { - myCardReaderShowViewModel.clearList() - dryIn.refresh() - } - } - }, - items = listOf( - MyTableData("包码", 3, { it.code }), - MyTableData("毛重", 2, { it.maozhong.toString() }), - MyTableData("皮重", 2, { it.pizhong.toString() }), - MyTableData("净重", 2, { it.jingzhong.toString() }), - MyTableData("操作", 2, { "补打茧票" }, true) { - addDryCocoonInViewModel.printDryCocoonLabel(it.sysid) - }), - scrollToTopOnRefresh = true, - verticalPadding = 5.dp - ) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = M - .padding(horizontal = 10.dp) - .fillMaxWidth() - ) { - VerticalInfo("烘茧人", info.hongjianren) - VerticalInfo("日期", info.datetime) - } - } - } - var grossWeight by rememberSaveable { mutableStateOf(0.0) } - var netWeight = MyUtil.formatDouble(grossWeight - info.bagzhongliang) - - val curReader by myCardReaderShowViewModel.curDevice.collectAsState() - - val deviceTagIds by (curReader?.tagList - ?: flowOf(emptyList())).collectAsState(initial = emptyList()) - val tagIds by addDryCocoonInViewModel.tagIds.collectAsState() - LaunchedEffect(deviceTagIds) { - addDryCocoonInViewModel.filterTagIds(deviceTagIds) - } - MyCard( - modifier = M - .weight(1f) - .padding(start = 10.dp), - ) { - var weightErrorMsg = rememberSaveable { "" } - val tagErrorMsg = - if (curReader == null) "未检测到读卡器" - else if (tagIds.isEmpty()) "未检测到新麻袋" - else if (tagIds.size > 1) "检测到多个麻袋" - else "" - val netWeightErrorMsg = if (netWeight < 0) "净重小于0" else "" - // 称稳定时间 - var weightStableSeconds by rememberSaveable { mutableStateOf(0) } - var autoOperate by rememberSaveable { mutableStateOf(false) } - Column( - modifier = M - .fillMaxWidth() - .padding(10.dp) - ) { - Column( - verticalArrangement = Arrangement.spacedBy(5.dp), - horizontalAlignment = Alignment.End - ) { - val standardPackageWeight by addDryCocoonInViewModel.standardPackageWeight.collectAsState() - MyWeightShow(targetStableWeight = standardPackageWeight, onErrorMsg = { - weightErrorMsg = it - }, onStableTimeChanged = { - weightStableSeconds = it - }) { - grossWeight = it - if (it == 0.0) { - hasBecomeZero = true - } - } - DryCocoonInfo("皮重(${info.bagtype})", "${info.bagzhongliang}kg", "") - DryCocoonInfo( - "净重", "${netWeight}kg", netWeightErrorMsg - ) - DryCocoonInfo( - "麻袋ID", - if (tagIds.isNotEmpty()) "${tagIds[0].take(2)}...${tagIds[0].takeLast(4)}" else "", - tagErrorMsg - ) - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton( - text = "查询茧包信息", - contentPadding = PaddingValues(5.dp, 2.5.dp) - ) { - if (autoOperate) { - Toasty.showTipsDialog("请先关闭自动入库,以防误操作") - return@MyButton - } - addDryCocoonInViewModel.showDryCocoonInfoQueryDialog() - } - MyButton( - text = "过滤特殊茧包", - contentPadding = PaddingValues(5.dp, 2.5.dp) - ) { - if (autoOperate) { - Toasty.showTipsDialog("请先关闭自动入库,以防误操作") - return@MyButton - } - addDryCocoonInViewModel.showDryCocoonFilterDialog( - myCardReaderShowViewModel - ) - } - MyButton( - text = "重新检测茧包", - contentPadding = PaddingValues(5.dp, 2.5.dp) - ) { - myCardReaderShowViewModel.clearList() - } - } - if (IS_DEBUG_DRYCOCOON) { - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton(text = "增加随机芯片") { - UHFReaderG06M_G25M.testXP() - } - MyButton(text = "测试增加芯片1") { - UHFReaderG06M_G25M.testXP("521323232") - } - } - } - } - Spacer(modifier = M.weight(1f)) - val onSave = { onFinish: () -> Unit -> - addDryCocoonInViewModel.saveDryCocoonInDetail( - DryCocoonSaveInDetailRequest( - rfid = tagIds[0], - rksysid = sysId, - jingzhong = netWeight, - maozhong = grossWeight, - pizhong = info.bagzhongliang - ), needPrintLabel, { - // 保存成功后清空数据 - dryIn.refresh() - myCardReaderShowViewModel.clearList() - }, onFinish = onFinish - ) - } - Column(modifier = M.fillMaxWidth()) { - AutoOperate( - "自动入库", - tagIds, - grossWeight, - weightStableSeconds, - addDryCocoonInViewModel, - hasBecomeZero, autoOperate = autoOperate, { - autoOperate = it - } - ) { it -> - hasBecomeZero = false - onSave.invoke { it.invoke() } - } - Row( - modifier = M.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.End - ) { - var isConnected by rememberSaveable { mutableStateOf(false) } - PrintState { - isConnected = it - } - MyCheckBox( - modifier = M.padding(end = 10.dp), - title = "打印茧票", - value = needPrintLabel - ) { - if (!isConnected && it) { - Toasty.error("打印机未连接,无法开启打印") - } else { - needPrintLabel = it - } - } - } - val allErrorMsg = if (tagErrorMsg.isNotEmpty()) tagErrorMsg + "\n" else "" + - if (netWeightErrorMsg.isNotEmpty()) netWeightErrorMsg + "\n" else "" + - if (weightErrorMsg.isNotEmpty()) weightErrorMsg + "\n" else "" - MyWeightButton( - text = "保存本包", - isEnable = allErrorMsg.isEmpty(), - ) { - // 增加称重 - if (allErrorMsg.isEmpty()) { - onSave.invoke { } - } else { - Toasty.showTipsDialog(allErrorMsg) - } - } - } - } - } - } - } - val myLabelPrintDialogData by addDryCocoonInViewModel.myLabelPrintDialogData.collectAsState() - MyLabelPrintDialog(myLabelPrintDialogData) - DryCocoonInfoQueryDialog(dryCocoonInfoQueryDialogData) - DryCocoonFilterDialog(dryCocoonFilterDialog) -} - -@Composable -fun ConditionText(isOK: Boolean, text: String) { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon( - imageVector = if (isOK) Icons.Filled.Check else Icons.Filled.Cancel, - contentDescription = null, - tint = if (isOK) MyColors.Green else MyColors.Red - ) - Text( - modifier = M.padding(start = 5.dp), - text = text, - color = if (isOK) MyColors.Green else MyColors.Red, - fontWeight = FontWeight.Bold, - fontSize = MaterialTheme.typography.titleSmall.fontSize - ) - } -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonInViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonInViewModel.kt deleted file mode 100644 index 0c31e21..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonInViewModel.kt +++ /dev/null @@ -1,175 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.secondFunc - -import android.media.MediaPlayer -import androidx.lifecycle.viewModelScope -import androidx.lifecycle.viewmodel.compose.viewModel -import com.bbitcn.f8.pad.R -import com.bbitcn.f8.pad.model.net.request.DryCocoonSaveInDetailRequest -import com.bbitcn.f8.pad.model.net.response.CocoonInDetailResponse -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.DryCocoonFilterDialogData -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.DryCocoonInfoQueryDialogData -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.printer.Page.MyLabelPrintDialogData -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -import com.bbitcn.f8.pad.utils.AudioPlayer -import com.bbitcn.f8.pad.utils.TTSManager -import com.bbitcn.f8.pad.utils.TTSManager.toChineseNumber -import com.bbitcn.f8.pad.utils.pager.DryCocoonInDetailPagingSource -import com.bbitcn.f8.pad.utils.pager.MyPager -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update - - -class AddDryCocoonInViewModel(val inSystemId: String) : AddDryCocoonBaseViewModel() { - - private var mediaPlayer: MediaPlayer? = null - - override fun onCleared() { - super.onCleared() - mediaPlayer?.release() - } - - private val _myLabelPrintDialogData = MutableStateFlow(MyLabelPrintDialogData()) - val myLabelPrintDialogData = _myLabelPrintDialogData.asStateFlow() - - private val _info = MutableStateFlow(CocoonInDetailResponse.Data()) - val info = _info.asStateFlow() - - init { - refreshDryCocoonInDetail(true) - } - - /** - * 刷新入库详情 - */ - fun refreshDryCocoonInDetail(needForce: Boolean = false) { - doInIoThreadWith(needForce, "正在刷新入库详情") { - val info = apiService.getCocoonInDetail(inSystemId) - if (info.code != 1) { - Toasty.showTipsDialog("请求错误,请尝试退出重新进入:${info.msg}") - } else { - _info.value = info.data - } - } - } - - /** - * 入库详情 - */ - val dryCocoonInDetailMyPager = MyPager( - pagingSourceFactory = { DryCocoonInDetailPagingSource(inSystemId) }, - initialRequestData = "", // 传入初始的请求数据 - ) - val dryCocoonInDetailPager = dryCocoonInDetailMyPager.createPager(viewModelScope) - - fun saveDryCocoonInDetail( - dryCocoonSaveInDetailRequest: DryCocoonSaveInDetailRequest, - needPrintLabel: Boolean, - onSuccess: () -> Unit, - onFinish: () -> Unit, - ) { - doInIoThread("正在保存本包记录", onFinish = onFinish, onError = { - // 当发生错误时 -// TTSManager.speak("入库失败,请检查网络连接", true) - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_in_failed_net, true) - }) { - val response = - apiService.saveDryCocoonInDetail(dryCocoonSaveInDetailRequest.copy(cjsysid = _info.value.cjsysid)) - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_in_failed) - } else { - Toasty.success("保存成功") - addHadHandleTagIds(response.data.toString(), dryCocoonSaveInDetailRequest.rfid) - onSuccess() - if (needPrintLabel) { - printDryCocoonLabel(response.data.toString()) - } - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_in_success) - } -// TTSManager.speak( -// if (response.code == 1) "第" + (_info.value.baoshu + 1).toChineseNumber() + "包已入库" else "入库失败,请联系管理员", -// true -// ) - refreshDryCocoonInDetail(false) - } - } - - fun printDryCocoonLabel(sysId: String) { - doInIoThread("正在打印标签") { - val ticketInfo = apiService.getDryCocoonInTicketInfo(sysId) - if (ticketInfo.code == 1) { - _myLabelPrintDialogData.value = MyLabelPrintDialogData( - showDialog = true, - ticketInfo = ticketInfo.data, - onDismissRequest = { - _myLabelPrintDialogData.value = - _myLabelPrintDialogData.value.copy(showDialog = false) - } - ) - } else { - Toasty.showTipsDialog(ticketInfo.msg) - } - } - } - - fun deleteDryCocoonInDetail(itemsysid: String, onSuccess: () -> Unit) { - doInIoThread("正在删除本包入库记录") { - val response = apiService.deleteDryCocoonInDetail(itemsysid) - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("删除成功") - onSuccess() - // 删除已处理的RFID 必须在成功后删除 - deleteHadHandleTagIds(itemsysid) - refreshDryCocoonInDetail(false) - } - } - } - - private val _dryCocoonInfoQueryDialogData = MutableStateFlow(DryCocoonInfoQueryDialogData()) - val dryCocoonInfoQueryDialogData = _dryCocoonInfoQueryDialogData.asStateFlow() - - fun showDryCocoonInfoQueryDialog() { - doInIoThread { - _dryCocoonInfoQueryDialogData.value = DryCocoonInfoQueryDialogData( - showDialog = true, - cjsysid = _info.value.cjsysid, - jiantypesysid = _info.value.jiantypesysid, - gjcksysid = _info.value.gjcksysid, - printTicket = { - printDryCocoonLabel(it) - }, - onDismiss = { - _dryCocoonInfoQueryDialogData.value = - _dryCocoonInfoQueryDialogData.value.copy(showDialog = false) - } - ) - } - } - - private val _dryCocoonFilterDialog = - MutableStateFlow( - DryCocoonFilterDialogData( - viewModel = this, - myCardReaderShowViewModel = MyCardReaderShowViewModel() - ) - ) - val dryCocoonFilterDialog = _dryCocoonFilterDialog.asStateFlow() - - fun showDryCocoonFilterDialog(myCardReaderShowViewModel: MyCardReaderShowViewModel) { - doInIoThread { - _dryCocoonFilterDialog.value = DryCocoonFilterDialogData( - showDialog = true, - viewModel = this, - myCardReaderShowViewModel = myCardReaderShowViewModel, - onDismiss = { - _dryCocoonFilterDialog.update { it.copy(showDialog = false) } - } - ) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonOutScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonOutScreen.kt deleted file mode 100644 index 1071a54..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonOutScreen.kt +++ /dev/null @@ -1,303 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.secondFunc - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.paging.compose.collectAsLazyPagingItems -import com.bbitcn.f8.pad.IS_DEBUG_DRYCOCOON -import com.bbitcn.f8.pad.M -import com.bbitcn.f8.pad.base.MainFuncFrame -import com.bbitcn.f8.pad.base.MyButton -import com.bbitcn.f8.pad.base.MyCard - -import com.bbitcn.f8.pad.base.MyRefreshTable -import com.bbitcn.f8.pad.base.MyTableData -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.DryCocoonLossDialogInOut -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.scale.MyWeightShow -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader.MyCardReaderShowViewModel -import com.bbitcn.f8.pad.ui.theme.MyColors -import com.bbitcn.f8.pad.ui.viewmodel.factory.AddDryCocoonOutViewModelFactory -import com.bbitcn.f8.pad.utils.MyUtil -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import com.bbitcn.f8.pad.utils.log.MyLog -import kotlinx.coroutines.flow.flowOf - -@Preview(showBackground = true, widthDp = 1280, heightDp = 800) -@Composable -fun DryCocoonOutScreenPreview() { - DryCocoonOutScreen("1123") -} - -@Composable -fun DryCocoonOutScreen( - sysId: String, - myCardReaderShowViewModel: MyCardReaderShowViewModel = viewModel() -) { - LaunchedEffect(Unit) { - MyLog.test("第一次进入,清空tagId缓存") - myCardReaderShowViewModel.clearList() - } - val addDryCocoonOutViewModel = viewModel( - factory = AddDryCocoonOutViewModelFactory(sysId) - ) - val info by addDryCocoonOutViewModel.info.collectAsState() - val myPager = addDryCocoonOutViewModel.dryCocoonOutDetailMyPager - val dryOut = - addDryCocoonOutViewModel.dryCocoonOutDetailPager.collectAsLazyPagingItems() - val isRefreshing by myPager.listIsRefreshing.collectAsState() - val dryCocoonLossDialogData by addDryCocoonOutViewModel.dryCocoonLossDialogData.collectAsState() - - MainFuncFrame { - Row( - modifier = M - .fillMaxWidth() - ) { - MyCard( - modifier = M - .fillMaxSize() - .weight(2f) - ) { - Column( - modifier = M - .weight(2f) - .padding(10.dp) - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = M - .padding(10.dp) - .fillMaxWidth() - ) { - Text( - modifier = M.padding(vertical = 5.dp), - text = info.code, - maxLines = 1, - color = MyColors.Orange, - fontSize = MaterialTheme.typography.headlineSmall.fontSize, - fontWeight = FontWeight.Bold - ) - VerticalInfo("仓库", info.ckname) - VerticalInfo("茧别", info.jiantype) - VerticalInfo("蚕品种", info.canpinzhong) - VerticalInfo("空包释放", info.releasebaoshu.toString()) - BigVerticalInfo("总包数", info.baoshu.toString()) - } - MyRefreshTable( - modifier = M - .fillMaxWidth() - .weight(1f), - isRefreshing = isRefreshing, - - info = dryOut, - key = { it.sysid }, - onFinishRefresh = { - myPager.setListIsRefreshClose() - }, - onLongClick = { - Toasty.showConfirmDialog("是否删除<${it.code}>茧包") { - addDryCocoonOutViewModel.deleteDryCocoonOutDetail(it.sysid) { - dryOut.refresh() - } - } - }, - items = listOf( - MyTableData("包码", 3, { it.code }), - MyTableData("毛重", 2, { it.maozhong.toString() }), - MyTableData("皮重", 2, { it.pizhong.toString() }), - MyTableData("净重", 2, { it.jingzhong.toString() }), - ), - scrollToTopOnRefresh = true, - ) - - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = M - .padding(10.dp) - .fillMaxWidth() - ) { - VerticalInfo("区域", info.xiangzhen) - VerticalInfo("往来单位", info.wldwname) - VerticalInfo("车牌号", info.carpaihao) - VerticalInfo( - "日期", info.ckdatetime.replace(" ", "\n") - ) - } - } - } - var grossWeight by rememberSaveable { mutableStateOf(0.0) } - var netWeight = MyUtil.formatDouble(grossWeight - info.bagzhongliang) - val curReader by myCardReaderShowViewModel.curDevice.collectAsState() - val deviceTagIds by (curReader?.tagList - ?: flowOf(emptyList())).collectAsState(initial = emptyList()) -// val tagIds by (curReader?.tagList -// ?: flowOf(emptyList())).collectAsState(initial = emptyList()) - val tagIds by addDryCocoonOutViewModel.tagIds.collectAsState() - // 称稳定时间 - var weightStableSeconds by rememberSaveable { mutableStateOf(0) } - var hasBecomeZero by rememberSaveable { mutableStateOf(true) } - var isAutoOperate by rememberSaveable { mutableStateOf(false) } - LaunchedEffect(deviceTagIds) { - addDryCocoonOutViewModel.filterTagIds(deviceTagIds) - } - MyCard( - modifier = M - .weight(1f) - .padding(start = 10.dp), - ) { - Column( - modifier = M.padding(10.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - horizontalAlignment = Alignment.End - ) { - var weightErrorMsg by rememberSaveable { mutableStateOf("") } - val tagErrorMsg = - if (curReader == null) "未检测到读卡器" - else if (tagIds.isEmpty()) "未检测到麻袋" - else if (tagIds.size > 1) "检测到多个麻袋" - else "" - val netWeightErrorMsg = if (netWeight < 0) "净重小于0" else "" - val standardPackageWeight by addDryCocoonOutViewModel.standardPackageWeight.collectAsState() - val onSave = { onFinish: () -> Unit -> - addDryCocoonOutViewModel.saveDryCocoonOutDetail( - rfid = tagIds[0], netWeight = netWeight, grossWeight = grossWeight, { - dryOut.refresh() - myCardReaderShowViewModel.clearList() - }, onFinish = onFinish - ) - } - val allErrorMsg = if (tagErrorMsg.isNotEmpty()) tagErrorMsg + "\n" else "" + - if (netWeightErrorMsg.isNotEmpty()) netWeightErrorMsg + "\n" else "" + - if (weightErrorMsg.isNotEmpty()) weightErrorMsg + "\n" else "" - MyWeightShow(targetStableWeight = standardPackageWeight, onErrorMsg = { - weightErrorMsg = it - }, onStableTimeChanged = { - weightStableSeconds = it - }) { - grossWeight = it - if (it == 0.0) { - hasBecomeZero = true - } - } - DryCocoonInfo("皮重(${info.bagtype})", "${info.bagzhongliang}kg", "") - DryCocoonInfo( - "净重", "${netWeight}kg", netWeightErrorMsg - ) - DryCocoonInfo( - "麻袋ID", - if (tagIds.isNotEmpty()) "${tagIds[0].take(2)}...${tagIds[0].takeLast(4)}" else "", - tagErrorMsg - ) - - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton( - modifier = M.padding(start = 5.dp), - text = "新增茧包出库", - enabled = allErrorMsg.isEmpty(), - ) { - if (isAutoOperate) { - Toasty.showTipsDialog("请先关闭自动出库,以防误操作") - } else if (!allErrorMsg.isEmpty()) { - Toasty.showTipsDialog(allErrorMsg) - } else { - Toasty.showConfirmDialog( - "该茧包未入库,将作为额外茧包出库", - "新增茧包出库" - ) { - addDryCocoonOutViewModel.addNewPackageOut( - netWeight = netWeight, - grossWeight = grossWeight, - rfid = tagIds[0] - ){ - dryOut.refresh() - myCardReaderShowViewModel.clearList() - } - } - } - } - MyButton(text = "重新检测茧包") { - myCardReaderShowViewModel.clearList() - } - } - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton( - modifier = M.padding(start = 5.dp), - text = "释放空包" - ) { - if (isAutoOperate) { - Toasty.showTipsDialog("请先关闭自动出库,以防误操作") - return@MyButton - } - addDryCocoonOutViewModel.showLossPackageForOut() - } - } - if (IS_DEBUG_DRYCOCOON) { - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - MyButton(text = "增加随机芯片") { - UHFReaderG06M_G25M.testXP() - } - MyButton(text = "测试增加芯片1") { - UHFReaderG06M_G25M.testXP("521323232") - } - } - } - Spacer(modifier = M.weight(1f)) - Column(modifier = M.fillMaxWidth()) { - AutoOperate( - "自动出库", - tagIds, - grossWeight, - weightStableSeconds, - addDryCocoonOutViewModel, - hasBecomeZero, autoOperate = isAutoOperate, onAutoOperate = { - isAutoOperate = it - } - ) { - hasBecomeZero = false - onSave.invoke { it.invoke() } - } - MyWeightButton( - text = "出库本包", - isEnable = allErrorMsg.isEmpty(), - ) { - // 出库本包 - if (allErrorMsg.isEmpty()) { - onSave.invoke { } - } else { - Toasty.showTipsDialog(allErrorMsg) - } - } - } - } - } - } - } - DryCocoonLossDialogInOut(dryCocoonLossDialogData) -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonOutViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonOutViewModel.kt deleted file mode 100644 index b3e3df8..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddDryCocoonOutViewModel.kt +++ /dev/null @@ -1,207 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.secondFunc - -import androidx.lifecycle.viewModelScope -import com.bbitcn.f8.pad.R -import com.bbitcn.f8.pad.model.net.request.DryCocoonPackageForOutLossRequest -import com.bbitcn.f8.pad.model.net.request.DryCocoonSaveNewOutDetail -import com.bbitcn.f8.pad.model.net.request.DryCocoonSaveOutDetail -import com.bbitcn.f8.pad.model.net.request.SearchOutDetailByRFIDRequest -import com.bbitcn.f8.pad.model.net.response.CocoonOutDetailResponse -import com.bbitcn.f8.pad.ui.screen.dialog.drycocoon.DryCocoonLossDialogInOutData -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.utils.AudioPlayer -import com.bbitcn.f8.pad.utils.TimeUtils -import com.bbitcn.f8.pad.utils.pager.DryCocoonOutDetailPagingSource -import com.bbitcn.f8.pad.utils.pager.MyPager -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlin.random.Random - - -class AddDryCocoonOutViewModel(val outSystemId: String) : AddDryCocoonBaseViewModel() { - - private val _info = MutableStateFlow(CocoonOutDetailResponse.Data()) - val info = _info.asStateFlow() - - init { - refreshDryCocoonOutDetail(true) - } - - /** - * 出库详情统计信息 - */ - fun refreshDryCocoonOutDetail(showDialog: Boolean = true) { - doInIoThreadWith(showDialog, "正在刷新出库详情") { - val info = apiService.getCocoonOutDetail(outSystemId) - if (info.code != 1) { - Toasty.showTipsDialog("请求错误,请尝试退出重新进入:${info.msg}") - } else { - _info.value = info.data - } - } - } - - /** - * 出库详情 - */ - val dryCocoonOutDetailMyPager = MyPager( - pagingSourceFactory = { DryCocoonOutDetailPagingSource(outSystemId) }, - initialRequestData = "", // 传入初始的请求数据 - ) - val dryCocoonOutDetailPager = dryCocoonOutDetailMyPager.createPager(viewModelScope) - - fun saveDryCocoonOutDetail( - rfid: String, - netWeight: Double, - grossWeight: Double, - onSuccess: () -> Unit, - onFinish: () -> Unit = { } // 添加onFinish回调 - ) { - doInIoThread("正在保存本包出库记录", onFinish = onFinish, onError = { - // 当发生错误时 - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_out_failed_net) -// TTSManager.speak("出库失败,网络异常,请检查网络连接", true) - }) { - val searchOutDetailByRFIDRequest: SearchOutDetailByRFIDRequest = - SearchOutDetailByRFIDRequest( - cjsysid = _info.value.cjsysid, - jiantypesysid = _info.value.jiantypesysid, - gjcksysid = _info.value.gjcksysid, - rfid = rfid - ) - val dryCocoonSaveOutDetail = - DryCocoonSaveOutDetail( - rfid = rfid, - cksysid = _info.value.sysid, - code = _info.value.code, - baoshu = 1, - jingzhong = netWeight, - maozhong = grossWeight, - pizhong = _info.value.bagzhongliang - ) - var res = false - // 根据RFID查询包码 - val searchResponse = apiService.searchOutDetailByRFID(searchOutDetailByRFIDRequest) - if (searchResponse.code != 1) { - Toasty.showTipsDialog(searchResponse.msg) - } else { - // 检查是否出库· - if (searchResponse.data.ischuku == 1) { -// TTSManager.speak("该包已出库,无法继续出库") - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_out_failed) - Toasty.showTipsDialog("该包已出库,无法继续出库") - } else { - // 保存出库记录 - val response = - apiService.saveDryCocoonOutDetail(dryCocoonSaveOutDetail.copy(code = searchResponse.data.code)) - if (response.code != 1) { - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_out_failed) -// TTSManager.speak("出库失败," + response.msg) - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("保存成功") - addHadHandleTagIds(searchResponse.data.sysid, searchOutDetailByRFIDRequest.rfid ) - AudioPlayer.playAudioOnce(R.raw.dry_cocoon_out_success) -// TTSManager.speak("第" + (_info.value.baoshu + 1).toChineseNumber() + "包已出库") - refreshDryCocoonOutDetail(false) - onSuccess() - res = true - } - } - } - } - } - - /** - * 新增茧包出库 - */ - fun addNewPackageOut(rfid: String, netWeight: Double, grossWeight: Double,onSuccess: () -> Unit) { - doInIoThread { - val res = apiService.addNewPackageOut( - DryCocoonSaveNewOutDetail( - jingzhong = netWeight, - maozhong = grossWeight, - pizhong = _info.value.bagzhongliang, - cksysid = _info.value.sysid, - rfid = rfid, - ) - ) - if (res.code != 1) { - Toasty.showTipsDialog(res.msg) - } else { - Toasty.success("新包已直接出库") - addHadHandleTagIds(res.data.toString(), rfid ) - refreshDryCocoonOutDetail(false) - // 刷新出库列表 - onSuccess() - } - } - } - - fun deleteDryCocoonOutDetail(itemsysid: String, onSuccess: () -> Unit) { - doInIoThread("正在删除本包出库记录") { - val response = apiService.deleteDryCocoonOutDetail(itemsysid) - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("删除成功") - onSuccess() - // 删除已处理的RFID 必须在成功后删除 - deleteHadHandleTagIds(itemsysid) - refreshDryCocoonOutDetail(false) - } - } - } - - /** - * 出库-空包释放 - */ - private val _dryCocoonLossDialogData: MutableStateFlow = - MutableStateFlow(DryCocoonLossDialogInOutData()) - val dryCocoonLossDialogData = _dryCocoonLossDialogData.asStateFlow() - - fun showLossPackageForOut() { - doInIoThread { - _dryCocoonLossDialogData.value = - DryCocoonLossDialogInOutData( - true, - onLossPackage = { rfids, onFinish -> - doInIoThread("正在释放空包") { - rfids.forEach { - // 释放空包 - val response = apiService.onLossPackageForOut( - DryCocoonPackageForOutLossRequest( - ckdsysid = _info.value.sysid, - rfid = it, - time = TimeUtils.getStringTime(), - cjsysid = _info.value.cjsysid - ) - ) - if (response.code != 1) { - Toasty.showTipsDialog(response.msg) - } else { - Toasty.success("释放成功") - onFinish() - } - } - refreshDryCocoonOutDetail(false) - } - }, - onDismiss = { - _dryCocoonLossDialogData.update { it.copy(showDialog = false) } - } - ) - } - } - -// fun getPackageWeightByName(name: String): Double { -// for (i in _packageKinds.value) { -// if (i.name == name) { -// return i.weight -// } -// } -// return 0.0 -// } - -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserScreen.kt index d1a2f01..00b5435 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserScreen.kt @@ -41,7 +41,6 @@ import androidx.navigation.NavController import androidx.navigation.compose.rememberNavController import coil3.compose.AsyncImage -import com.bbitcn.f8.pad.ui.screen.dialog.ScanDialog import com.bbitcn.f8.pad.R import com.bbitcn.f8.pad.base.BigButton import com.bbitcn.f8.pad.base.MainFuncFrame @@ -574,20 +573,6 @@ fun AddUserLeftColumn( ) { addUserViewModel.idCardNumber = it } - MyButton(text = "NFC") { - addUserViewModel.openIDCardDialog({ - addUserViewModel.idName = it.name - addUserViewModel.idGender = it.sex - addUserViewModel.idCardNumber = it.id - addUserViewModel.idCardAddress = it.address - }) { xian, xiang, cun, zu -> - // 地址解析 - addUserViewModel.userXian = xian - addUserViewModel.userXiang = xiang - addUserViewModel.userCun = cun - addUserViewModel.userZu = zu - } - } VipBadge { MyButton(text = "拍照识别") { addUserViewModel.recognizeIdCard({ name, gender, idCard, address -> @@ -660,9 +645,6 @@ fun AddUserRightColumn( addUserViewModel.clearBankCardInfo(true) addUserViewModel.updateBankCardCode(true, it) } - MyButton(text = "NFC") { - addUserViewModel.openNFCDialog(true) - } VipBadge { MyButton(text = "拍照识别") { addUserViewModel.recognizeBankCard(true) @@ -687,9 +669,6 @@ fun AddUserRightColumn( addUserViewModel.clearBankCardInfo(false) addUserViewModel.updateBankCardCode(false, it) } - MyButton(text = "NFC") { - addUserViewModel.openNFCDialog(false) - } VipBadge { MyButton(text = "拍照识别") { addUserViewModel.recognizeBankCard(false) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserViewModel.kt index 6490cf9..7f9fa4e 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserViewModel.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserViewModel.kt @@ -18,14 +18,10 @@ import com.bbitcn.f8.pad.model.net.response.FarmerFileListResponse import com.bbitcn.f8.pad.model.net.response.UserTypeResponse import com.bbitcn.f8.pad.ui.screen.dialog.FaceDialogData import com.bbitcn.f8.pad.ui.screen.dialog.OCRDialogData -import com.bbitcn.f8.pad.ui.screen.dialog.ScanDialogData import com.bbitcn.f8.pad.ui.screen.view.Toasty import com.bbitcn.f8.pad.ui.screen.view.Toasty.showTipsDialog import com.bbitcn.f8.pad.utils.externalModules.devices.reader.face.OssUtils -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.idcard.IDCardUtils -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.nfc.NFCUtils import com.bbitcn.f8.pad.utils.log.MyLog -import com.zkteco.android.biometric.module.idcard.meta.IDCardInfo import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update @@ -42,10 +38,6 @@ class AddUserViewModel : BaseViewModel() { private val _userExtendList = MutableStateFlow>(emptyList()) val userExtendList = _userExtendList.asStateFlow() - - private val _scanDialogData = MutableStateFlow(ScanDialogData()) - val scanDialogData = _scanDialogData.asStateFlow() - private val _ocrDialogData = MutableStateFlow(OCRDialogData()) val ocrDialogData = _ocrDialogData.asStateFlow() @@ -215,47 +207,6 @@ class AddUserViewModel : BaseViewModel() { } } - fun closeScanDialog() { - doInIoThreadNoDialog { - _scanDialogData.update { it.copy(showDialog = false) } - if (_scanDialogData.value.isNFC) { - // 关闭NFC Reader Mode - NFCUtils.disableReaderMode() - } else { - // 关闭身份证读卡模块 - IDCardUtils.closeGPIO() - } - } - } - - fun openIDCardDialog( - onCardReadListener: (IDCardInfo) -> Unit, - onAnalysisAddressListener: (String, String, String, String) -> Unit - ) { - doInIoThreadNoDialog { - try { - _scanDialogData.update { - it.copy(showDialog = true, isNFC = false) { - closeScanDialog() - } - } - // 初始化身份证读卡模块 - IDCardUtils.openGPIO() - IDCardUtils.openDevice { - // 读取到身份证信息 - onCardReadListener(it) - analysisIdAddress(it.address) { xian, xiang, cun, zu -> - onAnalysisAddressListener(xian, xiang, cun, zu) - closeScanDialog() - } - } - } catch (e: Exception) { - e.printStackTrace() - closeScanDialog() - } - } - } - fun analysisIdAddress( address: String, onAnalysisAddressListener: (String, String, String, String) -> Unit @@ -270,7 +221,6 @@ class AddUserViewModel : BaseViewModel() { addressResult.data.zu ) } - closeScanDialog() } } @@ -344,32 +294,8 @@ class AddUserViewModel : BaseViewModel() { } } afterAnalysis() - closeScanDialog() } } - - fun openNFCDialog(isMainCard: Boolean) { - doInIoThreadNoDialog { - try { - _scanDialogData.update { - it.copy(showDialog = true, isNFC = true) { - closeScanDialog() - } - } - // 初始化NFC Reader Mode - NFCUtils.init(isPayCard = true) { - // 读取到卡号 - analysisBankCard(it, isMainCard) { - closeScanDialog() - } - } - } catch (e: Exception) { - e.printStackTrace() - closeScanDialog() - } - } - } - fun editFarmer() { doInIoThread("正在" + if (sysId.isNotEmpty()) "修改信息" else "新增农户") { if ( diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShow.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShow.kt deleted file mode 100644 index a9ddca6..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShow.kt +++ /dev/null @@ -1,89 +0,0 @@ -//package com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader -// -//import androidx.compose.foundation.layout.Arrangement -//import androidx.compose.foundation.layout.Box -//import androidx.compose.foundation.layout.Row -//import androidx.compose.foundation.layout.fillMaxSize -//import androidx.compose.foundation.layout.fillMaxWidth -//import androidx.compose.foundation.layout.height -//import androidx.compose.foundation.layout.padding -//import androidx.compose.foundation.layout.width -//import androidx.compose.material3.MaterialTheme -//import androidx.compose.material3.Text -//import androidx.compose.runtime.Composable -//import androidx.compose.runtime.LaunchedEffect -//import androidx.compose.runtime.collectAsState -//import androidx.compose.runtime.getValue -//import androidx.compose.ui.Alignment -//import androidx.compose.ui.Modifier -//import androidx.compose.ui.text.font.FontWeight -//import androidx.compose.ui.tooling.preview.Preview -//import androidx.compose.ui.unit.dp -//import androidx.compose.ui.unit.sp -//import androidx.lifecycle.viewmodel.compose.viewModel -//import com.bbitcn.f8.pad.M -//import com.bbitcn.f8.pad.base.MyCard -//import com.bbitcn.f8.pad.ui.screen.view.common.CombinedDropdownMenu -// -//import com.bbitcn.f8.pad.ui.theme.MyColors -// -//@Preview(showBackground = true) -//@Composable -//fun MyCardReaderShowPreview() { -// MyCardReaderShow() -//} -// -//@Composable -//fun MyCardReaderShow( -// modifier: Modifier = M, -// myCardReaderShowViewModel: MyCardReaderShowViewModel = viewModel(), -// onErrorMsg: (String) -> Unit = {}, -// onValueChange: (Double) -> Unit = {} -//) { -// val weight by myCardReaderShowViewModel.curWeight.collectAsState() -// val curScale by myCardReaderShowViewModel.curScale.collectAsState() -// val scaleOptions by myCardReaderShowViewModel.scaleOptions.collectAsState() -// LaunchedEffect(weight) { -// onValueChange(weight) -// } -// MyCard(modifier = modifier, colors = MyColors.Black, elevation = 0.dp) { -// Box( -// modifier = M -// .fillMaxWidth() -// .height(100.dp), -// ) { -// CombinedDropdownMenu( -// modifier = M -// .padding(10.dp) -// .width(160.dp), -// hint = if (scaleOptions.isEmpty()) "未连接任何读卡器" else "请选择读卡器", -// value = curScale, -// options = scaleOptions -// ) { -// myCardReaderShowViewModel.setCurScale(it) -// } -// onErrorMsg(if (scaleOptions.isEmpty()) "未连接任何读卡器" else "") -// Row( -// modifier = M -// .padding(10.dp) -// .fillMaxSize(), -// verticalAlignment = Alignment.Bottom, -// horizontalArrangement = Arrangement.End -// ) { -// Text( -// text = weight.toString(), -// color = MyColors.White, -// fontSize = 50.sp, -// fontWeight = FontWeight.Bold -// ) -// Text( -// text = "kg", -// modifier = M.padding(bottom = 6.dp), -// color = MyColors.White, -// fontSize = MaterialTheme.typography.headlineSmall.fontSize, -// fontWeight = FontWeight.Bold -// ) -// } -// } -// } -//} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShowViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShowViewModel.kt deleted file mode 100644 index 9297889..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShowViewModel.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader - -import androidx.lifecycle.viewModelScope -import com.bbitcn.f8.pad.base.BaseViewModel -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M - -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG20R -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach - -class MyCardReaderShowViewModel2 : BaseViewModel() { - - - private val _curScale = MutableStateFlow("") - val curScale = _curScale.asStateFlow() - - private val _scaleOptions = MutableStateFlow>(emptyList()) - val scaleOptions = _scaleOptions.asStateFlow() - - private val allDevices: MutableList = mutableListOf() - - // 保存每个设备的流 - private val scaleFlows: MutableMap>> = mutableMapOf() - - private val _curTagList = MutableStateFlow>(emptyList()) - val tagList = _curTagList.asStateFlow() - - init { - doInIoThreadNoDialog { - // 大-读卡器 - allDevices.add(UHFReaderG20R) - // 小-读卡器 - allDevices.add(UHFReaderG06M_G25M) - allDevices.forEach { - // 存储每个设备的 `readData` 流 - scaleFlows[it.getModelName()] = it.tagList - // 监听设备状态变化 - it.listenStateChanges(viewModelScope) { isEnabled -> - // 如果设备开启,则添加到可选设备列表中 - if (isEnabled) { - _scaleOptions.value += it.getModelName() - if (_curScale.value.isEmpty()) { - // 如果当前没有选中设备,则默认选中第一个设备 - setCurScale(it.getModelName()) - } - } else { - // 如果设备关闭,则移除该设备 - _scaleOptions.value = _scaleOptions.value.filter { deviceName -> - deviceName != it.getModelName() - } - } - } - } - } - } - - // 切换当前设备 - fun setCurScale(scaleName: String) { - // 如果设备发生了变化,则更新当前选中的设备 - if (_curScale.value != scaleName) { - _curScale.value = scaleName - - // 使用 StateFlow 和 collect 进行切换 - scaleFlows[scaleName]?.onEach { - _curTagList.value = it - }?.launchIn(viewModelScope) - } - } - - fun clearList() { - allDevices.forEach { - it.clearList() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShowViewModel2.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShowViewModel2.kt deleted file mode 100644 index b524dde..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/reader/MyCardReaderShowViewModel2.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.bbitcn.f8.pad.ui.screen.view.deviceManager.reader - -import com.bbitcn.f8.pad.base.BaseViewModel -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M - -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG20R -import com.bbitcn.f8.pad.utils.externalModules.manager.DeviceController -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import java.util.UUID - -class MyCardReaderShowViewModel : BaseViewModel() { - - private val _options = MutableStateFlow>(emptyList()) - val options = _options.asStateFlow() - - private val _curDevice = MutableStateFlow(null) - val curDevice = _curDevice.asStateFlow() - - init { - doInIoThreadNoDialog { - UHFReaderG06M_G25M.state.collect { - onStateChanged(it, UHFReaderG06M_G25M) - } - } - doInIoThreadNoDialog { - UHFReaderG20R.state.collect { - onStateChanged(it, UHFReaderG20R) - } - } - } - - // 切换当前设备 - fun onStateChanged(state: Int, device: UHFReaderForSerial) { - // 如果设备开启,则添加到可选设备列表中 - if (state == DeviceController.STATE_CONNECTED) { - _options.value += device.getModelName() - if (_curDevice.value == null) { - // 如果当前没有选中设备,则默认选中第一个设备 - _curDevice.value = device - } - } else if (state == DeviceController.STATE_DISCONNECTED) { - // 如果设备关闭,则移除该设备 - _options.value = _options.value.filter { deviceName -> - deviceName != device.getModelName() - } - if (_curDevice.value == device) { - _curDevice.value = null - } - } - } - - fun clearList() { - _curDevice.value?.clearList() - // 增加逻辑 关了重开 - if (_curDevice.value is UHFReaderG06M_G25M) { - UHFReaderG06M_G25M.reStartScan() - } else if (_curDevice.value is UHFReaderG20R) { - UHFReaderG20R.reStartScan() - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/DrawerViewModel.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/DrawerViewModel.kt index ba7efa7..19cb8f0 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/DrawerViewModel.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/DrawerViewModel.kt @@ -98,25 +98,11 @@ class DrawerViewModel : BaseViewModel() { _isDrawerOpen.value = true } - fun openDryCocoonInDetailDrawer( - navController: NavController, - info: DryCocoonInListResponse.Data, - onClickDelete: () -> Unit - ) { + fun openDryCocoonInDetailDrawer(navController: NavController, info: DryCocoonInListResponse.Data) { doInIoThreadThenUI("正在加载入库单详情", onIO = { _drawerContent.value = { ModalDrawerSheet { - TicketForInDryCocoon(info = info, onClickEdit = { - closeDrawer() - navController.navigate( - "dryCoonOperateIn/${info.sysid}" - ) - }, onClickDelete = { - Toasty.showConfirmDialog("确定要删除此单吗?") { - onClickDelete() - closeDrawer() - } - }) + TicketForInDryCocoon(info = info) } } }) { @@ -124,23 +110,11 @@ class DrawerViewModel : BaseViewModel() { } } - fun openDryCocoonOutDetailDrawer( - navController: NavController, - info: DryCocoonOutListResponse.Data, - onClickDelete: () -> Unit - ) { + fun openDryCocoonOutDetailDrawer(navController: NavController, info: DryCocoonOutListResponse.Data) { doInIoThreadThenUI("正在记载出库单详情", onIO = { _drawerContent.value = { ModalDrawerSheet { - TicketForOutDryCocoon(info = info, onClickEdit = { - closeDrawer() - navController.navigate("dryCoonOperateOut/${info.sysid}") - }, onClickDelete = { - Toasty.showConfirmDialog("确定要删除此单吗?") { - onClickDelete() - closeDrawer() - } - }) + TicketForOutDryCocoon(info = info) } } }) { @@ -148,23 +122,11 @@ class DrawerViewModel : BaseViewModel() { } } - fun openDryCocoonAirDetailDrawer( - navController: NavController, - info: DryCocoonAirListResponse.Data, - onClickDelete: () -> Unit - ) { + fun openDryCocoonAirDetailDrawer(navController: NavController, info: DryCocoonAirListResponse.Data) { doInIoThreadThenUI("正在加载摊晾计划详情", onIO = { _drawerContent.value = { ModalDrawerSheet { - TicketForAirDryCocoon(info = info, onClickEdit = { - closeDrawer() - navController.navigate("dryCoonOperateAir/${info.sysid}") - }, onClickDelete = { - Toasty.showConfirmDialog("确定要删除此计划吗?") { - onClickDelete() - closeDrawer() - } - }) + TicketForAirDryCocoon(info = info) } } }) { diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/SetScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/SetScreen.kt index a063b3b..f5348a3 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/SetScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/SetScreen.kt @@ -16,14 +16,11 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.res.painterResource @@ -37,22 +34,14 @@ import com.bbitcn.f8.pad.base.MyButton import com.bbitcn.f8.pad.base.MyCard import com.bbitcn.f8.pad.base.MyTabRowHorizontal import com.bbitcn.f8.pad.ui.screen.view.common.CombinedDropdownMenu - import com.bbitcn.f8.pad.ui.theme.MyColors -import com.bbitcn.f8.pad.utils.externalModules.devices.light.Light_ -import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleBT -import com.bbitcn.f8.pad.utils.externalModules.manager.bluetooth.MyBlueTooth -import com.bbitcn.f8.pad.utils.externalModules.devices.printer.PrinterBT -import com.bbitcn.f8.pad.utils.externalModules.devices.water.WaterCutMeterBT -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.idcard.IDCardUtils -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.nfc.NFCUtils -import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleSerial -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M - -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG20R import com.bbitcn.f8.pad.utils.externalModules.devices.printer.JTPrinterUSB +import com.bbitcn.f8.pad.utils.externalModules.devices.printer.PrinterBT +import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleBT +import com.bbitcn.f8.pad.utils.externalModules.devices.scale.ScaleSerial +import com.bbitcn.f8.pad.utils.externalModules.devices.water.WaterCutMeterBT import com.bbitcn.f8.pad.utils.externalModules.manager.DeviceController -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial +import com.bbitcn.f8.pad.utils.externalModules.manager.bluetooth.MyBlueTooth import com.bbitcn.f8.pad.utils.externalModules.manager.usb.UsbDeviceConnector import com.blankj.utilcode.util.StringUtils import kotlinx.coroutines.Dispatchers @@ -67,13 +56,11 @@ fun SetPreview() { @Composable fun SetScreen() { - MyTabRowHorizontal(listOf("秤", "读卡器", "打印机", "含水仪", "灯")) { index -> + MyTabRowHorizontal(listOf("秤", "打印机", "含水仪")) { index -> when (index) { 0 -> BalanceSetScreen() - 1 -> CardReaderSetScreen() - 2 -> PrinterSetScreen() - 3 -> WaterCutMeterSetScreen() - 4 -> LightSetScreen() + 1 -> PrinterSetScreen() + 2 -> WaterCutMeterSetScreen() } } } @@ -83,14 +70,14 @@ fun PrinterSetScreen() { MyTabRowHorizontal(listOf("蓝牙-汉印", "USB-主干巨天")) { when (it) { 0 -> ConnectBluetooth(PrinterBT) - 1 -> ConnectUSB(JTPrinterUSB, "0x4B43", "0x3830")// 58打印机:"0x3538" 80打印机:"0x3830" + 1 -> ConnectUSB(JTPrinterUSB, "0x4B43", "0x3830") } } } @Composable fun BalanceSetScreen() { - MyTabRowHorizontal(listOf("串口-主干巨天", "蓝牙-今选")) { + MyTabRowHorizontal(listOf("串口-主干巨天", "蓝牙-今迈")) { when (it) { 0 -> ScaleSerialPort(ScaleSerial, "/dev/ttyS4", "9600") 1 -> ConnectBluetooth(ScaleBT) @@ -98,18 +85,6 @@ fun BalanceSetScreen() { } } -@Composable -fun CardReaderSetScreen() { - MyTabRowHorizontal(listOf("超高频(新)", "超高频(旧)", "NFC", "身份证")) { index -> - when (index) { - 0 -> ReaderSerialPort(UHFReaderG06M_G25M, "/dev/ttyS8", "57600") - 1 -> ReaderSerialPort(UHFReaderG20R, "/dev/ttyS8", "57600") - 2 -> NFCSetScreen() - 3 -> IDCardReaderSetScreen() - } - } -} - @Composable fun WaterCutMeterSetScreen() { MyTabRowHorizontal(listOf("蓝牙-光华")) { @@ -117,38 +92,6 @@ fun WaterCutMeterSetScreen() { } } -@Composable -fun LightSetScreen() { - MyTabRowHorizontal(listOf("USB-灯具")) { - LightUSB(Light_, "/dev/bus/usb/002/003", "9600") - } -} - -// —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— -@Composable -fun IDCardReaderSetScreen() { - SetFrame { - Row( - modifier = M - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - DeviceInfo("型号", "5501H") - DeviceInfo("状态", if (IDCardUtils.isEnable()) "已开启" else "未开启") - } - } -} - -@Composable -fun NFCSetScreen() { - SetFrame { - DeviceInfo("状态", if (NFCUtils.isEnable()) "已开启" else "未开启") - } -} - -/** - * USB设备 - */ @Composable fun ConnectUSB( device: UsbDeviceConnector, @@ -181,33 +124,19 @@ fun ConnectUSB( horizontalArrangement = Arrangement.spacedBy(10.dp) ) { val state by device.state.collectAsState() - MyButton( - text = "连接", - enabled = state != 1 - ) { -// val vIdT = vId.removePrefix("0x").toInt(16) -// val pIdT = pId.removePrefix("0x").toInt(16) + MyButton(text = "连接", enabled = state != DeviceController.STATE_CONNECTED) { device.connect(vId, pId) } - MyButton( - text = "测试", - enabled = state == 1 - ) { + MyButton(text = "测试", enabled = state == DeviceController.STATE_CONNECTED) { device.test() } - MyButton( - text = "断开", - enabled = state == 1 - ) { + MyButton(text = "断开", enabled = state == DeviceController.STATE_CONNECTED) { device.disconnect() } } } } -/** - * 称-串口 - */ @Composable fun ScaleSerialPort( device: ScaleSerial, @@ -217,23 +146,11 @@ fun ScaleSerialPort( var mPort by rememberSaveable { mutableStateOf(defaultPort) } var mBaudRate by rememberSaveable { mutableStateOf(defaultBaud) } val state by device.state.collectAsState() - val serialPortList by UHFReaderG06M_G25M.serialPortList.collectAsState() - - LaunchedEffect(serialPortList) { - if (serialPortList.isEmpty()) { - mPort = "" - } else if (serialPortList.contains(defaultPort)) { - mPort = defaultPort - } - } + val serialPortList = listOf(defaultPort) SetFrame { AutoConnectOnStartUp(device) - Row( - modifier = M - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { + Row(modifier = M.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { val realData by device.readData.collectAsState() if (!StringUtils.isEmpty(realData)) { DeviceInfo("实时数据", realData) @@ -246,18 +163,13 @@ fun ScaleSerialPort( } ) } - Row( - modifier = M.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { + Row(modifier = M.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { CombinedDropdownMenu( modifier = M.weight(1f), options = serialPortList, - hint = "未检测到串口", + hint = "选择串口", value = mPort - ) { - mPort = it - } + ) { mPort = it } CombinedDropdownMenu( modifier = M.weight(1f), options = listOf("1200", "4800", "9600", "115200"), @@ -272,239 +184,19 @@ fun ScaleSerialPort( .padding(top = 10.dp), horizontalArrangement = Arrangement.spacedBy(10.dp) ) { - val state by device.state.collectAsState() - MyButton( - text = "连接", - enabled = state != 1 && serialPortList.isNotEmpty() - ) { + MyButton(text = "连接", enabled = state != DeviceController.STATE_CONNECTED && mPort.isNotBlank()) { device.connect(mPort, mBaudRate.toInt()) } - MyButton( - text = "测试", - enabled = state == 1 - ) { + MyButton(text = "测试", enabled = state == DeviceController.STATE_CONNECTED) { device.test() } - MyButton( - text = "断开", - enabled = state == 1 - ) { + MyButton(text = "断开", enabled = state == DeviceController.STATE_CONNECTED) { device.disconnect() } } } } -/** - * 读卡器-串口 - */ -@Composable -fun ReaderSerialPort( - device: UHFReaderForSerial, - defaultPort: String, - defaultBaud: String, -) { - var mPort by rememberSaveable { mutableStateOf(defaultPort) } - var mBaudRate by rememberSaveable { mutableStateOf(defaultBaud) } - val serialPortList by UHFReaderG06M_G25M.serialPortList.collectAsState() - - LaunchedEffect(serialPortList) { - if (serialPortList.isEmpty()) { - mPort = "" - } else if (serialPortList.contains(defaultPort)) { - mPort = defaultPort - } - } - - SetFrame { - AutoConnectOnStartUp(device) - Row(modifier = M.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { - DeviceInfo("品牌", "骐宝") - DeviceInfo("型号", device.getModelName()) - DeviceInfo("连接方式", "串口") - } - Row(modifier = M.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { - CombinedDropdownMenu( - modifier = M.weight(1f), - options = serialPortList, - hint = "未检测到串口", - value = mPort - ) { mPort = it } - CombinedDropdownMenu( - modifier = M.weight(1f), - options = listOf("1200", "4800", "9600", "115200"), - hint = "选择波特率", - value = mBaudRate - ) { mBaudRate = it } - } - HorizontalDivider() - Row( - modifier = M - .fillMaxWidth() - .padding(vertical = 10.dp), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - val state by device.state.collectAsState() - MyButton( - text = "连接", - enabled = state != 1 && serialPortList.isNotEmpty() - ) { - device.connect(mPort, mBaudRate.toInt()) - } - MyButton( - text = "断开", - enabled = state == 1 - ) { - device.disconnect() - } - } - Row( - modifier = M - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - val readAuto by device.readAuto.collectAsState() - MyButton(text = if (readAuto) "关闭" else "开启") { - if (readAuto) { - device.stopScan() - } else { - device.startScan() - } - } - MyButton(text = "清空") { - device.clearList() - } - } - HorizontalDivider() - val labelList by device.tagList.collectAsState() - // 显示读取到的数据 - LazyColumn( - modifier = M - .padding(vertical = 10.dp) - .fillMaxSize() - ) { - item { - Text("标签列表", fontSize = 18.sp, fontWeight = FontWeight.Bold) - } - items(labelList) { tag -> - Text( - modifier = M - .fillMaxWidth() - .padding(10.dp), - text = tag, - color = MyColors.BlueGreen - ) - HorizontalDivider() - } - } - } -} - -/** - * 读卡器-串口 - */ -@Composable -fun LightUSB( - device: Light_, - defaultDeviceName: String, - defaultBaud: String, -) { - var mDeviceName by rememberSaveable { mutableStateOf(defaultDeviceName) } - var mBaudRate by rememberSaveable { mutableStateOf(defaultBaud) } - val devices by device.serialPortList.collectAsState() - val deviceNames by remember { derivedStateOf { devices.map { it.device.deviceName } } } - val state by device.state.collectAsState() - - LaunchedEffect(deviceNames) { - if (deviceNames.isEmpty()) { - mDeviceName = "" - } else if (deviceNames.contains(defaultDeviceName)) { - mDeviceName = defaultDeviceName - } - } - - SetFrame { - AutoConnectOnStartUp(device) - Row(modifier = M.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { - DeviceInfo("型号", "BBIT_Light_v1") - DeviceInfo("连接方式", "USB转串口") - } - Row(modifier = M.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { - CombinedDropdownMenu( - modifier = M.weight(1f), - options = deviceNames, - hint = "选择设备", - value = mDeviceName - ) { mDeviceName = it } - CombinedDropdownMenu( - modifier = M.weight(1f), - options = listOf("1200", "4800", "9600", "115200"), - hint = "选择波特率", - value = mBaudRate - ) { mBaudRate = it } - } - HorizontalDivider() - Row( - modifier = M - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - MyButton( - text = "连接", - enabled = state != 1 && deviceNames.isNotEmpty() - ) { - device.connect(mDeviceName, mBaudRate.toInt()) - } - MyButton( - text = "测试", - enabled = state == 1 - ) { - device.test() - } - MyButton( - text = "断开", - enabled = state == 1 - ) { - device.disconnect() - } - } - if (state == 1) { - val scope = rememberCoroutineScope() - Row( - modifier = M - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { - MyButton(text = "红灯") { - scope.launch { - device.openRedLight() - } - } - MyButton(text = "绿灯") { - scope.launch { - device.openGreenLight() - } - } - MyButton(text = "黄灯") { - scope.launch { - device.openYellowLight() - } - } - } - MyButton( - text = "关闭所有灯光", - modifier = M - .fillMaxWidth() - ) { - device.closeLight() - } - } - } -} - -/** - * 蓝牙设备 - */ @SuppressLint("MissingPermission") @Composable fun ConnectBluetooth(bluetooth: MyBlueTooth) { @@ -513,11 +205,7 @@ fun ConnectBluetooth(bluetooth: MyBlueTooth) { val state by bluetooth.state.collectAsState() SetFrame { AutoConnectOnStartUp(bluetooth) - Row( - modifier = M - .fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(10.dp) - ) { + Row(modifier = M.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(10.dp)) { DeviceInfo( "状态", when (state) { DeviceController.STATE_DISCONNECTED -> "未连接" @@ -540,12 +228,14 @@ fun ConnectBluetooth(bluetooth: MyBlueTooth) { ) { MyButton( text = if (bluetooth.sccaning.value) "扫描中" else "开始扫描", - onClick = { bluetooth.startScan() }) + onClick = { bluetooth.startScan() } + ) MyButton( text = "断开连接", modifier = M.padding(start = 16.dp), - enabled = state == 2, - onClick = { bluetooth.disconnect() }) + enabled = state == DeviceController.STATE_CONNECTED, + onClick = { bluetooth.disconnect() } + ) } HorizontalDivider() Text( @@ -554,14 +244,9 @@ fun ConnectBluetooth(bluetooth: MyBlueTooth) { fontSize = 18.sp, fontWeight = FontWeight.Bold ) - LazyColumn( - modifier = M - .fillMaxSize() - ) { + LazyColumn(modifier = M.fillMaxSize()) { items(bluetooth.devicesFound) { device -> val isIt = bluetooth.device.value?.address == device.address - println("device.address: $device.address") - println("bluetooth.device.value?.address: ${bluetooth.device.value?.address}") Row( modifier = M .fillMaxWidth() @@ -579,8 +264,8 @@ fun ConnectBluetooth(bluetooth: MyBlueTooth) { modifier = M.align(Alignment.CenterVertically), painter = painterResource( id = when (state) { - -1 -> R.drawable.error - 1 -> R.drawable.success + DeviceController.STATE_DISCONNECTED -> R.drawable.error + DeviceController.STATE_CONNECTED -> R.drawable.success else -> R.drawable.connecting } ), @@ -595,9 +280,7 @@ fun ConnectBluetooth(bluetooth: MyBlueTooth) { } @Composable -fun SetFrame( - content: @Composable () -> Unit, -) { +fun SetFrame(content: @Composable () -> Unit) { Column( modifier = M .fillMaxSize() diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryAirCocoon.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryAirCocoon.kt index d0ec103..7deac56 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryAirCocoon.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryAirCocoon.kt @@ -26,12 +26,10 @@ import androidx.compose.ui.unit.dp import androidx.paging.compose.collectAsLazyPagingItems import com.bbitcn.f8.pad.M import com.bbitcn.f8.pad.base.InfoText -import com.bbitcn.f8.pad.base.MyButton import com.bbitcn.f8.pad.base.MyRefreshTable import com.bbitcn.f8.pad.base.MyTableData import com.bbitcn.f8.pad.model.net.response.DryCocoonAirListResponse -import com.bbitcn.f8.pad.ui.screen.secondFunc.VerticalInfo import com.bbitcn.f8.pad.ui.theme.MyColors @Preview(showBackground = true) @@ -45,8 +43,6 @@ fun TicketForAirDryCocoon( modifier: Modifier = M, info: DryCocoonAirListResponse.Data = DryCocoonAirListResponse.Data(), ticketForDryCocoonViewModel: TicketForDryCocoonViewModel = TicketForDryCocoonViewModel(info.sysid), - onClickEdit: () -> Unit = {}, - onClickDelete: () -> Unit = {}, ) { Column(modifier = modifier.padding(10.dp)) { Text( @@ -86,24 +82,6 @@ fun TicketForAirDryCocoon( } InfoText("开始时间", info.startime) InfoText("结束时间", info.endtime) - - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(15.dp) - ) { - MyButton( - modifier = M.weight(1f), - text = "修改计划" - ) { - onClickEdit() - } - MyButton( - modifier = M.weight(1f), - text = "删除计划" - ) { - onClickDelete() - } - } HorizontalDivider( color = MyColors.BlueGreen, modifier = M.padding(vertical = 5.dp) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryInCocoon.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryInCocoon.kt index e54b54f..db93368 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryInCocoon.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryInCocoon.kt @@ -31,7 +31,6 @@ import androidx.paging.compose.collectAsLazyPagingItems import com.bbitcn.f8.pad.M import com.bbitcn.f8.pad.R import com.bbitcn.f8.pad.base.InfoText -import com.bbitcn.f8.pad.base.MyButton import com.bbitcn.f8.pad.base.MyRefreshTable import com.bbitcn.f8.pad.base.MyTableData @@ -53,8 +52,6 @@ fun TicketForInDryCocoon( modifier: Modifier = M, info: DryCocoonInListResponse.Data = DryCocoonInListResponse.Data(), ticketForDryCocoonViewModel: TicketForDryCocoonViewModel = TicketForDryCocoonViewModel(info.sysid), - onClickEdit: () -> Unit = {}, - onClickDelete: () -> Unit = {}, ) { // val ticketForDryCocoonViewModel = viewModel( // factory = DryCocoonDetailViewModelFactory(info.sysid) @@ -135,23 +132,6 @@ fun TicketForInDryCocoon( InfoText("烘茧人", info.hongjianren) } } - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(15.dp) - ) { - MyButton( - modifier = M.weight(1f), - text = "修改单据" - ) { - onClickEdit() - } - MyButton( - modifier = M.weight(1f), - text = "删除单据" - ) { - onClickDelete() - } - } HorizontalDivider( color = MyColors.BlueGreen, modifier = M.padding(vertical = 5.dp) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryOutCocoon.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryOutCocoon.kt index c5cfbd6..e3ad45e 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryOutCocoon.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForDryOutCocoon.kt @@ -31,7 +31,6 @@ import androidx.paging.compose.collectAsLazyPagingItems import com.bbitcn.f8.pad.M import com.bbitcn.f8.pad.R import com.bbitcn.f8.pad.base.InfoText -import com.bbitcn.f8.pad.base.MyButton import com.bbitcn.f8.pad.base.MyRefreshTable import com.bbitcn.f8.pad.base.MyTableData @@ -53,8 +52,6 @@ fun TicketForOutDryCocoon( modifier: Modifier = M, info: DryCocoonOutListResponse.Data = DryCocoonOutListResponse.Data(), ticketForDryCocoonViewModel: TicketForDryCocoonViewModel = TicketForDryCocoonViewModel(info.sysid), - onClickEdit: () -> Unit = {}, - onClickDelete: () -> Unit = {}, ) { Column(modifier = modifier.padding(10.dp)) { Text( @@ -132,24 +129,6 @@ fun TicketForOutDryCocoon( } } InfoText("日期", info.ckdatetime) - - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(15.dp) - ) { - MyButton( - modifier = M.weight(1f), - text = "修改单据" - ) { - onClickEdit() - } - MyButton( - modifier = M.weight(1f), - text = "删除单据" - ) { - onClickDelete() - } - } HorizontalDivider( color = MyColors.BlueGreen, modifier = M.padding(vertical = 5.dp) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonAirViewModelFactory.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonAirViewModelFactory.kt deleted file mode 100644 index b70c93d..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonAirViewModelFactory.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.bbitcn.f8.pad.ui.viewmodel.factory - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import com.bbitcn.f8.pad.ui.screen.secondFunc.AddDryCocoonAirViewModel -import com.bbitcn.f8.pad.ui.screen.secondFunc.AddDryCocoonInViewModel -import com.bbitcn.f8.pad.ui.screen.secondFunc.AddDryCocoonOutViewModel - -class AddDryCocoonAirViewModelFactory(private val inSystemId: String) : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(AddDryCocoonAirViewModel::class.java)) { - return AddDryCocoonAirViewModel(inSystemId) as T - } - return throw IllegalArgumentException("Unknown ViewModel class") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonInViewModelFactory.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonInViewModelFactory.kt deleted file mode 100644 index f578c8b..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonInViewModelFactory.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.bbitcn.f8.pad.ui.viewmodel.factory - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import com.bbitcn.f8.pad.ui.screen.secondFunc.AddDryCocoonInViewModel - -class AddDryCocoonInViewModelFactory(private val inSystemId: String) : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(AddDryCocoonInViewModel::class.java)) { - return AddDryCocoonInViewModel(inSystemId) as T - } - return throw IllegalArgumentException("Unknown ViewModel class") - } - /** - * - * val ticketForDryCocoonViewModel = viewModel( - * factory = DryCocoonDetailViewModelFactory(info.sysid) - * ) - * - */ -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonOutViewModelFactory.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonOutViewModelFactory.kt deleted file mode 100644 index bb35165..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/viewmodel/factory/AddDryCocoonOutViewModelFactory.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.bbitcn.f8.pad.ui.viewmodel.factory - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import com.bbitcn.f8.pad.ui.screen.secondFunc.AddDryCocoonInViewModel -import com.bbitcn.f8.pad.ui.screen.secondFunc.AddDryCocoonOutViewModel - -class AddDryCocoonOutViewModelFactory(private val inSystemId: String) : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(AddDryCocoonOutViewModel::class.java)) { - return AddDryCocoonOutViewModel(inSystemId) as T - } - return throw IllegalArgumentException("Unknown ViewModel class") - } - /** - * - * val ticketForDryCocoonViewModel = viewModel( - * factory = DryCocoonDetailViewModelFactory(info.sysid) - * ) - * - */ -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/light/Light_.kt b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/light/Light_.kt deleted file mode 100644 index 08ecc06..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/light/Light_.kt +++ /dev/null @@ -1,62 +0,0 @@ -@file:Suppress("INACCESSIBLE_TYPE") - -package com.bbitcn.f8.pad.utils.externalModules.devices.light - -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.SerialDeviceConnector2 -import com.bbitcn.f8.pad.utils.log.MyLog -import kotlinx.coroutines.currentCoroutineContext -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock - - -object Light_ : SerialDeviceConnector2() { - - override fun getDeviceName(): String = "指示灯" - - /** - * 协程挂起锁 保证指令顺序执行不会并发 - */ - private val lightMutex = Mutex() - - override fun test() { - doInIoThread("测试中,请观察指示灯") { - sendMsg("open1") - delay(1000) - sendMsg("close1") - } - } - - fun closeLight() { - doInIoThreadNoDialog { - control() - } - } - - suspend fun openYellowLight() { - control { sendMsg("open2") } - } - - suspend fun openGreenLight() { - control { sendMsg("open1") } - } - - suspend fun openRedLight() { - control { sendMsg("open3") } - } - - suspend fun control(instruction: suspend () -> Unit = {}) { - if (_state.value != STATE_CONNECTED) { - return - } - lightMutex.withLock { - if (!currentCoroutineContext().isActive) return - sendMsg("close0") - delay(50) - instruction() - } - } - - -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/printer/JTPrinterUSB.kt b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/printer/JTPrinterUSB.kt index 9962b7a..ad39f99 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/printer/JTPrinterUSB.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/printer/JTPrinterUSB.kt @@ -50,7 +50,7 @@ object JTPrinterUSB : UsbDeviceConnector(), PrinterInterface { doInIoThreadNoDialog { val h = openPort() if (h !== Pointer.NULL) { - var bitmap: Bitmap = getImageFromAssetsFile("RasterImage/yellowmen.png")!! + var bitmap: Bitmap = getImageFromAssetsFile("RasterImage/barcode.png")!! bitmap = resizeImageToWidth(bitmap, 395) AutoReplyPrint.CP_Pos_PrintRasterImageFromData_Helper.PrintRasterImageFromBitmap( h, diff --git a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/idcard/IDCardUtils.kt b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/idcard/IDCardUtils.kt deleted file mode 100644 index 08e130f..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/idcard/IDCardUtils.kt +++ /dev/null @@ -1,178 +0,0 @@ -package com.bbitcn.f8.pad.utils.externalModules.devices.reader.idcard - -import android.zyapi.CommonApi -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import com.bbitcn.f8.pad.MyApp -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.utils.externalModules.manager.DeviceController -import com.bbitcn.f8.pad.utils.log.MyLog -import com.zkteco.android.biometric.core.device.ParameterHelper -import com.zkteco.android.biometric.core.device.TransportType -import com.zkteco.android.biometric.module.idcard.IDCardReader -import com.zkteco.android.biometric.module.idcard.IDCardReaderFactory -import com.zkteco.android.biometric.module.idcard.IDCardType -import com.zkteco.android.biometric.module.idcard.exception.IDCardReaderException -import com.zkteco.android.biometric.module.idcard.meta.IDCardInfo -import com.zkteco.android.biometric.module.idcard.meta.IDPRPCardInfo -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit - -object IDCardUtils : DeviceController(){ - - override fun getDeviceName(): String = "身份证识别模块" - - // 身份证、港澳通行证 - val cardInfos: MutableState = mutableStateOf(null) - - //state - // 0: 初始化中,-1: 初始化失败,else: 初始化成功// 0: 初始化中,-1: 初始化失败,else: 初始化成功 - - // 护照 - val prpCardInfos: MutableState = mutableStateOf(null) - - private const val serialName = "/dev/ttyS0" - var mCommonApi: CommonApi? = null - private var idCardReader: IDCardReader? = null - private var countDownLatch: CountDownLatch? = null - - private var bStarted = false - private var bCancel = false - private const val bRepeatRead = true - - init { - doInIoThreadNoDialog { - try { - mCommonApi = CommonApi() - } catch (e: UnsatisfiedLinkError) { - e.printStackTrace() - MyLog.cardReader("CommonApi初始化失败") - } - } - } - - override fun isEnable(): Boolean { - return idCardReader != null - } - - /** - * 打开GPIO口,给身份证模块供电 - */ - suspend fun openGPIO() { - if(mCommonApi == null){ - Toasty.error("身份证模块初始化失败") - } - mCommonApi?.setGpioMode(25, 0); - mCommonApi?.setGpioDir(25, 1); - mCommonApi?.setGpioOut(25, 1); - } - - /** - * 对身份证模块断电 - */ - suspend fun closeGPIO() { - mCommonApi?.setGpioMode(25, 0); - mCommonApi?.setGpioDir(25, 1); - mCommonApi?.setGpioOut(25, 0); - } - - suspend fun openDevice(onCardReadListener: (info: IDCardInfo) -> Unit ){ - try { - setState(0) - startIDCardReader() - idCardReader!!.open(0) - countDownLatch = CountDownLatch(1) - val coroutineScope = CoroutineScope(Dispatchers.IO) - coroutineScope.launch { - bCancel = false - while (!bCancel) { - delay(500) - try { - idCardReader!!.findCard(0) - idCardReader!!.selectCard(0) - } catch (e: IDCardReaderException) { - if (!bRepeatRead) { - continue - } - } - delay(50) - var cardType = 0 - try { - cardType = idCardReader!!.readCardEx(0, 0) - } catch (e: IDCardReaderException) { - setState(-1) - continue - } - if (cardType == IDCardType.TYPE_CARD_SFZ || cardType == IDCardType.TYPE_CARD_PRP || cardType == IDCardType.TYPE_CARD_GAT) { - if (cardType == IDCardType.TYPE_CARD_SFZ || cardType == IDCardType.TYPE_CARD_GAT) { - // 读取照片 -// var bmpPhoto: Bitmap? = null -// if (idCardInfo.getPhotolength() > 0) { -// val buf = ByteArray(WLTService.imgLength) -// if (1 == WLTService.wlt2Bmp(idCardInfo.getPhoto(), buf)) { -// bmpPhoto = IDPhotoHelper.Bgr2Bitmap(buf) -// } -// } -// setImageBitmap - cardInfos.value = idCardReader?.lastIDCardInfo - idCardReader?.lastIDCardInfo?.let { onCardReadListener(it) } - } else { - prpCardInfos.value = idCardReader?.lastPRPIDCardInfo - } - } - } - countDownLatch?.countDown() - } - bStarted = true - MyLog.cardReader("打开设备成功,SAMID:" + idCardReader!!.getSAMID(0)) - setState(1) - } catch (e: IDCardReaderException) { - e.printStackTrace() - MyLog.cardReader("打开设备失败,错误信息:" + e.message) - setState(-1) - } - } - - - private suspend fun startIDCardReader() { - if (null != idCardReader) { - IDCardReaderFactory.destroy(idCardReader) - idCardReader = null - } - // Start fingerprint sensor - val idrparams = mutableMapOf() - idrparams[ParameterHelper.PARAM_SERIAL_SERIALNAME] = serialName - idrparams[ParameterHelper.PARAM_SERIAL_BAUDRATE] = 115200 - idCardReader = - IDCardReaderFactory.createIDCardReader( - MyApp.appContext, - TransportType.SERIALPORT, - idrparams - ) - } - - override suspend fun overrideDisconnect() { - if (bStarted) { - bCancel = true - if (null != countDownLatch) { - try { - countDownLatch!!.await((2 * 1000).toLong(), TimeUnit.MILLISECONDS) - } catch (e: InterruptedException) { - e.printStackTrace() - } - countDownLatch = null - } - try { - idCardReader!!.close(0) - } catch (e: IDCardReaderException) { - e.printStackTrace() - } - bStarted = false - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/nfc/NFCUtils.kt b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/nfc/NFCUtils.kt deleted file mode 100644 index fd9a2f1..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/nfc/NFCUtils.kt +++ /dev/null @@ -1,222 +0,0 @@ -package com.bbitcn.f8.pad.utils.externalModules.devices.reader.nfc - -import android.annotation.SuppressLint -import android.app.Activity -import android.nfc.NfcAdapter -import android.nfc.Tag -import android.nfc.tech.IsoDep -import android.os.Bundle -import android.util.Log -import com.bbitcn.f8.pad.MyApp -import com.bbitcn.f8.pad.utils.externalModules.manager.DeviceController -import com.bbitcn.f8.pad.utils.log.MyLog -import com.github.devnied.emvnfccard.exception.CommunicationException -import com.github.devnied.emvnfccard.model.EmvCard -import com.github.devnied.emvnfccard.parser.EmvTemplate -import com.github.devnied.emvnfccard.parser.IProvider -import java.io.IOException -import java.time.LocalDate -import java.time.ZoneId - -@SuppressLint("StaticFieldLeak") -object NFCUtils : DeviceController(), NfcAdapter.ReaderCallback { - - override fun getDeviceName(): String = "通用NFC" - - private var nfcAdapter: NfcAdapter? = null - private var onCardReadListener: ((String) -> Unit)? = null - private lateinit var activity: Activity - - override suspend fun overrideDisconnect() { - - } - - private var isPayCard = false - - fun initActivity(activity: Activity) { - NFCUtils.activity = activity - } - - // 初始化 NFCUtils 必须先调用initActivity - suspend fun init( - isPayCard: Boolean, - onCardReadListener: (String) -> Unit - ) { - doInIoThreadNoDialog { - nfcAdapter = NfcAdapter.getDefaultAdapter(MyApp.appContext) - NFCUtils.isPayCard = isPayCard - NFCUtils.onCardReadListener = onCardReadListener - enableReaderMode() - setState(if (isEnable()) 1 else -1) - } - } - - override fun isEnable(): Boolean { - return nfcAdapter != null && nfcAdapter?.isEnabled == true - } - - // 启用NFC Reader Mode - suspend fun enableReaderMode() { - nfcAdapter?.let { - val options = Bundle().apply { - putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250) - } - it.enableReaderMode( - activity, this, - NfcAdapter.FLAG_READER_NFC_A or - NfcAdapter.FLAG_READER_NFC_B or - NfcAdapter.FLAG_READER_NFC_F or - NfcAdapter.FLAG_READER_NFC_V or - NfcAdapter.FLAG_READER_NFC_BARCODE or - NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS, - options - ) - } - } - - // 禁用NFC Reader Mode - suspend fun disableReaderMode() { - nfcAdapter?.disableReaderMode(activity) - } - - // 处理 NFC 标签发现事件 - override fun onTagDiscovered(tag: Tag?) { - tag?.let { - if (isPayCard) { - // 银行卡读卡 - var isoDep: IsoDep? = null - try { - isoDep = IsoDep.get(it) - isoDep?.connect() - readEmvCard(isoDep) - } catch (e: IOException) { - MyLog.cardReader("Error reading NFC tag") - } finally { - try { - isoDep?.close() - } catch (e: IOException) { - e.printStackTrace() - } - } - } else { - // IC 卡读卡 - tag.id?.let { - val IdInHex = getHex(it) - val IdInDec = getDec(it) - val IdReversed = getReversed(it) - onCardReadListener?.invoke(IdReversed) - } - - } - } - } - - // 读取 EMV 卡片信息 - private fun readEmvCard(isoDep: IsoDep?): String? { - val provider = PcscProvider().apply { - setmTagCom(isoDep) - } - val config = EmvTemplate.Config() - .setContactLess(true) - .setReadAllAids(true) - .setReadTransactions(true) - .setRemoveDefaultParsers(false) - .setReadAt(true) - - val parser = EmvTemplate.Builder() - .setProvider(provider) - .setConfig(config) - .build() - - val card = parser.readEmvCard() ?: return null - return formatCardData(card) - } - - // 格式化卡片数据 - private fun formatCardData(card: EmvCard): String { - val cardNumber = prettyPrintCardNumber(card.cardNumber) - val expireDate = card.expireDate?.toInstant() - ?.atZone(ZoneId.systemDefault()) - ?.toLocalDate() - ?: LocalDate.of(1999, 12, 31) - - val typeName = card.type?.name ?: "Unknown" - val typeAids = card.type?.aid ?: emptyArray() - - val aidInfo = typeAids.joinToString(separator = "\n") { "aid: $it" } - - onCardReadListener?.invoke(card.cardNumber) - return """ - |typeName: $typeName - |$aidInfo - |cardNumber: $cardNumber - |expireDate: $expireDate - """.trimMargin() - } - - // 格式化卡号,每4位加一个空格 - private fun prettyPrintCardNumber(cardNumber: String?): String { - return cardNumber?.replace("....".toRegex(), "$0 ")?.trim() ?: "" - } - - // 其他辅助方法:十六进制、十进制和翻转ID计算 - private fun getHex(bytes: ByteArray) = - bytes.reversed().joinToString(" ") { String.format("%02X", it) } - - private fun getDec(bytes: ByteArray): Long { - var result: Long = 0 - var factor: Long = 1 - for (i in bytes.indices) { - val value = bytes[i].toLong() and 0xffL - result += value * factor - factor *= 256L - } - return result - } - - private fun getReversed(bytes: ByteArray): String { - var result: Long = 0 - var factor: Long = 1 - for (i in bytes.indices.reversed()) { - val value = bytes[i].toLong() and 0xffL - result += value * factor - factor *= 256L - } - return result.toString() - } - - private class PcscProvider : IProvider { - private var mTagCom: IsoDep? = null - - fun setmTagCom(mTagCom: IsoDep?) { - this.mTagCom = mTagCom - } - - @Throws(CommunicationException::class) - override fun transceive(pCommand: ByteArray): ByteArray { - var response: ByteArray? = null - try { - // send command to emv card - mTagCom!!.tag - //mTagCom.connect(); - if (mTagCom!!.isConnected) { - response = mTagCom!!.transceive(pCommand) - } - } catch (e: IOException) { - throw CommunicationException(e.message) - } - return response!! - } - - override fun getAt(): ByteArray { - // return new byte[0]; // from Stackoverflow - var result: ByteArray - result = mTagCom!!.historicalBytes // for tags using NFC-B - if (result == null) { - result = mTagCom!!.hiLayerResponse // for tags using NFC-B - } - return result - } - - } -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/uhf/UHFReaderG06M_G25M.kt b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/uhf/UHFReaderG06M_G25M.kt deleted file mode 100644 index 485bdfc..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/uhf/UHFReaderG06M_G25M.kt +++ /dev/null @@ -1,304 +0,0 @@ -@file:Suppress("INACCESSIBLE_TYPE") - -package com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf - -import android.serialport.SerialPort -import com.ad.rcp.RcpBase -import com.ad.rcp.RcpMM -import com.ad.rcp.TagID -import com.ad.sio.OnCommListener -import com.ad.sio.SioBase -import com.ad.sio.StatusEvent -import com.ad.sio.StatusType -import com.ad.sio.com.SioCom -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.utils.ConverterUtil -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial -import com.bbitcn.f8.pad.utils.log.MyLog -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import java.io.ByteArrayOutputStream -import java.util.UUID -import kotlin.experimental.xor - -object UHFReaderG06M_G25M : UHFReaderForSerial() { - - private var mRcpBase: RcpBase? = null - private var mSioBase: SioCom? = null - private var onCommListener: OnCommListener? = null - private val protocolScope = CoroutineScope(SupervisorJob() + Dispatchers.IO.limitedParallelism(1)) - - private var mBattaryLevel = 0 - - private val _serialPortList = MutableStateFlow>(emptyList()) - val serialPortList = _serialPortList.asStateFlow() - - init { - doInIoThreadNoDialog { - init() - } - } - - fun testXP(rfid: String? = null) { - setState(1) - // 8位 - val value = rfid ?: "${UUID.randomUUID()}".substring(0, 8) - _tagList.update { it + value } - } - - private fun init() { - if (mRcpBase == null || mSioBase == null) { - mRcpBase = RcpBase() - mSioBase = SioCom() - _serialPortList.value = - mSioBase!!.portList.mapIndexed { index, it -> mSioBase!!.getPortName(index) } - } - } - - private fun addToList(tagID: TagID) { - val list = _tagList.value.toMutableList() - list.forEach { - if (it == tagID.epc) { - return - } - } - list.add(tagID.epc) - _tagList.value = list - } - - override fun test() { - - } - - override suspend fun overrideDisconnect() { - - } - - override fun getDeviceName(): String = "新超高频读卡器" - - private fun Command(nCode: Byte, nType: Byte, ArgByte: ByteArray) { - mSioBase?.send(RcpBase.buildCmdPacketByte(nCode, nType, ArgByte)) - } - - - private fun Command(nCode: Byte, nType: Byte) { - mSioBase?.send(RcpBase.buildCmdPacketByte(nCode, nType)) - } - - fun getSuPath(): String? { - return try { - val process = Runtime.getRuntime().exec("which su") - process.inputStream.bufferedReader().readText().trim() - } catch (e: Exception) { - e.printStackTrace() - null - } - } - - // 缓冲区 - private val frameBuffer = ByteArrayOutputStream() - - // 使用时 - override fun connect(port: String, baudRate: Int) { - try { - setState(0) - // 只有干茧机 和 新Android11 设备是xbin - val suPath = getSuPath() - if (!suPath.isNullOrEmpty()) { - // 找到 su 路径,可以执行 setSuPath - SerialPort.setSuPath(suPath) - } - if (_serialPortList.value.isEmpty()) { - init() - if (_serialPortList.value.isEmpty()) { - Toasty.showTipsDialog("未检测到串口,无法连接超高频读卡器") - return - } - } - if (mSioBase?.connect(port, baudRate) == true) { - setPort(port) - setBaudRate(baudRate) - setState(1) - stopScan() - } else { - Toasty.showTipsDialog("超高频读卡器连接失败,请检查串口") - setState(-1) - } - Command(RcpMM.RCP_MM_PARA, RcpBase.RCP_MSG_GET) - - mRcpBase?.setOnProtocolListener({ obj, protocolEventArg -> - protocolScope.launch { - val psData = protocolEventArg.protocolPacket - when (psData.Code) { - RcpMM.RCP_MM_READ_C_UII -> - if (psData.Length > 0 && (psData.Type.toInt() == 0x05 || psData.Type.toInt() == 0x02)) { - var dataIndex = 0 - val tagID = TagID() - tagID.ant = psData.Payload[dataIndex++].toInt() //天线号,单天线读卡器默认0 - val pcepclen = RcpBase.GetCodelen(psData.Payload[dataIndex]) - tagID.pc = - SioBase.ByteArrayToHexString( - psData.Payload, - dataIndex, - 2 - ) //pc - dataIndex += 2 - tagID.epc = - SioBase.ByteArrayToHexString( - psData.Payload, - dataIndex, - pcepclen - 2 - ) //epc - dataIndex += pcepclen - 2 - - if (psData.Length % 2 == 1) { - if (psData.Length - dataIndex > 0) tagID.data = - SioBase.ByteArrayToHexString( - psData.Payload, - dataIndex, - psData.Length - dataIndex - ) //附加数据 - } else { - tagID.rssi = - RcpMM.CalcTagRssi(psData.Payload[dataIndex]) //rssi - } - addToList(tagID); - } else if (psData.Type.toInt() == 0x06) { - val tagID = TagID() - tagID.pc = "scan" - tagID.epc = ConverterUtil.SGBKToString( - psData.Payload, 0, - psData.Length.toInt() - ) - addToList(tagID); - } else if (psData.Type.toInt() == 0 || psData.Type.toInt() == 1) { -// if (hmR != null) hmR!!.setCommand() - } - - RcpMM.RCP_MM_PARA -> - if (psData.Length > 0 && psData.Type.toInt() == 0) { - val commmode = psData.Payload[0].toInt() - val workmode = psData.Payload[1].toInt() - - if (workmode == 0) { - _readAuto.value = false - } else if (workmode == 1) { - _readAuto.value = true - } - } - } - } - }) - onCommListener = object : OnCommListener { - override fun onStatus(`object`: Any, statusEvent: StatusEvent) { - if (statusEvent.status == StatusType.BATTERY_LEVEL) { - mBattaryLevel = statusEvent.getObject() as Int - Toasty.showToast( - "New Tag Read Succeed! BAT Level:[$mBattaryLevel] " - ) - } - } - - // override fun onReceived(`object`: Any, iData: ByteArray) { -// try { -// frameBuffer.write(iData) -// val bytes = frameBuffer.toByteArray() -// var index = 0 -// -// while (index + 4 <= bytes.size) { // 最小帧长 = 帧头+命令+长度+校验 = 4字节 -// if (bytes[index] != 0xBB.toByte()) { -// index++ // 忽略非帧头字节 -// continue -// } -// -// val cmdIndex = index + 1 -// val lenIndex = index + 2 -// val dataLen = bytes[lenIndex].toInt() and 0xFF -// val fullLen = 1 + 1 + 1 + dataLen + 1 // 帧结构总长度 -// -// if (index + fullLen > bytes.size) { -// break // 数据还不完整,等待下一次补齐 -// } -// -// val frame = bytes.copyOfRange(index, index + fullLen) -// if (isValidChecksum(frame)) { -// mRcpBase?.receivePacketByte(frame) -// } -// index += fullLen // 移动到下一帧 -// } -// -// // 清除已处理部分,保留剩余数据 -// frameBuffer.reset() -// frameBuffer.write(bytes.copyOfRange(index, bytes.size)) -// } catch (e: Exception) { -// Toasty.error("超高频读卡器接收数据异常: ${e.message}") -// } -// } - override fun onReceived(`object`: Any, iData: ByteArray) { - try { - mRcpBase?.receivePacketByte(iData) - } catch (e: Exception) { - Toasty.showTipsDialog("超高频读卡器接收数据异常: ${e.message ?: "未知错误"}") - } - } - }; - //加载当前通讯类状态监听 - (mSioBase as? SioCom)?.setOnCommListener(onCommListener) - } catch (e: Exception) { - MyLog.test("超高频读卡器连接失败${e.message}") - } - } - - fun isValidChecksum(frame: ByteArray): Boolean { - if (frame.size < 4) return false - val cmd = frame[1] - val len = frame[2].toInt() and 0xFF - val data = frame.sliceArray(1 until (3 + len)) // 从 cmd 到 data 结尾 - val checksum = frame[3 + len] - return data.reduce { acc, b -> (acc xor b) } == checksum - } - - override fun startScan() { - doInIoThreadNoDialog { - clearList() - _readAuto.value = false - IdentifyCtrl(true) - } - } - - fun IdentifyCtrl(flag: Boolean) { - _readAuto.value = flag - Command( - RcpMM.RCP_MM_CTRL_AUTO_READ, - RcpBase.RCP_MSG_CMD, - byteArrayOf((if (flag) 1 else 0).toByte()) - ) - } - - - override fun getModelName() = "QBG06M\nQBG25M" - - override fun stopScan() { - doInIoThreadNoDialog { - IdentifyCtrl(false) - } - } - - override fun reStartScan() { - doInIoThreadNoDialog { - IdentifyCtrl(false) - _readAuto.value = false - delay(50) - clearList() - IdentifyCtrl(true) - _readAuto.value = true - } - } - -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/uhf/UHFReaderG20R.kt b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/uhf/UHFReaderG20R.kt deleted file mode 100644 index b8ff617..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/devices/reader/uhf/UHFReaderG20R.kt +++ /dev/null @@ -1,139 +0,0 @@ -package com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf - -import android.serialport.SerialPort -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M.IdentifyCtrl -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M.getSuPath -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial.UHFReaderForSerial -import com.bbitcn.f8.pad.utils.log.MyLog -import com.rfid.trans18.ReadTag -import com.rfid.trans18.TagCallback -import com.rfid.trans18.UHFLib -import kotlinx.coroutines.delay - -object UHFReaderG20R : UHFReaderForSerial() { - - override fun getDeviceName(): String = "旧超高频读卡器" - - override fun getModelName() = "QBG20R" - - lateinit var uhf: UHFLib - - init { - doInIoThreadNoDialog() { - try { - uhf = UHFLib(0)//0:串口 1:TCP - } catch (e: Exception) { - e.printStackTrace() - } - } - } - - private fun addToList(tagID: ReadTag) { - val list = _tagList.value.toMutableList() - list.forEach { - if (it == tagID.epcId) { - return - } - } - list.add(tagID.epcId) - _tagList.value = list - } - - - override fun test() { - - } - - override suspend fun overrideDisconnect() { - try { - if (uhf.DisConnect() == 0) { - Toasty.success("超高频读卡器断开成功") - MyLog.test("超高频读卡器断开成功") - } - } catch (e: Exception) { - e.printStackTrace() - } - } - - - override fun connect(port: String, baudRate: Int) { - doInIoThreadNoDialog { - try { - setState(0) - val suPath = getSuPath() - if (!suPath.isNullOrEmpty()) { - // 找到 su 路径,可以执行 setSuPath - com.rfid.serialport.SerialPort.setSuPath("/system/xbin/su") - } - if (uhf.Connect(port, baudRate) == 0) { -// uhf.SetRfPower(14) -// uhf.SetInventoryScanTime(1) - Toasty.success("超高频读卡器连接成功") - MyLog.test("超高频读卡器连接成功") - setState(1) - } else { - setState(-1) - } - } catch (e: UnsatisfiedLinkError) { - MyLog.test("超高频读卡器连接失败${e.message}") - } catch (e: Exception) { - setState(-1) - Toasty.error("超高频读卡器连接失败${e.message}") - MyLog.test("超高频读卡器连接失败${e.message}") - } - } - } - - override fun startScan() { - doInIoThreadNoDialog { - clearList() -// 0- 应答模式下盘点标签 -// 1- 主动模式下获取上传的标签数据 - // - uhf.StartRead(0) - _readAuto.value = true - uhf.SetCallBack(object : TagCallback { - override fun tagCallback(p0: ReadTag?) { - if (p0 != null) { - addToList(p0) - } - } - - override fun tagCallbackFailed(p0: Int): Int { - // 251:没有标签 - return p0 - } - }) - } - } - - - override fun stopScan() { - doInIoThreadNoDialog { - uhf.StopRead() - _readAuto.value = false - } - } - - override fun reStartScan() { - doInIoThreadNoDialog { - uhf.StopRead() - _readAuto.value = false - delay(50) - clearList() - uhf.StartRead(0) - _readAuto.value = true - uhf.SetCallBack(object : TagCallback { - override fun tagCallback(p0: ReadTag?) { - if (p0 != null) { - addToList(p0) - } - } - override fun tagCallbackFailed(p0: Int): Int { - return p0 - } - }) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/manager/serial/SerialDeviceConnector2.kt b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/manager/serial/SerialDeviceConnector2.kt deleted file mode 100644 index 18d4410..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/manager/serial/SerialDeviceConnector2.kt +++ /dev/null @@ -1,111 +0,0 @@ -package com.bbitcn.f8.pad.utils.externalModules.manager.serial - -import android.content.Context -import android.hardware.usb.UsbManager -import com.bbitcn.f8.pad.ui.screen.view.Toasty -import com.bbitcn.f8.pad.utils.MMKVUtil -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import com.bbitcn.f8.pad.utils.externalModules.manager.DeviceController -import com.bbitcn.f8.pad.utils.log.MyLog -import com.blankj.utilcode.util.ActivityUtils -import com.hoho.android.usbserial.driver.UsbSerialDriver -import com.hoho.android.usbserial.driver.UsbSerialPort -import com.hoho.android.usbserial.driver.UsbSerialProber -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow - -// 串口设备-通过 usb-serial-for-android 库连接 -abstract class SerialDeviceConnector2 : DeviceController() { - - protected val _serialPortList = MutableStateFlow>(emptyList()) - val serialPortList = _serialPortList.asStateFlow() - var port: UsbSerialPort? = null - val manager: UsbManager? by lazy { - ActivityUtils.getTopActivity().getSystemService(Context.USB_SERVICE) as UsbManager? - } - - init { - doInIoThreadNoDialog { - init() - } - } - - suspend fun init() { - val availableDrivers: List = - UsbSerialProber.getDefaultProber().findAllDrivers( - manager - ) - _serialPortList.value = availableDrivers - } - - suspend fun sendMsg(msg: String) { - // 发送数据 1000ms超时 - if (port == null) { - MyLog.test("设备未连接,无法发送数据") - return - } else { - MyLog.test("发送数据:$msg") - port!!.write(msg.toByteArray(), 1000) - } - } - - fun connect(driverName: String, baudRate: Int) { - doInIoThreadNoDialog { - try { - setState(0) - if (_serialPortList.value.isEmpty()) { - init() - if (_serialPortList.value.isEmpty()) { - Toasty.showTipsDialog("未检测到可用新串口设备,无法连接") - return@doInIoThreadNoDialog - } - } - val driver: UsbSerialDriver = - _serialPortList.value.find { it.device.deviceName == driverName } ?: return@doInIoThreadNoDialog - val connection = manager!!.openDevice(driver.getDevice()) ?: return@doInIoThreadNoDialog - port = driver.getPorts().get(0) // Most devices have just one port (port 0) - if (port == null) { - MyLog.test(getDeviceName() + "连接失败") - setState(-1) - return@doInIoThreadNoDialog - } - setRDeviceName(driverName) - setBaudRate(baudRate) - setState(1) - port!!.open(connection) - port!!.setParameters( - baudRate, - 8, - UsbSerialPort.STOPBITS_1, - UsbSerialPort.PARITY_NONE - ) - } catch (e: Exception) { - setState(-1) - MyLog.test(getDeviceName() + "连接失败${e.message}") - } - } - } - - override suspend fun overrideDisconnect() { - port?.close() // 关闭串口连接 - } - - fun setRDeviceName(port: String) { - MMKVUtil.put(getDeviceName() + "_r_device_name", port) - } - - suspend fun getRDeviceName(): String { - return MMKVUtil.get(getDeviceName() + "_r_device_name", "/dev/bus/usb/002/003") - } - - fun setBaudRate(baudRate: Int) { - MMKVUtil.put(getDeviceName() + "_baudRate", baudRate) - } - - suspend fun getBaudRate(): Int { - return MMKVUtil.get(getDeviceName() + "_baudRate", 9600) - } - - abstract fun test() - -} diff --git a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/manager/serial/uhfSerial/UHFReaderForSerial.kt b/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/manager/serial/uhfSerial/UHFReaderForSerial.kt deleted file mode 100644 index 4ef325c..0000000 --- a/app/src/main/java/com/bbitcn/f8/pad/utils/externalModules/manager/serial/uhfSerial/UHFReaderForSerial.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.bbitcn.f8.pad.utils.externalModules.manager.serial.uhfSerial - -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG06M_G25M -import com.bbitcn.f8.pad.utils.externalModules.devices.reader.uhf.UHFReaderG20R -import com.bbitcn.f8.pad.utils.externalModules.manager.serial.SerialDeviceConnector -import com.bbitcn.f8.pad.utils.log.MyLog -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import java.util.UUID - -// 串口-超高频设备 -abstract class UHFReaderForSerial: SerialDeviceConnector() { - - protected val _tagList = MutableStateFlow>(emptyList()) - val tagList = _tagList.asStateFlow() - - protected var _readAuto = MutableStateFlow(false) - val readAuto = _readAuto.asStateFlow() - - - fun clearList(){ - _tagList.value = emptyList() - } - abstract fun getModelName(): String - abstract fun startScan() - abstract fun stopScan() - abstract fun reStartScan() - - companion object { - - suspend fun startAllScan() { - MyLog.test("startAllScan") - val device = listOf(UHFReaderG06M_G25M, UHFReaderG20R) - device.forEach { - if (it.state.value == 1) { - it.startScan() - } - } - } - - fun stopAllScan() { - MyLog.test("stopAllScan") - val device = listOf(UHFReaderG06M_G25M, UHFReaderG20R) - device.forEach { - if (it.state.value == 1) { - it.stopScan() - } - } - } - - } - -} diff --git a/app/src/main/res/xml/nfc_tech_filter.xml b/app/src/main/res/xml/nfc_tech_filter.xml deleted file mode 100644 index c15d6b9..0000000 --- a/app/src/main/res/xml/nfc_tech_filter.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - android.nfc.tech.IsoDep - android.nfc.tech.NfcA - android.nfc.tech.NfcB - android.nfc.tech.NfcF - android.nfc.tech.NfcV - android.nfc.tech.Ndef - android.nfc.tech.NdefFormatable - android.nfc.tech.MifareClassic - android.nfc.tech.MifareUltralight - - - - - - - - - - - \ No newline at end of file