初始化项目

This commit is contained in:
BBIT-Kai
2026-05-25 15:06:08 +08:00
commit 2017535f0f
630 changed files with 52394 additions and 0 deletions
@@ -0,0 +1,24 @@
package com.bbitcn.f8.pad
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.bbitcn.f8.pad", appContext.packageName)
}
}
+141
View File
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- NFC -->
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="false" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- 安装应用-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!-- 电话状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 蓝牙-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 网络-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 存储权限-->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!--配置权限,用来记录应用配置信息 -->
<uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务-->
<!--定位信息是敏感信息,可通过Setting.setLocationEnable(false)关闭定位请求 -->
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>-->
<!--如需使用人脸识别,还要添加:摄像头权限,拍照需要用到 -->
<!-- <uses-permission android:name="android.permission.CAMERA" />-->
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<!-- 摄像头权限-->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.any" />
<!-- 超高频读卡器 -->
<uses-permission
android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<!-- 开机自启-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- USB-->
<uses-permission android:name="android.permission.USB_PERMISSION" />
<uses-feature android:name="android.hardware.usb.host" />
<application
android:name=".MyApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/logo"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:resizeableActivity="true"
android:roundIcon="@drawable/logo"
android:supportsRtl="true"
android:theme="@style/Theme.F8"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".ui.MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/Theme.F8">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
<service android:name="com.inuker.bluetooth.library.BluetoothService" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.bbitcn.f8.pad.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<receiver
android:name=".receiver.BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.FrpStartReceiver"
android:exported="true">
<intent-filter>
<action android:name="receiver_start_frp" />
<action android:name="receiver_frp_version" />
<action android:name="receiver_frp_info" />
</intent-filter>
</receiver>
<meta-data
android:name="ScopedStorage"
android:value="true" />
</application>
</manifest>
Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

@@ -0,0 +1,30 @@
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");
}
}
@@ -0,0 +1,95 @@
/*
* 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<ParsedNdefRecord> parse(NdefMessage message) {
return getRecords(message.getRecords());
}
public static List<ParsedNdefRecord> getRecords(NdefRecord[] records) {
List<ParsedNdefRecord> elements = new ArrayList<ParsedNdefRecord>();
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();
}
}
@@ -0,0 +1,26 @@
/*
* 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();
}
@@ -0,0 +1,205 @@
/*
* 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<ParsedNdefRecord> 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> T getFirstIfExists(Iterable<?> elements, Class<T> type) {
Iterable<T> 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<Byte, RecommendedAction> LOOKUP;
static {
ImmutableMap.Builder<Byte, RecommendedAction> 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();
}
}
@@ -0,0 +1,107 @@
/*
* 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;
}
}
}
@@ -0,0 +1,148 @@
/*
* 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<Byte, String> URI_PREFIX_MAP = ImmutableBiMap.<Byte, String>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];
}
@@ -0,0 +1,79 @@
package com.bbitcn.f8.pad
import android.app.Application
import android.content.Context
import android.provider.Settings
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.ui.Modifier
import com.bbitcn.f8.pad.utils.MMKVUtil
import com.bbitcn.f8.pad.utils.TTSManager
import com.bbitcn.f8.pad.utils.global.Global
import com.bbitcn.f8.pad.utils.log.CrashHandlerUtil
import com.bbitcn.f8.pad.utils.log.MyLog
import com.blankj.utilcode.util.ActivityUtils
import com.iflytek.cloud.SpeechConstant
import com.iflytek.cloud.SpeechUtility
import org.xutils.x
import timber.log.Timber
/**
* @Description APPLICATION类
* @Author DuanKaiji
* @CreateTime 2024年03月27日 13:43
*/
val M = Modifier
.animateContentSize(
animationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessLow
)
)
val MD = Modifier
val IS_DEBUG_DRYCOCOON = false // 是否是调试状态
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
// 初始化MMKV
MMKVUtil.init(applicationContext)
// 初始化崩溃捕捉
CrashHandlerUtil.init()
// 初始化日志库
Timber.plant(MyLog())
// 初始化网络请求库
x.Ext.init(this)
// 初始化全局变量
MMKVUtil.put(Global.DEVICE_ID, Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID))
// 初始化讯飞语音
SpeechUtility.createUtility(applicationContext, SpeechConstant.APPID +"=5d0fed03")
// 初始化文本转语音
TTSManager.init(applicationContext)
MyLog.test("设备唯一码:${Global.getDeviceId()}")
// 在开发阶段启用 StrictMode
// if (BuildConfig.DEBUG) {
// val policy = StrictMode.ThreadPolicy.Builder()
// .detectDiskReads()
// .detectDiskWrites()
// .detectNetwork()
// .penaltyLog() // 记录到 Logcat
// .build()
//
// StrictMode.setThreadPolicy(policy)
// }
}
companion object {
@JvmStatic
val appContext: Context
get() = ActivityUtils.getTopActivity()
}
}
@@ -0,0 +1,164 @@
package com.bbitcn.f8.pad.base
import android.app.Activity
import android.os.Build
import android.view.WindowInsetsController
import androidx.annotation.RequiresApi
import androidx.compose.foundation.background
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.Spacer
import androidx.compose.foundation.layout.WindowInsets
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.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.max
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import com.bbitcn.f8.pad.M
import com.bbitcn.f8.pad.MyApp
import com.blankj.utilcode.util.ActivityUtils
@Preview(showBackground = true, widthDp = 1280, heightDp = 800)
@Composable
fun BaseDialogPreview() {
MyDialog(
title = "关于我们",
showDialog = true,
onDismissRequest = {},
content = {
Column {
Text(
text = "奥立集团旗下四川主干信息技术有限公司,是一家专业从事搭建互联网云平台," +
"服务传统行业的互联网企业,主营业务包括软件产品设计与研发、系统集成与维护" +
"、互联网数据挖掘及应用。公司秉承“行业互助,资源共享、助小众企业实现大众信息化" +
"、助大众企业实现全球化”的企业宗旨,以“专业、创新、服务、共赢”为核心价值观," +
"为客户提供全方位的信息化解决方案。",
color = Color.Black
)
}
}, onClickOK = {
}
)
}
@Composable
fun MyDialog(
title: String = "",
showDialog: Boolean,
onDismissRequest: () -> Unit,
clickOKStr: String = "",
onClickOK: () -> Unit = {},
content: @Composable () -> Unit,
) {
MyAnimatedVisibility(showDialog) {
Box(
modifier = M
.fillMaxSize()
.background(Color(0x99000000))
.noVisualFeedbackClickable {
// onDismissRequest()
},
contentAlignment = Alignment.Center
) {
BaseDialogFrame(title, {
content()
}) {
Row(modifier = M.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
BigButton(
"返回", modifier = M
.weight(1f)
.widthIn(max = 100.dp)
) {
onDismissRequest()
}
// 判断是否有点击事件
if (clickOKStr != "") {
Spacer(modifier = M.width(30.dp))
BigButton(clickOKStr, modifier = M.weight(1f), true) {
onClickOK()
}
}
}
}
}
}
}
@Composable
fun BaseDialogFrame(
title: String = "",
content: @Composable () -> Unit = {},
bottomContent: @Composable () -> Unit = {}
) {
MyCard(
modifier = M
.padding(top = 10.dp, bottom = 50.dp, start = 100.dp, end = 100.dp)
.noVisualFeedbackClickable { }
.fillMaxSize()
) {
Column(
modifier = M
.fillMaxSize()
.padding(horizontal = 30.dp)
) {
Row(
modifier = M
.padding(top = 20.dp, bottom = 5.dp)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
// 一个绿色的竖线
Box(
modifier = M
.width(3.dp)
.height(40.dp)
.padding(end = 10.dp)
.background(Color(0xFF209344))
)
Text(
text = title,
fontSize = MaterialTheme.typography.titleLarge.fontSize,
)
}
Box(
modifier = M
.weight(1f)
.fillMaxWidth(),
contentAlignment = Alignment.TopCenter
) {
content()
}
Column(
modifier = M
.fillMaxWidth()
.padding(top = 10.dp, bottom = 20.dp), // 调整底部间距
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
bottomContent()
}
}
}
}
}
@@ -0,0 +1,751 @@
package com.bbitcn.f8.pad.base
import android.R.attr.onClick
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Text
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.VerticalDivider
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.material3.pulltorefresh.PullToRefreshState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
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 androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.itemKey
import com.bbitcn.f8.pad.M
import com.bbitcn.f8.pad.MD
import com.bbitcn.f8.pad.R
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 org.slf4j.helpers.Reporter.info
import kotlin.collections.map
@Composable
fun TableHeadLine(modifier: Modifier, list: List<Pair<String, Int>>) {
MyCard(elevation = 0.dp, colors = MyColors.BlueGreen, radius = 5.dp) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
list.forEach {
if (it.first == "|") {
VerticalDivider(
color = MyColors.Gray,
thickness = 1.dp,
modifier = M
.height(25.dp)
.padding(horizontal = 5.dp)
)
} else {
Text(
text = it.first,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = M
.weight(it.second.toFloat())
.padding(vertical = 7.dp),
fontWeight = FontWeight.Bold,
color = MyColors.White,
textAlign = TextAlign.Center,
)
}
}
}
}
}
@Composable
fun TableHeadLineCard(modifier: Modifier, list: List<Pair<String, Int>>, isSelect: Boolean) {
MyCard(
elevation = 0.dp,
radius = 0.dp,
colors = if (isSelect) MyColors.BlueGreen else MyColors.White
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
list.forEach {
Text(
text = it.first,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = M
.weight(it.second.toFloat())
.padding(vertical = 5.dp),
fontWeight = FontWeight.Bold,
color = if (isSelect) MyColors.White else MyColors.Black,
textAlign = TextAlign.Center,
)
}
}
}
}
@Composable
fun TableContent(
modifier: Modifier,
backgroundDeepColor: Boolean,
list: List<Pair<String, Int>>,
verticalPadding: Dp = 5.dp,
onLongClick: () -> Unit = {},
onClick: () -> Unit = {}
) {
Card(
modifier = modifier.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
onLongClick()
},
onTap = {
onClick()
}
)
},
colors = CardDefaults.cardColors(
containerColor = if (backgroundDeepColor) Color(0xFFF3F7FD) else Color.White
)
) {
Row(
modifier = M.padding(vertical = verticalPadding),
verticalAlignment = Alignment.CenterVertically
) {
list.forEach {
if (it.first == "|") {
VerticalDivider(
color = MyColors.Gray,
thickness = 1.dp,
modifier = M
.height(10.dp)
.padding(horizontal = 5.dp)
)
} else {
Text(
text = it.first,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = M.weight(it.second.toFloat()),
textAlign = TextAlign.Center,
)
}
}
}
}
}
@Composable
fun MyTable(
modifier: Modifier,
headerStrings: List<String>,
ratio: List<Float>,
items: List<List<Any>>,
verticalPadding: Dp = 5.dp,
) {
Column(modifier = modifier) {
TableHeadLine(
modifier = M.fillMaxWidth(),
list = headerStrings.zip(ratio.map { it.toInt() })
)
LazyColumn {
items(count = items.size) { itIndex ->
TableContent(
verticalPadding = verticalPadding,
modifier = M
.fillMaxWidth()
.animateItem(),
backgroundDeepColor = itIndex % 2 == 0,
list = items[itIndex].map { it.toString() }.zip(ratio.map { it.toInt() }),
)
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun <T : Any> MyRefreshTableForCard(
modifier: Modifier,
isRefreshing: Boolean,
info: LazyPagingItems<T>,
key: (T) -> Any,
onFinishRefresh: () -> Unit,
columns: Int,// 列数
item: @Composable (T, index: Int) -> Unit,
) {
val state = rememberPullToRefreshState()
val pagerSate = info.loadState.append
LaunchedEffect(pagerSate) {
if (pagerSate is LoadState.NotLoading) {
onFinishRefresh()
}
}
Column(modifier = modifier) {
PullToRefreshBox(
modifier = M.fillMaxSize(),
state = state,
isRefreshing = isRefreshing,
onRefresh = {
info.refresh()
},
indicator = {
PullToRefreshDefaults.IndicatorBox(
state = state,
isRefreshing = isRefreshing,
modifier = M.align(Alignment.TopCenter),
elevation = 0.dp
) {
if (isRefreshing) {
CircularProgressIndicator(modifier = M.size(30.dp))
} else {
CircularProgressIndicator(
modifier = M.size(30.dp),
progress = { state.distanceFraction },
trackColor = ProgressIndicatorDefaults.circularIndeterminateTrackColor,
)
}
}
}
) {
LazyVerticalGrid(
modifier = M.fillMaxSize(),
columns = GridCells.Fixed(columns),
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
items(count = info.itemCount, key = info.itemKey { key(it) }) { index ->
val lineItem = info[index]!!
Box(modifier = M.animateItem()) {
item(lineItem, index)
}
}
item {
when (pagerSate) {
is LoadState.NotLoading -> if (pagerSate.endOfPaginationReached)
ListNoMore()
is LoadState.Loading -> ListLoading()
is LoadState.Error -> ListError(message = pagerSate.error.message.toString())
}
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun <T : Any> MyAnyTable(
modifier: Modifier,
// 每行
info: List<T>,
onLongClick: (T) -> Unit = {},
onClick: (T) -> Unit = {},
// 每列
items: List<MyTableData<T>>,
verticalPadding: Dp = 15.dp,
) {
Column(modifier = modifier) {
TableHeadLine(
modifier = M.fillMaxWidth(), list = items.map { it.header to it.weight }
)
var selectIndex by rememberSaveable { mutableStateOf(-1) }
LazyColumn {
items(count = info.size) { index ->
// 每行
val lineItem = info[index]
Card(
modifier = M
.animateItem()
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
onLongClick(lineItem)
},
onTap = {
onClick(lineItem)
selectIndex = if (selectIndex == index) -1 else index
}
)
},
colors = CardDefaults.cardColors(
containerColor = if (selectIndex == index
|| (index % 2 == 0)
) {
Color(0xFFF3F7FD)
} else {
Color.White
}
)
) {
Box(
modifier = M
.fillMaxSize()
.padding()
.padding(vertical = verticalPadding),
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
items.forEach { item ->
val content = item.content(lineItem)
if (content == "|") {
VerticalDivider(
color = MyColors.Gray,
thickness = 1.dp,
modifier = M
.height(10.dp)
.padding(horizontal = 5.dp)
)
} else if (item.isButton) {
MyButton(
text = content,
modifier = M
.weight(item.weight.toFloat())
.padding(horizontal = 2.5.dp),
contentPadding = PaddingValues(5.dp, 2.5.dp)
) {
item.onClick(lineItem)
}
} else if (item.isIndex) {
Text(
text = (index + 1).toString(),
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = M.weight(item.weight.toFloat()),
textAlign = TextAlign.Center,
)
} else {
Text(
text = content,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = M.weight(item.weight.toFloat()),
textAlign = TextAlign.Center,
maxLines = 1, // 限制为单行
overflow = TextOverflow.Ellipsis // 超出部分显示省略号
)
}
}
}
}
}
}
}
}
}
@Composable
fun <T : Any> MyTable2(
modifier: Modifier = Modifier,
infos: List<T>,
items: List<MyTableData<T>>,
onLongClick: (T) -> Unit = {},
onClick: (T) -> Unit = {},
onExpend: @Composable (T) -> Unit = {},
verticalPadding: Dp = 5.dp,
) {
Column(modifier = modifier) {
// 表头
TableHeadLine(
modifier = Modifier.fillMaxWidth(),
list = items.map { it.header to it.weight }
)
var selectIndex by rememberSaveable { mutableStateOf(-1) }
LazyColumn {
items(count = infos.size) { index ->
val lineItem = infos[index]
Card(
modifier = MD
.animateItem()
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
onLongClick(lineItem)
},
onTap = {
selectIndex = if (selectIndex == index) -1 else index
onClick(lineItem)
}
)
},
// 直角
shape = MaterialTheme.shapes.small,
colors = CardDefaults.cardColors(
containerColor = if (selectIndex == index) {
MyColors.LightLightBlueGreen
} else if (index % 2 == 0) {
Color(0xFFF3F7FD)
} else {
Color.White
}
)
) {
Column(
modifier = Modifier
.fillMaxWidth(),
) {
Row(
modifier = M
.padding(vertical = verticalPadding),
verticalAlignment = Alignment.CenterVertically
) {
items.forEach { item ->
Text(
text = item.content(lineItem),
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = Modifier.weight(item.weight.toFloat()),
textAlign = TextAlign.Center,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
if (selectIndex == index) {
Box(modifier = M.padding(2.5.dp)){
Column {
onExpend(lineItem)
}
}
}
}
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun <T : Any> MyRefreshTable(
modifier: Modifier,
isRefreshing: Boolean,
info: LazyPagingItems<T>,
key: (T) -> Any,
onFinishRefresh: () -> Unit,
// 每行
onLongClick: (T) -> Unit = {},
onClick: (T) -> Unit = {},
onExpend: @Composable (T) -> Unit = {},
// 每列
items: List<MyTableData<T>>,
verticalPadding: Dp = 15.dp,
scrollToTopOnRefresh: Boolean = false,
) {
val listState: LazyListState = rememberLazyListState()
val state = rememberPullToRefreshState()
val pagerSate = info.loadState.append
LaunchedEffect(pagerSate) {
if (pagerSate is LoadState.NotLoading) {
onFinishRefresh()
}
}
LaunchedEffect(info.loadState.refresh) {
if (info.loadState.refresh is LoadState.NotLoading && scrollToTopOnRefresh) {
listState.animateScrollToItem(0)
}
}
Column(modifier = modifier) {
TableHeadLine(
modifier = M.fillMaxWidth(), list = items.map { it.header to it.weight }
)
PullToRefreshBox(
modifier = M.fillMaxSize(),
state = state,
isRefreshing = isRefreshing,
onRefresh = {
info.refresh()
},
indicator = {
PullToRefreshDefaults.IndicatorBox(
state = state,
isRefreshing = isRefreshing,
modifier = M.align(Alignment.TopCenter),
elevation = 0.dp
) {
if (isRefreshing) {
CircularProgressIndicator(modifier = M.size(30.dp))
} else {
CircularProgressIndicator(
modifier = M.size(30.dp),
progress = { state.distanceFraction },
trackColor = ProgressIndicatorDefaults.circularIndeterminateTrackColor,
)
}
}
}
) {
var selectIndex by rememberSaveable { mutableStateOf(-1) }
LazyColumn(state = listState) {
items(count = info.itemCount, key = info.itemKey { key(it) }) { index ->
// // 每行
val lineItem = info[index]!!
Card(
modifier = MD
.animateItem()
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
onLongClick(lineItem)
},
onTap = {
onClick(lineItem)
selectIndex = if (selectIndex == index) -1 else index
}
)
},
colors = CardDefaults.cardColors(
containerColor = if (selectIndex == index) {
MyColors.LightLightBlueGreen
} else if (index % 2 == 0) {
Color(0xFFF3F7FD)
} else {
Color.White
}
)
) {
Column(
modifier = M
.fillMaxSize()
.padding(vertical = verticalPadding),
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
items.forEach { item ->
val content = item.content(lineItem)
if (content == "|") {
VerticalDivider(
color = MyColors.Gray,
thickness = 1.dp,
modifier = M
.height(10.dp)
.padding(horizontal = 5.dp)
)
} else if (item.isButton) {
MyButton(
text = content,
modifier = M
.weight(item.weight.toFloat())
.padding(horizontal = 2.5.dp),
contentPadding = PaddingValues(5.dp, 2.dp)
) {
item.onClick(lineItem)
}
} else if (item.isIndex) {
Text(
text = (index + 1).toString(),
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = M.weight(item.weight.toFloat()),
textAlign = TextAlign.Center,
)
} else {
Text(
text = content,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = M.weight(item.weight.toFloat()),
textAlign = TextAlign.Center,
maxLines = 1, // 限制为单行
overflow = TextOverflow.Ellipsis // 超出部分显示省略号
)
}
}
}
if (selectIndex == index) {
onExpend(lineItem)
}
}
}
}
item {
when (pagerSate) {
is LoadState.NotLoading -> if (pagerSate.endOfPaginationReached)
ListNoMore()
is LoadState.Loading -> ListLoading()
is LoadState.Error -> ListError(message = pagerSate.error.message.toString())
}
}
}
}
}
}
data class MyTableData<T>(
val header: String,
val weight: Int,
val content: (T) -> String,
val isButton: Boolean = false,
val isIndex: Boolean = false,
val onClick: (T) -> Unit = {},
) {
constructor(weight: Int, isIndex: Boolean = false) : this(
header = "序号",
content = { "" },
weight = weight,
isIndex = isIndex
)
constructor(
header: String, weight: Int, content: (T) -> String
) : this(
header = header,
content = content,
weight = weight,
isButton = false,
isIndex = false,
onClick = { }
)
}
@Composable
fun ListNoMore() {
Row(
modifier = M
.fillMaxWidth()
.wrapContentHeight()
.padding(6.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Text(
color = Color.Black,
text = "没有更多数据了",
fontSize = 16.sp,
modifier = M
.padding(start = 12.dp)
.align(CenterVertically)
)
}
}
@Composable
fun ListLoading() {
Row(
modifier = M
.fillMaxWidth()
.wrapContentHeight()
.padding(6.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
CircularProgressIndicator(modifier = M.size(24.dp))
Text(
color = Color.Black,
text = "正在加载中...",
fontSize = 16.sp,
modifier = M
.padding(start = 12.dp)
.align(CenterVertically)
)
}
}
@Composable
fun ListError(message: String) {
Card(
modifier = M
.padding(6.dp)
.fillMaxWidth()
.wrapContentHeight()
) {
Row(
modifier = M
.fillMaxWidth()
.background(Color.Red)
.padding(8.dp)
) {
Image(
modifier = M
.clip(CircleShape)
.width(42.dp)
.height(42.dp),
painter = painterResource(id = R.drawable.error),
contentDescription = "",
colorFilter = ColorFilter.tint(Color.White)
)
Text(
color = Color.White,
text = message,
fontSize = 16.sp,
modifier = M
.padding(start = 12.dp)
.align(CenterVertically)
)
}
}
}
@@ -0,0 +1,76 @@
package com.bbitcn.sericulture.base
import com.bbitcn.f8.pad.utils.MMKVUtil
import com.bbitcn.f8.pad.utils.log.MyLog
import com.google.gson.Gson
import java.lang.reflect.Type
/**
*
* @Description 列表临时存储库
* @Author DuanKaiji
* @CreateTime 2024年08月06日 11:39:31
*/
abstract class BaseListTempDataBase<T> {
protected val gson: Gson = Gson()
abstract fun getKey(): String
abstract fun getType(): Type
fun getAll(): MutableList<T> {
val json = MMKVUtil.get(getKey(), "[]")
return Gson().fromJson(json, getType())
}
suspend fun init(data: List<T>) {
MMKVUtil.put(getKey(), gson.toJson(data))
}
suspend fun insert(t: T, afterInsert: (T) -> Unit = {}): Boolean {
// val type: Type = ParameterizedTypeImpl(T::class.java)
val temp: MutableList<T> = getAll()
if (temp.contains(t)) {
return false
}
temp.add(t)
MyLog.test("insert: ${gson.toJson(temp)}")
MMKVUtil.put(getKey(), gson.toJson(temp))
afterInsert(t)
return true
}
/**
* 更新
*/
fun update(predicate: (T) -> Boolean, afterUpdate: (T) -> Unit = {}): Boolean {
val temp: MutableList<T> = getAll()
for (mode in temp) {
if (predicate(mode)) {
afterUpdate(mode)
MMKVUtil.put(getKey(), gson.toJson(temp))
return true
}
}
return false
}
fun delete(predicate: (T) -> Boolean,afterDel: (T) -> Boolean = { true }): Boolean {
val temp: MutableList<T> = getAll()
val iterator = temp.iterator()
while (iterator.hasNext()) {
val mode = iterator.next()
if (predicate(mode)) {
iterator.remove()
afterDel(mode)
MMKVUtil.put(getKey(), gson.toJson(temp))
return true
}
}
return false
}
fun clear(): Boolean {
MMKVUtil.put(getKey(), "[]")
return true
}
}
@@ -0,0 +1,41 @@
package com.bbitcn.f8.pad.base
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.bbitcn.f8.pad.model.net.request.PageInfo
import com.bbitcn.f8.pad.utils.network.RetrofitClient
abstract class BasePagingSource<T : Any, R : Any>(
private val requestData: R
) : PagingSource<Int, T>() {
val apiService = RetrofitClient.apiInterface()
abstract suspend fun fetchData(pageInfoJsonStr: String, requestData: R): List<T> // 返回 T 类型的列表
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, T> {
return try {
val page = params.key ?: 1
val pageSize = params.loadSize
val response = fetchData(PageInfo(page, pageSize).toJson(), requestData)
// 计算上一页和下一页的 key
val prevKey = if (page > 1) page - 1 else null
val nextKey = if (response.size < pageSize) null else page + 1
LoadResult.Page(
data = response, // 直接返回数据列表
prevKey = prevKey,
nextKey = nextKey
)
} catch (exception: Exception) {
LoadResult.Error(exception)
}
}
/**
* 这里可以根据当前的分页位置来返回刷新key
*/
override fun getRefreshKey(state: PagingState<Int, T>): Int {
return 1 // 默认返回1,具体实现可根据需求调整
}
}
@@ -0,0 +1,35 @@
package com.bbitcn.sericulture.base
import com.bbitcn.f8.pad.utils.MMKVUtil
import com.blankj.utilcode.util.GsonUtils
import com.google.gson.Gson
import java.lang.reflect.Type
/**
*
* @Description 临时数据库(单实体,列表请用@BaseListTempDataBase
* @Author DuanKaiji
* @CreateTime 2024年08月06日 11:39:31
*/
abstract class BaseTempDataBase<T> {
abstract fun getKey(): String
abstract fun defaultData(): T
abstract fun getType(): Type
fun init(value :T): Boolean {
MMKVUtil.put(getKey(), Gson().toJson(value))
return true
}
fun getData(): T {
val json = MMKVUtil.get(getKey(), GsonUtils.toJson(defaultData()))
return Gson().fromJson(json, getType())
}
fun clear(): Boolean {
MMKVUtil.put(getKey(), "")
return true
}
}
@@ -0,0 +1,215 @@
package com.bbitcn.f8.pad.base
import android.media.MediaPlayer
import androidx.compose.material3.SnackbarHostState
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.bbitcn.f8.pad.MyApp
import com.bbitcn.f8.pad.R
import com.bbitcn.f8.pad.ui.screen.dialog.LoadingDialogData
import com.bbitcn.f8.pad.ui.screen.dialog.TipsDialogData
import com.bbitcn.f8.pad.ui.screen.view.Toasty
import com.bbitcn.f8.pad.ui.screen.view.Toasty.hideLoadingDialog
import com.bbitcn.f8.pad.utils.PollingTask
import com.bbitcn.f8.pad.utils.log.MyLog
import com.bbitcn.f8.pad.utils.network.RetrofitClient
import com.bbitcn.f8.pad.utils.network.RetrofitClientAI
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import java.net.SocketException
import kotlin.coroutines.cancellation.CancellationException
open class BaseViewModel : ViewModel() {
val apiService = RetrofitClient.apiInterface()
val aiApiService = RetrofitClientAI.aiApiInterface()
protected var pollingTask: PollingTask =
PollingTask.getInstance(javaClass.simpleName) // 使用类名作为ID
protected fun doInUIThread(task: () -> Unit) {
viewModelScope.launch {
withContext(Dispatchers.Main) {
task()
}
}
}
protected fun <T> doInIoThreadThenUI(
loadingTips: String = "正在加载中",
showDialog: Boolean = true,
onError: (Throwable) -> Unit = { },
onIO: suspend () -> T,
onFinish: () -> Unit = { },
onUI: (T) -> Unit,
) {
viewModelScope.launch {
val result = kotlin.runCatching {
withContext(Dispatchers.IO) {
if (showDialog) {
Toasty.showLoadingDialog(loadingTips)
}
onIO()
}
}
if (showDialog) {
hideLoadingDialog()
}
withContext(Dispatchers.Main) {
result.onSuccess { data ->
onUI(data)
}.onFailure { exception ->
// ✅ 如果是协程取消,不处理,只记录日志
if (exception is CancellationException || exception.cause is SocketException && exception.cause?.message?.contains(
"Socket closed"
) == true
) {
MyLog.test("协程被取消:${exception.javaClass.simpleName}message=${exception.message}")
return@onFailure
}
// 其他异常继续处理
exception.printStackTrace()
onError(exception)
exception.message?.let {
Toasty.error(it)
}
}.also {
// ✅ 最终执行的操作
onFinish()
}
}
}
}
fun <T> doInIoThread(
loadingTips: String = "正在加载中",
showDialog: Boolean = true,
onError: (Throwable) -> Unit = { },
onFinish: () -> Unit = { },
doInIO: suspend () -> T,
) {
doInIoThreadThenUI(loadingTips, showDialog, onError, doInIO, onFinish) { }
}
fun <T> doInIoThreadNoDialog(
onError: (Throwable) -> Unit = { },
task: suspend () -> T,
) {
doInIoThread(showDialog = false, doInIO = task, onError = onError)
}
/**
* 在IO线程中执行任务,可选择是否显示加载对话框
*/
fun doInIoThreadWith(showLoading: Boolean, loadingTips: String, function: suspend () -> Unit) {
if (showLoading) {
doInIoThread(loadingTips) { function() }
} else {
doInIoThreadNoDialog { function() }
}
}
/**
* 启动一个无限轮询任务
*
* @param pollingInterval 轮询间隔时间(单位:秒)
* @param pollingTask 轮询任务的挂起函数
*/
fun polling(intervalSeconds: Long, task: suspend () -> Unit) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
MyLog.test("开始轮询任务,间隔:$intervalSeconds")
while (true) {
task()
delay(intervalSeconds * 1000L) // 转换秒为毫秒
}
}
}
}
/**
* 延迟开始轮询任务
*/
suspend fun delayPolling(delaySeconds: Long, intervalSeconds: Long, task: suspend () -> Unit) {
delay(delaySeconds * 1000L)
polling(intervalSeconds, task)
}
private val taskMap = mutableMapOf<String, Job>()
/**
* 放弃旧任务,执行新任务
*
* @param key 任务的唯一标识符
* @param block 任务的挂起函数,必须使用协程,不能开启新的协程,否则无法取消任务
*/
fun launchTaskNewFirst(
key: String,
block: suspend () -> Unit
) {
taskMap[key]?.cancel() // 取消旧任务
taskMap[key] = viewModelScope.launch {
withContext(Dispatchers.IO) {
try {
block()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
/**
* 有新任务时,取消。优先执行旧任务直到完成
*
* @param key 任务的唯一标识符
* @param block 任务函数,可以自由新建协程,但一定要在任务完成时调用 onFinished 回调,否则会导致后续任务永远无法执行
*/
fun launchTaskOldFirst(
key: String,
block: (onFinished: () -> Unit) -> Unit
) {
val existing = taskMap[key]
if (existing?.isActive == true) {
MyLog.test("已有任务在运行,取消新任务")
return
}
val job = viewModelScope.launch {
try {
suspendCancellableCoroutine<Unit> { continuation ->
block {
if (continuation.isActive) {
continuation.resume(Unit) { cause, _, _ ->
println("resume 后任务被取消: $cause")
}
}
taskMap.remove(key)
}
}
} catch (e: Exception) {
e.printStackTrace()
taskMap.remove(key)
}
}
taskMap[key] = job
}
override fun onCleared() {
super.onCleared()
taskMap.values.forEach { it.cancel() }
taskMap.clear()
}
}
@@ -0,0 +1,933 @@
package com.bbitcn.f8.pad.base
import android.bluetooth.BluetoothAdapter
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
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.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.AssistChip
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.InputChipDefaults
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.TabRow
import androidx.compose.material3.TabRowDefaults
import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
import androidx.compose.material3.Text
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.produceState
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.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil3.compose.AsyncImage
import coil3.request.ImageRequest
import com.bbitcn.f8.pad.M
import com.bbitcn.f8.pad.R
import com.bbitcn.f8.pad.ui.screen.view.Toasty
import com.bbitcn.f8.pad.ui.screen.view.drawer.IconInfo
import com.bbitcn.f8.pad.ui.theme.MyColors
import com.lt.compose_views.text_field.BackgroundComposeWithTextField
import com.lt.compose_views.text_field.GoodTextField
import com.lt.compose_views.text_field.HintComposeWithTextField
import kotlinx.coroutines.delay
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
/**
* 监听某个键的变化,附带防抖功能
*
* @param key 要监听的键
* @param debounceMillis 防抖延迟时间,默认100毫秒
* @param effect 当键变化时执行的副作用函数
*/
@Composable
fun <T> DebouncedEffect(
key: T,
debounceMillis: Long = 100L,
effect: suspend () -> Unit
) {
val stableKey by produceState(initialValue = key, key) {
delay(debounceMillis)
value = key
}
LaunchedEffect(stableKey) {
effect()
}
}
/**
*
* @Author DuanKaiji
* @CreateTime 2024年05月13日 10:09:12
*/
@Composable
fun WhiteText(
text: String,
modifier: Modifier = M,
fontSize: TextUnit = 16.sp,
fontWeight: FontWeight? = null,
color: Color = Color.White,
) {
Text(
text = text,
modifier = modifier,
fontSize = fontSize,
fontWeight = fontWeight,
color = color,
style = TextStyle.Default.copy(color = color),
)
}
@Composable
fun MyButton(
modifier: Modifier = M,
text: String = "",
enabled: Boolean = true,
shape: Shape = RoundedCornerShape(4.dp), // 将圆角设为 4.dp
border: BorderStroke? = null,
colors: Color = MyColors.BlueGreen,
contentPadding: PaddingValues = PaddingValues(
start = 24.dp, top = 2.dp,
end = 24.dp, bottom = 2.dp
),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
onClick: () -> Unit,
) {
Button(
onClick = onClick,
modifier = modifier,
enabled = enabled,
interactionSource = interactionSource,
shape = shape,
border = border,
colors = ButtonDefaults.buttonColors(containerColor = colors),
contentPadding = contentPadding,
) {
Text(
text = text,
fontSize = MaterialTheme.typography.titleMedium.fontSize,
textAlign = TextAlign.Center
)
}
}
@Composable
fun BigButton(text: String, modifier: Modifier = M, isLight: Boolean = false, onClick: () -> Unit) {
Button(
onClick = onClick,
shape = RoundedCornerShape(30.dp),
modifier = modifier
.height(50.dp)
.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(containerColor = if (text.contains("") || isLight) MyColors.BlueGreen else MyColors.Gray)
) {
WhiteText(text, fontSize = MaterialTheme.typography.headlineMedium.fontSize)
}
}
@Composable
fun MyCard(
modifier: Modifier = M,
colors: Color = if (isSystemInDarkTheme()) MyColors.Black else Color.White,
radius: Dp = 4.dp,
border: BorderStroke? = null,
elevation: Dp = 6.dp,
content: @Composable ColumnScope.() -> Unit
) {
Card(
modifier = modifier,
shape = RoundedCornerShape(radius),
colors = CardDefaults.cardColors(containerColor = colors),
elevation = CardDefaults.cardElevation(defaultElevation = elevation),
border = border,
content = content
)
}
@Composable
fun MyInfoCard(
modifier: Modifier,
content: @Composable ColumnScope.() -> Unit
) {
MyCard(
modifier = modifier,
elevation = 0.dp
) {
Box(modifier = M.fillMaxSize()) {
this@MyCard.content()
}
}
}
@Composable
fun MainFuncFrame(
content: @Composable ColumnScope.() -> Unit
) {
Box(
modifier = M
.fillMaxSize()
.background(Color.White)
) {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(R.drawable.bg)
.build(),
contentDescription = "Background",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
// 设置前景内容,透明背景方便显示背景图片
Column(
modifier = M
.fillMaxSize()
.padding(15.dp)
.background(Color.Transparent) // 确保内容背景透明
) {
content()
}
}
}
@Preview(showBackground = true)
@Composable
fun MyTextFieldPreview() {
MyTextField(
value = "Hello",
onValueChange = {})
}
@Composable
fun MyTextField(
modifier: Modifier = M,
value: String,
hint: String? = null,
maxLines: Int = 1,
fontSize: TextUnit = 16.sp,
fontColor: Color = Color(0xff333333),
maxLength: Int = Int.MAX_VALUE,
contentAlignment: Alignment.Vertical = Alignment.CenterVertically,
leading: (@Composable RowScope.() -> Unit)? = null,
trailing: (@Composable RowScope.() -> Unit)? = null,
background: BackgroundComposeWithTextField? = BackgroundComposeWithTextField.DEFAULT,
horizontalPadding: Dp = 10.dp,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = LocalTextStyle.current,
isNumberInputType: Boolean = false,
keyboardActions: KeyboardActions = KeyboardActions.Default,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
cursorBrush: Brush = SolidColor(Color.Black),
dateSelectTitle: String = "选择日期",
isSelectDate: Boolean = false,
onValueChange: (String) -> Unit = {},
) {
GoodTextField(
value = value,
onValueChange = onValueChange,
modifier = modifier
.height(35.dp)
.background(color = MyColors.White)
.noVisualFeedbackClickable {
if (isSelectDate) {
Toasty.openDatePickerDrawer(dateSelectTitle) {
onValueChange(it.toString().replace("T", " "))
}
}
},
hint = hint?.let { HintComposeWithTextField.createTextHintCompose(it) },
maxLines = maxLines,
fontSize = fontSize,
fontColor = if (readOnly) MyColors.Gray else fontColor,
maxLength = maxLength,
contentAlignment = contentAlignment,
leading = leading,
trailing = trailing,
background = background,
horizontalPadding = horizontalPadding,
enabled = if (isSelectDate) false else enabled,
readOnly = readOnly,
textStyle = textStyle,
keyboardOptions = KeyboardOptions(keyboardType = if (isNumberInputType) KeyboardType.Number else KeyboardType.Text),
keyboardActions = keyboardActions,
visualTransformation = visualTransformation,
onTextLayout = onTextLayout,
interactionSource = interactionSource,
cursorBrush = cursorBrush
)
}
@Preview(showBackground = true)
@Composable
fun VipBadgePreview() {
VipBadge {
MyButton(text = "Hello") {
}
}
}
@Composable
fun VipBadge(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
Box(modifier = modifier) {
// 内容显示区域
content()
// 显示 Badge
Box(
modifier = M
.align(Alignment.TopEnd) // 控制Badge的位置
.padding(2.5.dp) // 适当的内边距,避免和内容重叠
) {
// Badge(containerColor = MyColors.Transparent) {
Image(
painter = painterResource(id = R.drawable.vip),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.size(20.dp)
)
// }
}
}
}
@Composable
fun RedPointBadge(content: @Composable () -> Unit) {
Box {
// 内容显示区域
content()
Box(
modifier = M
.align(Alignment.TopEnd) // 控制Badge的位置
.padding(5.dp) // 适当的内边距,避免和内容重叠
) {
Box(
modifier = M
.size(6.dp) // 调整位置到右上角
.background(MyColors.Red, shape = MaterialTheme.shapes.small)
.align(Alignment.TopEnd),
)
}
}
}
@Composable
fun MyAnimatedVisibility(
visible: Boolean,
modifier: Modifier = M,
enter: EnterTransition = fadeIn(),
exit: ExitTransition = fadeOut(),
label: String = "AnimatedVisibility",
content: @Composable AnimatedVisibilityScope.() -> Unit
) {
AnimatedVisibility(
visible = visible,
modifier = modifier,
enter = enter,
exit = exit,
label = label,
content = content
)
}
@Composable
fun MyAnimatedVisibilityFromDownToUp(
visible: Boolean,
modifier: Modifier = M,
enter: EnterTransition = expandVertically(expandFrom = Alignment.Bottom),
exit: ExitTransition = fadeOut(),
label: String = "AnimatedVisibility",
content: @Composable AnimatedVisibilityScope.() -> Unit
) {
AnimatedVisibility(
visible = visible,
modifier = modifier,
enter = enter,
exit = exit,
label = label,
content = content
)
}
@Composable
fun MyOutlineButton(
modifier: Modifier = M,
text: String,
isImportance: Boolean = false,
onClick: () -> Unit
) {
OutlinedButton(
onClick = onClick,
border = BorderStroke(1.dp, if (isImportance) MyColors.Red else MyColors.BlueGreen),
contentPadding = PaddingValues(0.dp),
modifier = modifier.height(20.dp)
) {
Text(
modifier = M.padding(horizontal = 5.dp),
text = text,
color = if (isImportance) MyColors.Red else MyColors.BlueGreen
)
}
}
@Composable
fun QueryTextField(
modifier: Modifier = M,
text: String,
hint: String = "搜索信息",
onValueChange: (String) -> Unit
) {
MyTextField(
modifier = modifier.height(35.dp),
value = text,
hint = hint,
horizontalPadding = 5.dp,
leading = {
Icon(
imageVector = Icons.Default.Search,
contentDescription = "Search Icon",
tint = Color.Gray
)
},
trailing = {
if (text.isNotEmpty()) {
IconButton(onClick = {
// 清空输入框
onValueChange("")
}) {
Image(
// painter = painterResource(id = R.drawable.check_more),
Icons.Filled.Clear,
contentDescription = "Check More",
modifier = M.size(24.dp)
)
}
}
}, onValueChange = onValueChange
)
}
@Composable
fun DateRangePickTextFiled(
modifier: Modifier = M,
dateRange: Pair<Date, Date>,
onClick: () -> Unit
) {
GoodTextField(
modifier = modifier
.background(color = MyColors.White)
.clickable(onClick = {
onClick()
})
.width(200.dp)
.height(35.dp),
value = SimpleDateFormat("yyyy-M-d", Locale.getDefault()).format(
dateRange.first
) + " ~ " + SimpleDateFormat("yyyy-M-d", Locale.getDefault()).format(
dateRange.second
),
onValueChange = {},
horizontalPadding = 5.dp,
enabled = false,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
leading = {
Icon(
imageVector = Icons.Default.CalendarMonth,
contentDescription = "Calendar Icon",
tint = Color.Gray
)
}
)
// DateRangePickerModal(
// showDialog = datePickerDialog,
// onDateRangeSelected = { dateRange ->
// if (dateRange.first != null && dateRange.second != null) {
// queryDateRange = Pair(Date(dateRange.first!!), Date(dateRange.second!!))
// onDateChanged(queryDateRange)
// }
// },
// onDismiss = { datePickerDialog = false }
// )
}
@Composable
fun InfoText(title: String, content: String, modifier: Modifier = M, forceShow: Boolean = false) {
if (content.isNotEmpty() || forceShow) {
Row(
modifier = modifier.padding(vertical = 3.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = title,
color = MyColors.Gray,
fontSize = MaterialTheme.typography.bodyMedium.fontSize
)
Text(
modifier = M
.weight(1f)
.padding(horizontal = 5.dp),
text = content,
maxLines = 10,
fontSize = MaterialTheme.typography.bodyMedium.fontSize
)
}
}
}
@Composable
fun VerticalTabs(
modifier: Modifier = M,
textModifier: Modifier = M,
tabs: List<String>,
selectedTab: Int,
onTabSelected: (Int) -> Unit
) {
LazyColumn(modifier = modifier) {
item {
tabs.forEachIndexed() { index, tab ->
Row(
modifier = M
.animateItem()
.clickable {
onTabSelected(index)
}
.background(color = if (index == selectedTab) MyColors.LightGray else MyColors.Transparent),
verticalAlignment = Alignment.CenterVertically
) {
VerticalDivider(
modifier = M
.width(10.dp)
.height(30.dp),
color = if (index == selectedTab) MyColors.BlueGreen else MyColors.Transparent
)
Text(
modifier = textModifier
.padding(
start = 15.dp, top = 15.dp, bottom = 15.dp
)
.width(100.dp),
text = tab,
fontWeight = if (index == selectedTab) FontWeight.Bold else FontWeight.Normal,
color = if (index == selectedTab) MyColors.BlueGreen else MyColors.Black,
fontSize = MaterialTheme.typography.bodyMedium.fontSize
)
}
}
}
}
}
@Composable
fun VerticalTabPages(
modifier: Modifier = M,
textModifier: Modifier = M,
tabs: List<String>,
onTabSelected: @Composable (Int) -> Unit
) {
var tabSelected by rememberSaveable { mutableStateOf(0) }
Row {
VerticalTabs(
modifier = modifier,
textModifier = textModifier,
tabs = tabs,
selectedTab = tabSelected,
onTabSelected = {
tabSelected = it
}
)
VerticalDivider()
Box(
modifier = M
.padding(horizontal = 10.dp)
.fillMaxWidth()
) {
onTabSelected(tabSelected)
}
}
}
@Composable
fun UserBaseInfo(
name: String,
phone: String,
address: String,
idCard: String,
payCard: String,
payCardAddress: String = "",
modifier: Modifier = M,
) {
Column(modifier = modifier) {
Row(verticalAlignment = Alignment.CenterVertically) {
Image(
painter = painterResource(R.drawable.icon_user),
contentDescription = null,
contentScale = ContentScale.FillBounds,
modifier = M
.size(35.dp)
.padding(5.dp)
)
Text(
text = name,
fontSize = MaterialTheme.typography.bodyLarge.fontSize,
fontWeight = FontWeight.Bold
)
Spacer(modifier = M.weight(1f))
Image(
painter = painterResource(R.drawable.icon_tel),
contentDescription = null,
contentScale = ContentScale.FillBounds,
modifier = M.size(20.dp)
)
Text(
text = phone,
fontSize = MaterialTheme.typography.bodyLarge.fontSize,
fontWeight = FontWeight.Bold,
color = MyColors.BlueGreen
)
}
IconInfo(R.drawable.icon_address, address)
IconInfo(R.drawable.icon_idcard, idCard)
IconInfo(R.drawable.icon_bankcard, payCard)
if (payCardAddress != "") {
InfoText("所属银行", payCardAddress)
}
}
}
@Composable
fun EasySelect(
modifier: Modifier,
items: List<String>,
onlyNumber: Boolean = false,
canInput: Boolean = true,
onValueChanged: (String) -> Unit
) {
var value by rememberSaveable { mutableStateOf("") }
LazyRow(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
item {
if (items.isEmpty()) {
Text(
text = "暂无数据",
color = MyColors.Black,
fontSize = MaterialTheme.typography.bodyMedium.fontSize
)
}
}
items(items) {
Box(
modifier = M
.clickable {
value = it
onValueChanged(it)
}
.background(color = if (value == it) MyColors.BlueGreen else MyColors.White)
.border(1.dp, MyColors.Gray)
) {
Text(
text = it,
modifier = M
.padding(horizontal = 10.dp, vertical = 5.dp),
color = if (value == it) MyColors.White else MyColors.Black,
fontSize = MaterialTheme.typography.bodyMedium.fontSize
)
}
}
item {
if (canInput) {
MyTextField(
modifier = M
.width(100.dp)
.padding(horizontal = 10.dp),
value = value,
isNumberInputType = true,
onValueChange = {
value = it
onValueChanged(it)
}
)
}
}
}
}
@Composable
fun MyCheckBox(
title: String,
value: Boolean = true,
modifier: Modifier = M,
onValueChange: (Boolean) -> Unit = {}
) {
Row(
modifier
.wrapContentWidth()
.toggleable(
value = value,
onValueChange = {
onValueChange(!value)
},
role = Role.Checkbox
),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(
colors = CheckboxDefaults.colors(
checkedColor = MyColors.BlueGreen
),
checked = value,
onCheckedChange = {
onValueChange(!value)
}
)
Text(
text = title,
style = MaterialTheme.typography.bodyMedium,
modifier = M.padding(start = 10.dp)
)
}
}
@Composable
fun isLandscape(): Boolean {
val configuration = LocalConfiguration.current
return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
}
fun isBluetoothEnabled(): Boolean {
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
return bluetoothAdapter?.isEnabled == true
}
/**
* 自定义点击事件
* 不使用clickable的点击效果
*/
fun Modifier.noVisualFeedbackClickable(
onClick: () -> Unit
): Modifier {
return this.pointerInput(Unit) {
detectTapGestures(
onTap = {
onClick()
}
)
}
}
@Composable
fun MyTabRowHorizontal(
tabs: List<String>,
onTabSelected: @Composable (Int) -> Unit
) {
var curPage by rememberSaveable { mutableStateOf(0) }
Column {
TabRow(
selectedTabIndex = curPage,
indicator = { tabPositions ->
TabRowDefaults.Indicator(
M.tabIndicatorOffset(tabPositions[curPage]),
color = MyColors.BlueGreen
)
}
) {
tabs.forEachIndexed { index, title ->
Tab(
text = {
Text(
title,
color = if (curPage == index) MyColors.BlueGreen else MyColors.Black,
fontWeight = if (curPage == index) FontWeight.Bold else FontWeight.Normal,
fontSize = 18.sp
)
},
selected = curPage == index,
onClick = {
curPage = index
}
)
}
}
// HorizontalPager(
// state = pagerState,
// beyondViewportPageCount = tabs.size,
// modifier = M
// .fillMaxSize()
// .weight(1f)
// ) { page ->
// Column(
// modifier = M.fillMaxWidth(),
// horizontalAlignment = Alignment.CenterHorizontally
// ) {
// onTabSelected(page)
// }
// }
Column(
modifier = M.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
onTabSelected(curPage)
}
// HorizontalPager(
// state = pagerState,
// beyondViewportPageCount = tabs.size,
// modifier = Modifier
// .fillMaxSize()
// .weight(1f)
// ) { page ->
// Column(
// modifier = M.fillMaxWidth(),
// horizontalAlignment = Alignment.CenterHorizontally
// ) {
// onTabSelected(page)
// }
// }
}
}
@Composable
fun MyScrollableTabRow(
moidifer: Modifier = Modifier,
position: Int,
tabs: List<String>,
onValueChange: (Int) -> Unit = {}
) {
ScrollableTabRow(
selectedTabIndex = position,
containerColor = MyColors.Transparent,
edgePadding = 5.dp,
modifier = moidifer,
indicator = { tabPositions ->
TabRowDefaults.SecondaryIndicator(
M.tabIndicatorOffset(tabPositions[position]),
color = MyColors.BlueGreen,
)
}
) {
tabs.forEachIndexed { index, title ->
Tab(
text = {
Text(
title,
color = if (position == index) MyColors.BlueGreen else MyColors.Black,
fontWeight = if (position == index) FontWeight.Bold else FontWeight.Normal,
fontSize = MaterialTheme.typography.bodyLarge.fontSize
)
},
selected = position == index,
onClick = {
onValueChange(index)
}
)
}
}
}
@Composable
fun AssistChipFilter(
title: String,
content: String,
onClick: (String) -> Unit = {},
deleteEnable: Boolean = true,
) {
if (content.isNotEmpty()) {
AssistChip(
modifier = M.padding(horizontal = 10.dp),
onClick = { onClick("") },
label = { Text(title + content) },
trailingIcon = {
if (deleteEnable) {
Icon(
Icons.Default.Close,
contentDescription = null,
M.size(InputChipDefaults.AvatarSize)
)
}
},
)
}
}
@@ -0,0 +1,18 @@
package com.bbitcn.f8.pad.model
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
class ParameterizedTypeImpl(private var clazz: Class<*>) : ParameterizedType {
override fun getActualTypeArguments(): Array<Type> {
return arrayOf(clazz)
}
override fun getRawType(): Type {
return MutableList::class.java
}
override fun getOwnerType(): Type? {
return null
}
}
@@ -0,0 +1,26 @@
package com.bbitcn.f8.pad.model.net.request
import com.bbitcn.f8.pad.utils.TimeUtils
import com.google.gson.annotations.SerializedName
data class AddDryAirRequest(
@SerializedName("cjsysid")
var cjsysid: String = "",
@SerializedName("gjckcode")
var gjckcode: String = "",
@SerializedName("gjcksysid")
var gjcksysid: String = "",
@SerializedName("jiantype")
var jiantype: String = "",
@SerializedName("jiantypesysid")
var jiantypesysid: String = "",
@SerializedName("plantime")
var plantime: String = TimeUtils.getStringTime(),
@SerializedName("tanliangren")
var tanliangren: String = "",
@SerializedName("canpinzhong")
var canpinzhong: String = "",
@SerializedName("xiangzhen")
var xiangzhen: String = "",
)
@@ -0,0 +1,38 @@
package com.bbitcn.f8.pad.model.net.request
import com.bbitcn.f8.pad.utils.MyUtil
import com.bbitcn.f8.pad.utils.TimeUtils
import com.google.gson.annotations.SerializedName
data class AddDryInRequest(
@SerializedName("bagtype")
var bagtype: String = "",
@SerializedName("bagzhongliang")
var bagzhongliang: Double = 0.0,
@SerializedName("canpinzhong")
var canpinzhong: String = "",
@SerializedName("cjsysid")
var cjsysid: String = "",
@SerializedName("codegeneralmodel")
var codegeneralmodel: Int = 0,
@SerializedName("gjckcode")
var gjckcode: String = "",
@SerializedName("gjcksysid")
var gjcksysid: String = "",
@SerializedName("hongjianren")
var hongjianren: String = "",
@SerializedName("jiantype")
var jiantype: String = "",
@SerializedName("jiantypesysid")
var jiantypesysid: String = "",
@SerializedName("rkdatetime")
var rkdatetime: String = TimeUtils.getStringTime(),
@SerializedName("rukuren")
var rukuren: String = "",
@SerializedName("xiangzhen")
var xiangzhen: String = "",
@SerializedName("rukutype")
var rukutype: Int = -1, //入库类型 0:烘茧入库 1:翻包摊晾 2:出库盈余
@SerializedName("standardtype")
var standardtype: Int = 0
)
@@ -0,0 +1,39 @@
package com.bbitcn.f8.pad.model.net.request
import com.bbitcn.f8.pad.utils.MyUtil
import com.bbitcn.f8.pad.utils.TimeUtils
import com.google.gson.annotations.SerializedName
data class AddDryOutRequest(
@SerializedName("bagtype")
var bagtype: String = "",
@SerializedName("bagzhongliang")
var bagzhongliang: Double = 0.0,
@SerializedName("canpinzhong")
var canpinzhong: String = "",
@SerializedName("carpaihao")
var carpaihao: String = "",
@SerializedName("chukuren")
var chukuren: String = "",
@SerializedName("cjsysid")
var cjsysid: String = "",
@SerializedName("ckdatetime")
var ckdatetime: String = TimeUtils.getStringTime(),
@SerializedName("codegeneratemodel")
var codegeneratemodel: Int = 0,
@SerializedName("gjckcode")
var gjckcode: String = "",
@SerializedName("gjcksysid")
var gjcksysid: String = "",
@SerializedName("jiantype")
var jiantype: String = "",
@SerializedName("jiantypesysid")
var jiantypesysid: String = "",
@SerializedName("memo")
var memo: String = "",
@SerializedName("tihuoren")
var tihuoren: String = "",
@SerializedName("xiangzhen")
var xiangzhen: String = "",
@SerializedName("wldwsysid")
var wldwsysid: String = ""
)
@@ -0,0 +1,52 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class AddFarmerRequest(
@SerializedName("BankCode")
val bankCode: String = "",
@SerializedName("BankCode2")
val bankCode2: String = "",
@SerializedName("BankName")
val bankName: String = "",
@SerializedName("BankName2")
val bankName2: String = "",
@SerializedName("BankShortName")
val bankShortName: String = "",
@SerializedName("BankShortName2")
val bankShortName2: String = "",
@SerializedName("Cun")
val cun: String = "",
@SerializedName("DepartmentSysid")
val departmentSysid: String = "",
@SerializedName("IcCardCode")
val icCardCode: Long = 0,
@SerializedName("IdCard")
val idCard: String = "",
@SerializedName("IdCardAddress")
val idCardAddress: String = "",
@SerializedName("NhName")
val nhName: String = "",
@SerializedName("NhTips")
val nhTips: String = "",
@SerializedName("Phone")
val phone: String = "",
@SerializedName("PropertyName")
val propertyName: String = "",
@SerializedName("PropertySysid")
val propertySysid: String = "",
@SerializedName("RecBankCode")
val recBankCode: String = "",
@SerializedName("RecBankCode2")
val recBankCode2: String = "",
@SerializedName("Sex")
val sex: String = "",
@SerializedName("Sysid")
val sysid: String = "",
@SerializedName("Xian")
val xian: String = "",
@SerializedName("Xiang")
val xiang: String = "",
@SerializedName("Zu")
val zu: String = ""
)
@@ -0,0 +1,37 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class AddUserRequest(
@SerializedName("DepartmentSysid")
val departmentSysid: String = "",
@SerializedName("ICCardId")
val iCCardId: Int = 0,
@SerializedName("UserNew")
val userNew: UserNew = UserNew(),
@SerializedName("UserRole")
val userRole: List<String> = listOf()
) {
data class UserNew(
@SerializedName("Cun")
val cun: String = "",
@SerializedName("ICCardId")
val iCCardId: Int = 0,
@SerializedName("IdCard")
val idCard: String = "",
@SerializedName("LoginName")
val loginName: String = "",
@SerializedName("Memo")
val memo: String = "",
@SerializedName("Name")
val name: String = "",
@SerializedName("Sex")
val sex: Boolean = false,
@SerializedName("Sort")
val sort: Int = 0,
@SerializedName("Tel")
val tel: String = "",
@SerializedName("Xiang")
val xiang: String = ""
)
}
@@ -0,0 +1,20 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class AuthDevice(
@SerializedName("Applicant")
val applicant: String = "",
@SerializedName("HardwareId")
val hardwareId: String = "",
@SerializedName("Job")
val job: String = "",
@SerializedName("Memo")
val memo: String = "",
@SerializedName("Phone")
val phone: String = "",
@SerializedName("Pwd")
val pwd: String = "",
@SerializedName("TenantCode")
val tenantCode: String = ""
)
@@ -0,0 +1,13 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class ChatMessageRequest(
@SerializedName("question")
val question: String = "",
@SerializedName("session_id")
val sessionId: String = "",
@SerializedName("stream")
val stream: Boolean = false
)
@@ -0,0 +1,15 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class CocoonTypeTranslateRequest(
@SerializedName("czsysid")
val czsysid: String = "",
@SerializedName("newname")
val newname: String = "",
@SerializedName("newsysid")
val newsysid: String = "",
@SerializedName("oldname")
val oldname: String = "",
@SerializedName("oldsysid")
val oldsysid: String = ""
)
@@ -0,0 +1,10 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DateRangeRequest(
@SerializedName("startdate")
val startdate: String = "",
@SerializedName("endate")
val endate: String = "",
)
@@ -0,0 +1,8 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DeleteUserRequest(
@SerializedName("Id")
val id: Long = 0
)
@@ -0,0 +1,7 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DryCocoonAirDetailListRequest(
@SerializedName("tlsysid")
val tlsysid: String = ""
)
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DryCocoonAirListRequest(
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("endtime")
val endtime: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("like")
val like: String = "",
@SerializedName("starttime")
val starttime: String = ""
)
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DryCocoonOutListRequest(
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("endtime")
val endtime: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("like")
val like: String = "",
@SerializedName("starttime")
val starttime: String = ""
)
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.bbitcn.f8.pad.utils.MyUtil
import com.bbitcn.f8.pad.utils.TimeUtils
import com.google.gson.annotations.SerializedName
data class DryCocoonPackageForOutLossRequest(
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("ckdsysid")
val ckdsysid: String = "",
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("time")
val time: String = ""
)
@@ -0,0 +1,13 @@
package com.bbitcn.f8.pad.model.net.request
import com.bbitcn.f8.pad.utils.MyUtil
import com.google.gson.annotations.SerializedName
data class DryCocoonPackageLossRequest(
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("time")
val time: String = "",
@SerializedName("tlsysid")
val tlsysid: String = ""
)
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DryCocoonQueryListRequest(
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("endtime")
val endtime: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("like")
val like: String = "",
@SerializedName("starttime")
val starttime: String = ""
)
@@ -0,0 +1,20 @@
package com.bbitcn.f8.pad.model.net.request
import com.bbitcn.f8.pad.utils.MyUtil
import com.bbitcn.f8.pad.utils.TimeUtils
import com.google.gson.annotations.SerializedName
data class DryCocoonRefreshStartRequest(
@SerializedName("code")
val code: String = "",
@SerializedName("kcmaozhong")
val kcmaozhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: String = "",
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("rkitemsysid")
val rkitemsysid: String = "",
@SerializedName("time")
val time: String = TimeUtils.getStringTime(),
)
@@ -0,0 +1,14 @@
package com.bbitcn.f8.pad.model.net.request
import com.bbitcn.f8.pad.utils.MyUtil
import com.bbitcn.f8.pad.utils.TimeUtils
import com.google.gson.annotations.SerializedName
data class DryCocoonRefreshStopRequest(
@SerializedName("maozhong")
val maozhong: String = "",
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("time")
val time: String = TimeUtils.getStringTime(),
)
@@ -0,0 +1,22 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DryCocoonSaveInDetailRequest(
@SerializedName("baoshu")
val baoshu: Int = 0,
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("codegeneratemodel")
val codegeneratemodel: Int = 0,
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("pizhong")
val pizhong: Double = 0.0,
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("rksysid")
val rksysid: String = ""
)
@@ -0,0 +1,18 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DryCocoonSaveNewOutDetail(
@SerializedName("baoshu")
val baoshu: Int = 1,
@SerializedName("cksysid")
val cksysid: String = "",
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("pizhong")
val pizhong: Double = 0.0,
@SerializedName("rfid")
val rfid: String = ""
)
@@ -0,0 +1,20 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DryCocoonSaveOutDetail(
@SerializedName("baoshu")
val baoshu: Int = 1,
@SerializedName("cksysid")
val cksysid: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("pizhong")
val pizhong: Double = 0.0
)
@@ -0,0 +1,9 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class DryCocoonStoreDetailListRequest(
@SerializedName("tlsysid")
val tlsysid: String = "",
@SerializedName("tlsysid")
val like: String = ""
)
@@ -0,0 +1,14 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class EditPasswordRequest(
@SerializedName("newpwd")
val newpwd: String = "",
@SerializedName("phone")
val phone: String = "",
@SerializedName("smsbucket")
val smsbucket: String = "",
@SerializedName("smscode")
val smscode: String = ""
)
@@ -0,0 +1,13 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class FaceRecognizeRequest(
@SerializedName("group_id_list")
val group_id_list: String = "",
@SerializedName("image")
val image: String = "",
@SerializedName("image_type")
val image_type: String = "BASE64",
)
@@ -0,0 +1,17 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class FaceRegisterF8Request(
@SerializedName("baidu_face_token")
val baiduFaceToken: String = "",
@SerializedName("oss_bucketname")
val ossBucketname: String = "",
@SerializedName("oss_objectname")
val ossObjectname: String = "",
@SerializedName("userid")
val userid: String = "",
@SerializedName("usertype")
val usertype: Int = 0
)
@@ -0,0 +1,17 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class FaceRegisterRequest(
@SerializedName("group_id")
val group_id: String = "",
@SerializedName("image")
val image: String = "",
@SerializedName("image_type")
val image_type: String = "BASE64",
@SerializedName("user_id")
val user_id: String = "",
@SerializedName("quality_control")
val quality_control: String = "NORMAL",
)
@@ -0,0 +1,18 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class ForgetPasswordRequest(
@SerializedName("hardwareid")
val hardwareid: String = "",
@SerializedName("newpwd")
val newpwd: String = "",
@SerializedName("phone")
val phone: String = "",
@SerializedName("smsbucket")
val smsbucket: String = "",
@SerializedName("smscode")
val smscode: String = "",
@SerializedName("tenantcode")
val tenantcode: String = ""
)
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class FundsRequest(
@SerializedName("BegDate")
val begDate: String = "",
@SerializedName("DepSysid")
val depSysid: String = "",
@SerializedName("EndData")
val endData: String = "",
@SerializedName("Like")
val like: String = "",
@SerializedName("SearchType")
val searchType: String = ""
)
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class FundsTotalListRequest(
@SerializedName("BegDate")
val begDate: String = "",
@SerializedName("DepSysid")
val depSysid: String = "",
@SerializedName("EndData")
val endData: String = "",
@SerializedName("Like")
val like: String = "",
@SerializedName("SearchType")
val searchType: String = "0"
)
@@ -0,0 +1,14 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class LoginByFaceRequest(
@SerializedName("hardwareid")
val hardwareid: String = "",
@SerializedName("tenantcode")
val tenantcode: String = "",
@SerializedName("facetoken")
val facetoken: String = "",
@SerializedName("userid")
val userid: String = ""
)
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class LoginPhoneRequest(
@SerializedName("hardwareid")
val hardwareid: String = "",
@SerializedName("phone")
val phone: String = "",
@SerializedName("smsbucket")
val smsbucket: String = "",
@SerializedName("smscode")
val smscode: String = "",
@SerializedName("tenantcode")
val tenantcode: String = ""
)
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class LoginRequest(
@SerializedName("account")
val account: String = "",
@SerializedName("hardwareid")
val hardwareid: String = "",
@SerializedName("password")
val password: String = "",
@SerializedName("tenantcode")
val tenantcode: String = ""
)
@@ -0,0 +1,11 @@
package com.bbitcn.f8.pad.model.net.request
data class PageInfo(
val page: Int = 1,
val limit: Int = 30,
val orderby: String = ""
) {
fun toJson(): String {
return "{\"page\":$page,\"limit\":$limit,\"orderby\":\"$orderby\"}"
}
}
@@ -0,0 +1,18 @@
package com.bbitcn.f8.pad.model.net.request
import com.bbitcn.f8.pad.utils.MMKVUtil
import com.bbitcn.f8.pad.utils.global.Global
import com.google.gson.annotations.SerializedName
data class PurchaseDataRequest(
@SerializedName("BegDate")
val begDate: String = "",
@SerializedName("DepSysid")
val depSysid: String = MMKVUtil.get(Global.DEP_SYS_ID),
@SerializedName("EndData")
val endData: String = "",
@SerializedName("Like")
val like: String = "",
@SerializedName("sgSearchState")
val sgSearchState: String = ""
)
@@ -0,0 +1,12 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class RefreshTokenRequest(
@SerializedName("hardwareid")
val hardwareid: String = "",
@SerializedName("ref_token")
val refToken: String = "",
@SerializedName("token")
val token: String = ""
)
@@ -0,0 +1,23 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
class SaveExtendInfoRequest(items: List<SaveExtendInfoRequestItem>) :
ArrayList<SaveExtendInfoRequest.SaveExtendInfoRequestItem>(items) {
data class SaveExtendInfoRequestItem(
@SerializedName("colname")
val colname: String = "",
@SerializedName("colsysid")
val colsysid: String = "",
@SerializedName("coltitle")
val coltitle: String = "",
@SerializedName("colvalue")
val colvalue: String = "",
@SerializedName("extendsysid")
val extendsysid: String = "",
@SerializedName("nhsysid")
val nhsysid: String = ""
)
}
@@ -0,0 +1,47 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class SaveWeightDetailRequest(
@SerializedName("BoxCount")
val boxCount: Int = 0,
@SerializedName("BoxName")
val boxName: String = "",
@SerializedName("BoxSysid")
val boxSysid: String = "",
@SerializedName("CarCode")
val carCode: Int = 0,
@SerializedName("CarWeight")
val carWeight: Double = 0.0,
@SerializedName("ChengIndex")
val chengIndex: Int = 0,
@SerializedName("CzItemSysid")
val czItemSysid: String = "",
@SerializedName("CzSysid")
val czSysid: String = "",
@SerializedName("HsRatio")
val hsRatio: Int = 0,
@SerializedName("HsValue")
val hsValue: Int = 0,
@SerializedName("ItemMoney")
val itemMoney: Int = 0,
@SerializedName("Jweight")
val jweight: Double = 0.0,
@SerializedName("Kweight")
val kweight: Double = 0.0,
@SerializedName("Mweight")
val mweight: Double = 0.0,
@SerializedName("NhSysid")
val nhSysid: String = "",
@SerializedName("Price")
val price: Double = 0.0,
@SerializedName("Pweight")
val pweight: Double = 0.0,
@SerializedName("SgTypeId")
val sgTypeId: Int = 0,
@SerializedName("SgTypeName")
val sgTypeName: String = "",
@SerializedName("SgTypeSysid")
val sgTypeSysid: String = "",
@SerializedName("WeiShuValue")
val weiShuValue: Int = 0
)
@@ -0,0 +1,43 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class SaveWeightTicketRequest(
@SerializedName("BatchCjSysid")
val batchCjSysid: String = "",
@SerializedName("CzSysid")
val czSysid: String = "",
@SerializedName("DepCode")
val depCode: String = "",
@SerializedName("DepSysid")
val depSysid: String = "",
@SerializedName("Extention")
val extention: Extention = Extention(),
@SerializedName("Gsysid")
val gsysid: String = "",
@SerializedName("GyhSysid")
val gyhSysid: String = "",
@SerializedName("InoputDataList")
val inoputDataList: List<InoputData> = listOf(),
@SerializedName("NhSysid")
val nhSysid: String = "",
@SerializedName("YpState")
val ypState: String = ""
) {
data class Extention(
@SerializedName("czsysid")
val czsysid: String = "",
@SerializedName("validhanshuicishu")
val validhanshuicishu: Int = 0,
@SerializedName("validhanshuilv")
val validhanshuilv: String = ""
)
data class InoputData(
@SerializedName("InputName")
val inputName: String = "",
@SerializedName("InputSysid")
val inputSysid: String = "",
@SerializedName("InputValue")
val inputValue: Int = 0 // 这里虽然理论上是Any 但实际上各个值都可以用int表示 例如:【是否方格簇-1表示没有选择,1是,0否】,【色泽1上、0中、-1下】 【含水率 也是数字】
)
}
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class SearchOutDetailByRFIDRequest(
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("jiantypesysid")
val jiantypesysid: String = "",
@SerializedName("rfid")
val rfid: String = ""
)
@@ -0,0 +1,9 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class SeedInfoRequest(
@SerializedName("CjSysid")
val cjSysid: String = "",
@SerializedName("NhSysid")
val nhSysid: String = ""
)
@@ -0,0 +1,14 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class SendCodeRequest(
@SerializedName("expired")
val expired: Int = 10,
@SerializedName("smsbucket")
val smsbucket: String = "",
@SerializedName("tel")
val tel: String = ""
)
@@ -0,0 +1,18 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class SetUserListRequest(
@SerializedName("DepSysid")
val depSysid: String = "",
@SerializedName("Like")
val like: String = "",
/**
* 查询用户类型
* 全部用户=0,
* 有效用户=1,
* 冻结用户=2,
*/
@SerializedName("SearchUserType")
val searchUserType: String = "0"//
)
@@ -0,0 +1,14 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class StatisticsRequest(
@SerializedName("endate")
val endate: String = "",
@SerializedName("like")
val like: String = "",
@SerializedName("sgtypesysid")
val sgtypesysid: String = "",
@SerializedName("startdate")
val startdate: String = ""
)
@@ -0,0 +1,22 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class TareRequest(
@SerializedName("CzSysid")
val czSysid: String = "",
@SerializedName("UpdateItemList")
val updateItemList: List<UpdateItem> = listOf()
) {
data class UpdateItem(
@SerializedName("Jweight")
var jweight: Double = 0.0,
@SerializedName("Kweight")
var kweight: Double = 0.0,
@SerializedName("Pweight")
var pweight: Double = 0.0,
@SerializedName("SgTypName")
val sgTypName: String = "",
@SerializedName("Sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,26 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class UpdateTicketPriceRequest(
@SerializedName("CzSysid")
val czSysid: String = "",
@SerializedName("UpdateList")
val updateList: List<Update> = listOf()
) {
data class Update(
@SerializedName("NewJweight")
val newJweight: Double = 0.0,
@SerializedName("NewKweight")
val newKweight: Double = 0.0,
@SerializedName("NewMoney")
var newMoney: Double = 0.0,
@SerializedName("NewPrice")
var newPrice: Double = 0.0,
@SerializedName("NewPweight")
val newPweight: Double = 0.0,
@SerializedName("Sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,36 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class UpdateUserRequest(
@SerializedName("DepartmentSysid")
val departmentSysid: String = "",
@SerializedName("UserNew")
val userNew: UserNew = UserNew(),
@SerializedName("UserRole")
val userRole: List<String> = listOf()
) {
data class UserNew(
@SerializedName("Cun")
val cun: String = "",
@SerializedName("ICCardId")
val iCCardId: Int = 0,
@SerializedName("Id")
val id: Long = 0,
@SerializedName("IdCard")
val idCard: String = "",
@SerializedName("LoginName")
val loginName: String = "",
@SerializedName("Memo")
val memo: String = "",
@SerializedName("Name")
val name: String = "",
@SerializedName("Sex")
val sex: Boolean = false,
@SerializedName("Sort")
val sort: Int = 0,
@SerializedName("Tel")
val tel: String = "",
@SerializedName("Xiang")
val xiang: String = ""
)
}
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class UserListDataRequest(
@SerializedName("Xian")
val xian: String = "",
@SerializedName("Xiang")
val xiang: String = "",
@SerializedName("Cun")
val cun: String = "",
@SerializedName("Zu")
val zu: String = "",
@SerializedName("Like")
val like: String = ""
)
@@ -0,0 +1,21 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class StartDryCocoonAirDetailRequest(
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("kcmaozhong")
val kcmaozhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("rkitemsysid")
val rkitemsysid: String = "",
@SerializedName("time")
val time: String = "",
@SerializedName("tlsysid")
val tlsysid: String = ""
)
@@ -0,0 +1,13 @@
package com.bbitcn.f8.pad.model.net.request
import com.google.gson.annotations.SerializedName
data class StopDryCocoonAirDetailRequest(
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("time")
val time: String = "",
@SerializedName("tlsysid")
val tlsysid: String = ""
)
@@ -0,0 +1,20 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class AboutResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("describe")
val describe: String = "",
@SerializedName("tenantname")
val tenantname: String = ""
)
}
@@ -0,0 +1,35 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class AllExtendInfoResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("coldroplist")
val coldroplist: String = "",
@SerializedName("colname")
val colname: String = "",
@SerializedName("colsysid")
val colsysid: String = "",
@SerializedName("coltitle")
val coltitle: String = "",
@SerializedName("coltype")
val coltype: Int = 0,
@SerializedName("colvalue")
val colvalue: String = "",
@SerializedName("extendsysid")
val extendsysid: String = "",
@SerializedName("isnotnull")
val isnotnull: Boolean = false,
@SerializedName("nhsysid")
val nhsysid: String = "",
@SerializedName("sort")
val sort: Int = 0
)
}
@@ -0,0 +1,84 @@
package com.bbitcn.f8.pad.model.net.response;
import com.google.gson.annotations.SerializedName;
/**
* @Description 应用版本-网络请求
* @Author DuanKaiji
* @CreateTime 2023年10月19日 16:06:36
*/
public class AppVersion {
@SerializedName("Code")
private int code;
@SerializedName("Message")
private String message;
@SerializedName("Data")
private DataDTO data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public DataDTO getData() {
return data;
}
public void setData(DataDTO data) {
this.data = data;
}
public static class DataDTO {
@SerializedName("VersionNumber")
private int versionNumber;
@SerializedName("VersionName")
private String versionName;
@SerializedName("VersionDescription")
private String versionDescription;
@SerializedName("Url")
private String url;
public int getVersionNumber() {
return versionNumber;
}
public void setVersionNumber(int versionNumber) {
this.versionNumber = versionNumber;
}
public String getVersionName() {
return versionName;
}
public void setVersionName(String versionName) {
this.versionName = versionName;
}
public String getVersionDescription() {
return versionDescription;
}
public void setVersionDescription(String versionDescription) {
this.versionDescription = versionDescription;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
}
@@ -0,0 +1,25 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class BankInfoResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("BankName")
val bankName: String = "",
@SerializedName("BankShortName")
val bankShortName: String = "",
@SerializedName("BankType")
val bankType: Int = 0,
@SerializedName("RecBankCode")
val recBankCode: String = "",
@SerializedName("Validated")
val validated: Boolean = false
)
}
@@ -0,0 +1,29 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class BoxInfoResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("IsVisible")
val isVisible: Boolean = false,
@SerializedName("MaxCount")
val maxCount: Int = 0,
@SerializedName("Memo")
val memo: String = "",
@SerializedName("Name")
val name: String = "",
@SerializedName("Sort")
val sort: Int = 0,
@SerializedName("Sysid")
val sysid: String = "",
@SerializedName("Weight")
val weight: Double = 0.0
)
}
@@ -0,0 +1,29 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class CarInfoResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("CarCode")
val carCode: Int = -1,
@SerializedName("CarWeight")
val carWeight: Double = 0.0,
@SerializedName("DepCode")
val depCode: String = "",
@SerializedName("DepSysid")
val depSysid: String = "",
@SerializedName("Memo")
val memo: String = "",
@SerializedName("Sort")
val sort: Int = 0,
@SerializedName("Sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,68 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class ChatMessageResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data()
) {
data class Data(
@SerializedName("answer")
val answer: String = "",
@SerializedName("audio_binary")
val audioBinary: Any? = null,
@SerializedName("id")
val id: String = "",
@SerializedName("prompt")
val prompt: String = "",
@SerializedName("reference")
val reference: Reference = Reference(),
@SerializedName("session_id")
val sessionId: String = ""
) {
data class Reference(
@SerializedName("chunks")
val chunks: List<Chunk> = listOf(),
@SerializedName("doc_aggs")
val docAggs: List<DocAgg> = listOf(),
@SerializedName("total")
val total: Int = 0
) {
data class Chunk(
@SerializedName("content")
val content: String = "",
@SerializedName("dataset_id")
val datasetId: String = "",
@SerializedName("document_id")
val documentId: String = "",
@SerializedName("document_name")
val documentName: String = "",
@SerializedName("id")
val id: String = "",
@SerializedName("image_id")
val imageId: String = "",
@SerializedName("positions")
val positions: List<List<Int>> = listOf(),
@SerializedName("similarity")
val similarity: Double = 0.0,
@SerializedName("term_similarity")
val termSimilarity: Double = 0.0,
@SerializedName("vector_similarity")
val vectorSimilarity: Double = 0.0
)
data class DocAgg(
@SerializedName("count")
val count: Int = 0,
@SerializedName("doc_id")
val docId: String = "",
@SerializedName("doc_name")
val docName: String = ""
)
}
}
}
@@ -0,0 +1,66 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class ChatMessageStreamResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("message")
val message: String = "",
@SerializedName("data")
val `data`: Data = Data()
) {
data class Data(
@SerializedName("answer")
val answer: String = "",
@SerializedName("id")
val id: String = "",
@SerializedName("prompt")
val prompt: String = "",
@SerializedName("reference")
val reference: Reference = Reference(),
@SerializedName("session_id")
val sessionId: String = ""
) {
data class Reference(
@SerializedName("chunks")
val chunks: List<Chunk> = listOf(),
@SerializedName("doc_aggs")
val docAggs: List<DocAgg> = listOf(),
@SerializedName("total")
val total: Int = 0
) {
data class Chunk(
@SerializedName("content")
val content: String = "",
@SerializedName("dataset_id")
val datasetId: String = "",
@SerializedName("document_id")
val documentId: String = "",
@SerializedName("document_name")
val documentName: String = "",
@SerializedName("id")
val id: String = "",
@SerializedName("image_id")
val imageId: String = "",
@SerializedName("positions")
val positions: List<List<Int>> = listOf(),
@SerializedName("similarity")
val similarity: Double = 0.0,
@SerializedName("term_similarity")
val termSimilarity: Double = 0.0,
@SerializedName("vector_similarity")
val vectorSimilarity: Double = 0.0
)
data class DocAgg(
@SerializedName("count")
val count: Int = 0,
@SerializedName("doc_id")
val docId: String = "",
@SerializedName("doc_name")
val docName: String = ""
)
}
}
}
@@ -0,0 +1,29 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class CheckUpdateResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("describe")
val describe: String = "",
@SerializedName("forceupdate")
val forceupdate: Int = 0,
@SerializedName("issuer")
val issuer: String = "",
@SerializedName("size")
val size: Double = 0.0,
@SerializedName("url")
val url: String = "",
@SerializedName("versionname")
val versionname: String = "",
@SerializedName("versionnumber")
val versionnumber: Int = 0
)
}
@@ -0,0 +1,58 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class CocoonInDetailResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("bagtype")
val bagtype: String = "",
@SerializedName("bagzhongliang")
val bagzhongliang: Double = 0.0,
@SerializedName("baoshu")
val baoshu: Int = 0,
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("cpzname")
val cpzname: String = "",
@SerializedName("datetime")
val datetime: String = "",
@SerializedName("depname")
val depname: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("hongjianren")
val hongjianren: String = "",
@SerializedName("jiantype")
val jiantype: String = "",
@SerializedName("jiantypesysid")
val jiantypesysid: String = "",
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("memo")
val memo: String = "",
@SerializedName("pizhong")
val pizhong: Double = 0.0,
@SerializedName("rukuren")
val rukuren: String = "",
@SerializedName("standardtype")
val standardtype: String = "",
@SerializedName("sysid")
val sysid: String = "",
@SerializedName("xiangzhen")
val xiangzhen: String = ""
)
}
@@ -0,0 +1,62 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class CocoonOutDetailResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("bagtype")
val bagtype: String = "",
@SerializedName("bagzhongliang")
val bagzhongliang: Double = 0.0,
@SerializedName("baoshu")
val baoshu: Int = 0,
@SerializedName("canpinzhong")
val canpinzhong: String = "",
@SerializedName("releasebaoshu")
val releasebaoshu: Int = 0,
@SerializedName("carpaihao")
val carpaihao: String = "",
@SerializedName("chukuren")
val chukuren: String = "",
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("ckdatetime")
val ckdatetime: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("jiantype")
val jiantype: String = "",
@SerializedName("jiantypesysid")
val jiantypesysid: String = "",
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("memo")
val memo: String = "",
@SerializedName("pizhong")
val pizhong: Double = 0.0,
@SerializedName("sysid")
val sysid: String = "",
@SerializedName("tihuoren")
val tihuoren: String = "",
@SerializedName("wldwname")
val wldwname: String = "",
@SerializedName("wldwsysid")
val wldwsysid: String = "",
@SerializedName("xiangzhen")
val xiangzhen: String = ""
)
}
@@ -0,0 +1,16 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
/**
* 通用网络请求
* Data值为唯一值的
*/
data class CommonResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Any = Any(),
@SerializedName("msg")
val msg: String = ""
)
@@ -0,0 +1,33 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DeviceResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("Applicant")
val applicant: String = "",
@SerializedName("ClientType")
val clientType: String = "",
@SerializedName("Flag")
val flag: Int = 0,
@SerializedName("HardwareId")
val hardwareId: String = "",
@SerializedName("Job")
val job: String = "",
@SerializedName("Memo")
val memo: String = "",
@SerializedName("Phone")
val phone: String = "",
@SerializedName("Sysid")
val sysid: String = "",
@SerializedName("TenantCode")
val tenantCode: String = ""
)
}
@@ -0,0 +1,33 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonAirDetailByRFIDResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("msg")
val msg: String = "",
@SerializedName("data")
val `data`: Data = Data()
) {
data class Data(
@SerializedName("bagtype")
val bagtype: String = "",
@SerializedName("bagzhongliang")
val bagzhongliang: Double = 0.0,
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("istanlianging")
val istanlianging: Int = 0,
@SerializedName("jiantypename")
val jiantypename: String = "",
@SerializedName("kcmaozhong")
val kcmaozhong: Double = 0.0,
@SerializedName("sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,41 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonAirDetailListResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("bagrelease")
val bagrelease: String = "",
@SerializedName("chayizhongliang")
val chayizhongliang: Double = 0.0,
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("endtime")
val endtime: String = "",
@SerializedName("fbendmaozhong")
val fbendmaozhong: Double = 0.0,
@SerializedName("fbstartmaozhong")
val fbstartmaozhong: Double = 0.0,
@SerializedName("jiantypename")
val jiantypename: String = "",
@SerializedName("kcmaozhong")
val kcmaozhong: Double = 0.0,
@SerializedName("starttime")
val starttime: String = "",
@SerializedName("status")
val status: String = "",
@SerializedName("sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,49 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonAirDetailResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("baoshu")
val baoshu: Int = 0,
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("endtime")
val endtime: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("jiantype")
val jiantype: String = "",
@SerializedName("canpinzhong")
val canpinzhong: String = "",
@SerializedName("xiangzhen")
val xiangzhen: String = "",
@SerializedName("jiantypesysid")
val jiantypesysid: String = "",
@SerializedName("memo")
val memo: String = "",
@SerializedName("plantime")
val plantime: String = "",
@SerializedName("releaseBaoshu")
val releaseBaoshu: Int = 0,
@SerializedName("startime")
val startime: String = "",
@SerializedName("sysid")
val sysid: String = "",
@SerializedName("tanliangingbaoshu")
val tanliangingbaoshu: Int = 0,
@SerializedName("tanliangren")
val tanliangren: String = ""
)
}
@@ -0,0 +1,43 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonAirListResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("baoshu")
val baoshu: Int = 0,
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("endtime")
val endtime: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("jiantype")
val jiantype: String = "",
@SerializedName("xiangzhen")
val xiangzhen: String = "",
@SerializedName("jiantypesysid")
val jiantypesysid: String = "",
@SerializedName("plantime")
val plantime: String = "",
@SerializedName("startime")
val startime: String = "",
@SerializedName("sysid")
val sysid: String = "",
@SerializedName("tanliangingbaoshu")
val tanliangingbaoshu: Int = 0,
@SerializedName("tanliangren")
val tanliangren: String = ""
)
}
@@ -0,0 +1,11 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonAreaResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<String> = listOf(),
@SerializedName("msg")
val msg: String = "",
)
@@ -0,0 +1,29 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonDealObjectResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("address")
val address: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("contact")
val contact: String = "",
@SerializedName("name")
val name: String = "",
@SerializedName("phone")
val phone: String = "",
@SerializedName("sort")
val sort: Int = 0,
@SerializedName("sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,29 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonInDetailResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("code")
val code: String = "",
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("pizhong")
val pizhong: Double = 0.0,
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("rksysid")
val rksysid: String = "",
@SerializedName("sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,23 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonInLevel(
@SerializedName("code")
val code: Int = 0,
@SerializedName("msg")
val msg: String = "",
@SerializedName("data")
val `data`: List<Data> = listOf()
) {
data class Data(
@SerializedName("name")
val name: String = "",
@SerializedName("sort")
val sort: Int = 0,
@SerializedName("type")
val type: Int = 0,//0:其他,1:正茧,2:下足茧
@SerializedName("sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,57 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonInListResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("bagtype")
val bagtype: String = "",
@SerializedName("bagzhongliang")
val bagzhongliang: Double = 0.0,
@SerializedName("baoshu")
val baoshu: Int = 0,
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("cpzname")
val cpzname: String = "",
@SerializedName("datetime")
val datetime: String = "",
@SerializedName("depname")
val depname: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("hongjianren")
val hongjianren: String = "",
@SerializedName("jiantype")
val jiantype: String = "",
@SerializedName("jiantypesysid")
val jiantypesysid: String = "",
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("pizhong")
val pizhong: Double = 0.0,
@SerializedName("rukuren")
val rukuren: String = "",
@SerializedName("standardtype")
val standardtype: String = "",
@SerializedName("sysid")
val sysid: String = "",
@SerializedName("xiangzhen")
val xiangzhen: String = ""
)
}
@@ -0,0 +1,23 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonInPackageType(
@SerializedName("code")
val code: Int = 0,
@SerializedName("msg")
val msg: String = "",
@SerializedName("data")
val `data`: List<Data> = listOf()
) {
data class Data(
@SerializedName("name")
val name: String = "",
@SerializedName("sort")
val sort: Int = 0,
@SerializedName("sysid")
val sysid: String = "",
@SerializedName("weight")
val weight: Double = 0.0
)
}
@@ -0,0 +1,24 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonInStatisticsResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("total_baoshu")
val totalBaoshu: Int = 0,
@SerializedName("total_jingzhong")
val totalJingzhong: Double = 0.0,
@SerializedName("total_maozhong")
val totalMaozhong: Double = 0.0,
@SerializedName("total_num")
val totalNum: Int = 0,
@SerializedName("total_pizhong")
val totalPizhong: Double = 0.0
)
}
@@ -0,0 +1,27 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonInStore(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("cangkucode")
val cangkucode: String = "",
@SerializedName("cangkuname")
val cangkuname: String = "",
@SerializedName("depname")
val depname: String = "",
@SerializedName("depsysid")
val depsysid: String = "",
@SerializedName("sort")
val sort: Int = 0,
@SerializedName("sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,21 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonInType(
@SerializedName("code")
val code: Int = 0,
@SerializedName("msg")
val msg: String = "",
@SerializedName("data")
val `data`: List<Data> = listOf()
) {
data class Data(
@SerializedName("name")
val name: String = "",
@SerializedName("sort")
val sort: Int = 0,
@SerializedName("sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,29 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonOutDetailResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("code")
val code: String = "",
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("pizhong")
val pizhong: Double = 0.0,
@SerializedName("rfid")
val rfid: String = "",
@SerializedName("rksysid")
val rksysid: String = "",
@SerializedName("sysid")
val sysid: String = ""
)
}
@@ -0,0 +1,59 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonOutListResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: List<Data> = listOf(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("bagtype")
val bagtype: String = "",
@SerializedName("bagzhongliang")
val bagzhongliang: Double = 0.0,
@SerializedName("baoshu")
val baoshu: Int = 0,
@SerializedName("canpinzhong")
val canpinzhong: String = "",
@SerializedName("carpaihao")
val carpaihao: String = "",
@SerializedName("chukuren")
val chukuren: String = "",
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("cjsysid")
val cjsysid: String = "",
@SerializedName("ckdatetime")
val ckdatetime: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("gjcksysid")
val gjcksysid: String = "",
@SerializedName("jiantype")
val jiantype: String = "",
@SerializedName("jiantypesysid")
val jiantypesysid: String = "",
@SerializedName("jingzhong")
val jingzhong: Double = 0.0,
@SerializedName("maozhong")
val maozhong: Double = 0.0,
@SerializedName("pizhong")
val pizhong: Double = 0.0,
@SerializedName("sysid")
val sysid: String = "",
@SerializedName("tihuoren")
val tihuoren: String = "",
@SerializedName("wldwname")
val wldwname: String = "",
@SerializedName("wldwsysid")
val wldwsysid: String = "",
@SerializedName("xiangzhen")
val xiangzhen: String = ""
)
}
@@ -0,0 +1,24 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonOutStatisticsResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("total_baoshu")
val totalBaoshu: Int = 0,
@SerializedName("total_jingzhong")
val totalJingzhong: Double = 0.0,
@SerializedName("total_maozhong")
val totalMaozhong: Double = 0.0,
@SerializedName("total_num")
val totalNum: Int = 0,
@SerializedName("total_pizhong")
val totalPizhong: Double = 0.0
)
}
@@ -0,0 +1,33 @@
package com.bbitcn.f8.pad.model.net.response
import com.google.gson.annotations.SerializedName
data class DryCocoonPackageInfoResponse(
@SerializedName("code")
val code: Int = 0,
@SerializedName("data")
val `data`: Data = Data(),
@SerializedName("msg")
val msg: String = ""
) {
data class Data(
@SerializedName("bagtype")
val bagtype: String = "",
@SerializedName("bagzhongliang")
val bagzhongliang: Double = 0.0,
@SerializedName("cjname")
val cjname: String = "",
@SerializedName("ckname")
val ckname: String = "",
@SerializedName("code")
val code: String = "",
@SerializedName("fanbaotanlianging")
val fanbaotanlianging: Int = 0,
@SerializedName("jiantypename")
val jiantypename: String = "",
@SerializedName("kcmaozhong")
val kcmaozhong: Double = 0.0,
@SerializedName("sysid")
val sysid: String = ""
)
}

Some files were not shown because too many files have changed in this diff Show More