From 7e25bb01a9a6c8cad9dc1906fba6cc698ecc6447 Mon Sep 17 00:00:00 2001 From: Liuyf Date: Wed, 15 Jan 2025 19:08:23 +0800 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Eapp=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=91=E5=B8=83=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lan/lan_ar.json | 3 ++- lan/lan_bg.json | 3 ++- lan/lan_bn.json | 3 ++- lan/lan_cs.json | 3 ++- lan/lan_da.json | 3 ++- lan/lan_de.json | 3 ++- lan/lan_el.json | 3 ++- lan/lan_en.json | 3 ++- lan/lan_es.json | 3 ++- lan/lan_et.json | 3 ++- lan/lan_fi.json | 3 ++- lan/lan_fr.json | 3 ++- lan/lan_he.json | 3 ++- lan/lan_hk.json | 3 ++- lan/lan_hr.json | 3 ++- lan/lan_hu.json | 3 ++- lan/lan_id.json | 3 ++- lan/lan_it.json | 3 ++- lan/lan_ja.json | 3 ++- lan/lan_keys.json | 3 ++- lan/lan_kk.json | 3 ++- lan/lan_ko.json | 3 ++- lan/lan_lt.json | 3 ++- lan/lan_ms.json | 3 ++- lan/lan_nl.json | 3 ++- lan/lan_pl.json | 3 ++- lan/lan_pt.json | 3 ++- lan/lan_ro.json | 3 ++- lan/lan_ru.json | 3 ++- lan/lan_sk.json | 3 ++- lan/lan_sr_cyrl.json | 3 ++- lan/lan_sv.json | 3 ++- lan/lan_th.json | 3 ++- lan/lan_tr.json | 3 ++- lan/lan_tw.json | 3 ++- lan/lan_uk.json | 3 ++- lan/lan_vi.json | 3 ++- lan/lan_zh.json | 3 ++- lib/login/login/app_get_version.dart | 2 ++ lib/mine/about/about_page.dart | 37 ++++++++++++++++++++++++++ lib/tools/storage.dart | 2 +- lib/tools/wechat/wechatManageTool.dart | 11 ++++---- 42 files changed, 121 insertions(+), 45 deletions(-) diff --git a/lan/lan_ar.json b/lan/lan_ar.json index cc05a60a..f550d3eb 100644 --- a/lan/lan_ar.json +++ b/lan/lan_ar.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "اتبع النظام", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "بعد إعادة الضبط ، سيتم حذف بصمات القفل. هل أنت متأكد أنك تريد إعادة ضبطه ؟", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "بعد إعادة الضبط ، سيتم حذف جهاز التحكم عن بعد للقفل. هل تريد إعادة ضبطه ؟" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "بعد إعادة الضبط ، سيتم حذف جهاز التحكم عن بعد للقفل. هل تريد إعادة ضبطه ؟", + "版本说明": "تعليمات الإصدار" } \ No newline at end of file diff --git a/lan/lan_bg.json b/lan/lan_bg.json index 1ff0814d..2f3d144b 100644 --- a/lan/lan_bg.json +++ b/lan/lan_bg.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Следете система", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "След нулиране, пръстовите отпечатъци на заключването ще бъдат изтрити. Сигурен ли сте, че искате да го нулирате?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "След нулиране, дистанционното управление на ключалката ще бъде изтрито. Искате ли да го нулирате?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "След нулиране, дистанционното управление на ключалката ще бъде изтрито. Искате ли да го нулирате?", + "版本说明": "Обяснение на версията" } \ No newline at end of file diff --git a/lan/lan_bn.json b/lan/lan_bn.json index 795fae0c..03eafc2b 100644 --- a/lan/lan_bn.json +++ b/lan/lan_bn.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "এক্ফক্লোসিস্টেম", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "ব্যান্ডোটারট্রাসেট, thelock'sferprinতা?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "ব্যান্ডোটারপ্রাসেট, নিয়ন্ত্রণের নিয়ন্ত্রণ। ডোডো ডাইভান্টটুরে?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "ব্যান্ডোটারপ্রাসেট, নিয়ন্ত্রণের নিয়ন্ত্রণ। ডোডো ডাইভান্টটুরে?", + "版本说明": "ভার্সনপরিচিতি", } \ No newline at end of file diff --git a/lan/lan_cs.json b/lan/lan_cs.json index 7481a2b9..d0eb38e6 100644 --- a/lan/lan_cs.json +++ b/lan/lan_cs.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Sledovat systém", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Po resetování budou otisky prstů zámku odstraněny. Opravdu ho chcete obnovit?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Po resetu bude dálkové ovládání zámku odstraněno. Chcete ho obnovit?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Po resetu bude dálkové ovládání zámku odstraněno. Chcete ho obnovit?", + "版本说明": "Verze" } \ No newline at end of file diff --git a/lan/lan_da.json b/lan/lan_da.json index d31899a2..768ec600 100644 --- a/lan/lan_da.json +++ b/lan/lan_da.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Følg systemet", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Efter nulstilling vil låsens fingeraftryk blive slettet. Er du sikker på at du vil nulstille den?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Efter nulstilling, fjernbetjeningen af låsen vil blive slettet. Vil du nulstille den?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Efter nulstilling, fjernbetjeningen af låsen vil blive slettet. Vil du nulstille den?", + "版本说明": "Versionsbeskrivelse", } \ No newline at end of file diff --git a/lan/lan_de.json b/lan/lan_de.json index 049563a7..e6e2f250 100644 --- a/lan/lan_de.json +++ b/lan/lan_de.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "System folgen", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Nach dem Zurücksetzen werden die Finger abdrücke des Schlosses gelöscht. Sind Sie sicher, dass Sie es zurücksetzen wollen?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Nach dem Zurücksetzen wird die Fernbedienung des Schlosses gelöscht. Willst du es zurücksetzen?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Nach dem Zurücksetzen wird die Fernbedienung des Schlosses gelöscht. Willst du es zurücksetzen?", + "版本说明": "Versionsbeschreibung" } \ No newline at end of file diff --git a/lan/lan_el.json b/lan/lan_el.json index 82a15dfe..a076aac3 100644 --- a/lan/lan_el.json +++ b/lan/lan_el.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Ακολουθήστε το σύστημα", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Μετά την επαναφορά, τα αποτυπώματα της κλειδαριάς θα διαγραφούν. Είστε σίγουροι ότι θέλετε να το επαναφέρετε;", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Μετά την επαναφορά, το τηλεχειριστήριο της κλειδαριάς θα διαγραφεί. Θέλεις να το επαναφέρεις;" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Μετά την επαναφορά, το τηλεχειριστήριο της κλειδαριάς θα διαγραφεί. Θέλεις να το επαναφέρεις;", + "版本说明": "Περιγραφή έκδοσης", } \ No newline at end of file diff --git a/lan/lan_en.json b/lan/lan_en.json index a4376a71..9138e86a 100644 --- a/lan/lan_en.json +++ b/lan/lan_en.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Follow system", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "After reset, the lock's fingerprints will be deleted. Are you sure you want to reset it?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "After reset, the remote control of the lock will be deleted. Do you want to reset it?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "After reset, the remote control of the lock will be deleted. Do you want to reset it?", + "版本说明": "Version description" } diff --git a/lan/lan_es.json b/lan/lan_es.json index b9c06ea5..3e47d880 100644 --- a/lan/lan_es.json +++ b/lan/lan_es.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Seguir sistema", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Después de restablecer, se eliminarán las huellas dactilares del bloqueo. ¿Está seguro de que desea restablecerlo?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Después del reinicio, se eliminará el control remoto de la cerradura. ¿Quieres resetearlo?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Después del reinicio, se eliminará el control remoto de la cerradura. ¿Quieres resetearlo?", + "版本说明": "Instrucciones de versión" } \ No newline at end of file diff --git a/lan/lan_et.json b/lan/lan_et.json index e7209737..63e90c7a 100644 --- a/lan/lan_et.json +++ b/lan/lan_et.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Süsteemi jälgimine", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Pärast lähtestamist kustutatakse luku sõrmejäljed. Kas tõesti soovid see lähtestada?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Pärast lähtestamist kustutatakse luku kaugjuhtimine. Kas sa tahad seda lähtestada?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Pärast lähtestamist kustutatakse luku kaugjuhtimine. Kas sa tahad seda lähtestada?", + "版本说明": "Versiooniteave", } \ No newline at end of file diff --git a/lan/lan_fi.json b/lan/lan_fi.json index 727a8557..53aee63c 100644 --- a/lan/lan_fi.json +++ b/lan/lan_fi.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Seuraa järjestelmää", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Lukon sormenjäljet poistetaan. Haluatko varmasti nollataa sen?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Nollauksen jälkeen lukon kaukosäädin poistetaan. Haluatko palauttaa sen?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Nollauksen jälkeen lukon kaukosäädin poistetaan. Haluatko palauttaa sen?", + "版本说明": "Versio", } \ No newline at end of file diff --git a/lan/lan_fr.json b/lan/lan_fr.json index f630b6df..36f4918d 100644 --- a/lan/lan_fr.json +++ b/lan/lan_fr.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Suivre le système", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Après réinitialisation, les empreintes digitales de la serrure seront supprimées. Êtes-vous sûr de vouloir le réinitialiser?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Après réinitialisation, la télécommande du verrou sera supprimée. Voulez-vous le réinitialiser?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Après réinitialisation, la télécommande du verrou sera supprimée. Voulez-vous le réinitialiser?", + "版本说明": "Explication de la version", } \ No newline at end of file diff --git a/lan/lan_he.json b/lan/lan_he.json index 4ed3a79a..2214efd6 100644 --- a/lan/lan_he.json +++ b/lan/lan_he.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "מערכת מעקב", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "לאחר איפוס, טביעות האצבעות של המנעול יימחקו. אתה בטוח שברצונך לאפס את זה?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "לאחר איפוס, השליטה מרחוק של המנעול יימחק. אתה רוצה לאפס את זה?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "לאחר איפוס, השליטה מרחוק של המנעול יימחק. אתה רוצה לאפס את זה?", + "版本说明": "המידע על גרסה", } \ No newline at end of file diff --git a/lan/lan_hk.json b/lan/lan_hk.json index e774f098..10f8f20f 100644 --- a/lan/lan_hk.json +++ b/lan/lan_hk.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "跟隨系統", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "重置之後,鎖嘅指紋將被刪除。 你確定要重置它啊?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置之後,鎖嘅遙控器將被刪除。 是否要重置它?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置之後,鎖嘅遙控器將被刪除。 是否要重置它?", + "版本说明": "版本說明" } \ No newline at end of file diff --git a/lan/lan_hr.json b/lan/lan_hr.json index 756e9c3d..2b46ae3f 100644 --- a/lan/lan_hr.json +++ b/lan/lan_hr.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Prati sistem:", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Nakon resetovanja, otisci brave će biti izbrisani. Jeste li sigurni da ga želite resetirati?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Nakon resetovanja, daljinski upravljač brave će biti izbrisan. Hoæeš da ga resetuješ?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Nakon resetovanja, daljinski upravljač brave će biti izbrisan. Hoæeš da ga resetuješ?", + "版本说明": "Informacije o verziji", } \ No newline at end of file diff --git a/lan/lan_hu.json b/lan/lan_hu.json index 5e47b0c3..5f6c38c9 100644 --- a/lan/lan_hu.json +++ b/lan/lan_hu.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Follow system", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "A reset után a zár ujjlenyomatai törlődnek. Biztos vagy benne, hogy vissza szeretné állítani?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "A reset után a zár távirányítója törlődik. Szeretné visszaállítani?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "A reset után a zár távirányítója törlődik. Szeretné visszaállítani?", + "版本说明": "Versió leírás", } \ No newline at end of file diff --git a/lan/lan_id.json b/lan/lan_id.json index 698dbd83..872dcb41 100644 --- a/lan/lan_id.json +++ b/lan/lan_id.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Sistem mengikuti", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Setelah mengulang, sidik jari kunci akan dihapus. Yakin ingin meresetnya?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Setelah reset, remote control kunci akan dihapus. Ingin mengatur ulang?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Setelah reset, remote control kunci akan dihapus. Ingin mengatur ulang?", + "版本说明": "Catatan versi", } \ No newline at end of file diff --git a/lan/lan_it.json b/lan/lan_it.json index cd375d3c..7bb5d872 100644 --- a/lan/lan_it.json +++ b/lan/lan_it.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Seguire il sistema", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Dopo il reset, le impronte digitali del lucchetto verranno cancellate. Sei sicuro di volerlo resettare?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Dopo il reset, il telecomando del lucchetto verrà eliminato. Vuoi resettarlo?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Dopo il reset, il telecomando del lucchetto verrà eliminato. Vuoi resettarlo?", + "版本说明": "Versione" } \ No newline at end of file diff --git a/lan/lan_ja.json b/lan/lan_ja.json index ef2509f4..6c2f6de7 100644 --- a/lan/lan_ja.json +++ b/lan/lan_ja.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "システムに従う", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "リセット後、ロックの指紋は削除されます。リセットしてもよろしいですか。", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "リセット後、ロックのリモコンが削除されます。リセットしますか?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "リセット後、ロックのリモコンが削除されます。リセットしますか?", + "版本说明": "バージョン説明", } \ No newline at end of file diff --git a/lan/lan_keys.json b/lan/lan_keys.json index bf8f6820..577abfa7 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -1120,5 +1120,6 @@ "分简称": "分简称", "跟随系统": "跟随系统", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "重置后,该锁的指纹都将被删除哦,确认要重置吗?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?", + "版本说明": "版本说明", } diff --git a/lan/lan_kk.json b/lan/lan_kk.json index 9e6961bc..ee063c9e 100644 --- a/lan/lan_kk.json +++ b/lan/lan_kk.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Жүйені қолдану", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Қайта ысырып тастау Шынымен ысырып тастауды қалайсыз ба?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Қайта ысырып ысырып тасымалдауын өшіріледі. Оны ысырып тастауды қалайсыз ба?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Қайта ысырып ысырып тасымалдауын өшіріледі. Оны ысырып тастауды қалайсыз ба?", + "版本说明": "Версиятын көрсету", } \ No newline at end of file diff --git a/lan/lan_ko.json b/lan/lan_ko.json index eddb7629..0240269d 100644 --- a/lan/lan_ko.json +++ b/lan/lan_ko.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "시스템을 따르십시오", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "재설정 후 잠금 장치의 지문이 삭제됩니다. 당신은 그것을 재설정 하시겠습니까?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "재설정 후 잠금 장치의 리모컨이 삭제됩니다. 당신은 그것을 재설정 하시겠습니까?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "재설정 후 잠금 장치의 리모컨이 삭제됩니다. 당신은 그것을 재설정 하시겠습니까?", + "版本说明": "버전 설명", } \ No newline at end of file diff --git a/lan/lan_lt.json b/lan/lan_lt.json index 3be128da..d9e18b00 100644 --- a/lan/lan_lt.json +++ b/lan/lan_lt.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Sekti sistema", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Po reset užrakto pirštų atspaudai bus ištrinti. Ar tikrai norite jį atkurti?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Po reset, nuotolinis valdymo pultas užraktas bus ištrintas. Ar norite jį atkurti?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Po reset, nuotolinis valdymo pultas užraktas bus ištrintas. Ar norite jį atkurti?", + "版本说明": "Versijos aprašymas", } \ No newline at end of file diff --git a/lan/lan_ms.json b/lan/lan_ms.json index 9e382f28..05ed0ebd 100644 --- a/lan/lan_ms.json +++ b/lan/lan_ms.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Ikut system", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Selepas menetapkan semula, cap jari kunci akan dipadamkan. Adakah anda pasti anda mahu menetapkan semula?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Selepas menetapkan semula, kawalan jauh kunci akan dipadamkan. Adakah anda mahu menetapkan semula?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Selepas menetapkan semula, kawalan jauh kunci akan dipadamkan. Adakah anda mahu menetapkan semula?", + "版本说明": "Penerangan versi", } \ No newline at end of file diff --git a/lan/lan_nl.json b/lan/lan_nl.json index 545dd0a9..ceb6ec0e 100644 --- a/lan/lan_nl.json +++ b/lan/lan_nl.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Systeem volgen", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Na het resetten worden de vingerafdrukken van het slot verwijderd. Weet je zeker dat je het wilt resetten?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Na het resetten wordt de afstandsbediening van het slot verwijderd. Wilt u het resetten?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Na het resetten wordt de afstandsbediening van het slot verwijderd. Wilt u het resetten?", + "版本说明": "Versieomschrijving", } \ No newline at end of file diff --git a/lan/lan_pl.json b/lan/lan_pl.json index cb25c002..18cfb3d6 100644 --- a/lan/lan_pl.json +++ b/lan/lan_pl.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Śledź system", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Po zresetowaniu odciski palców zamka zostaną usunięte. Czy na pewno chcesz go zresetować?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Po zresetowaniu zdalne sterowanie zamkiem zostanie usunięte. Czy chcesz go zresetować?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Po zresetowaniu zdalne sterowanie zamkiem zostanie usunięte. Czy chcesz go zresetować?", + "版本说明": "Wersja", } \ No newline at end of file diff --git a/lan/lan_pt.json b/lan/lan_pt.json index d77d3b0e..22636d1e 100644 --- a/lan/lan_pt.json +++ b/lan/lan_pt.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Siga o sistema", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Após a redefinição, as impressões digitais do bloqueio serão apagadas. Tens a certeza que queres redefini-lo?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Após a reinicialização, o controle remoto do bloqueio será excluído. Você quer redefini-lo?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Após a reinicialização, o controle remoto do bloqueio será excluído. Você quer redefini-lo?", + "版本说明": "Descrição da versão", } \ No newline at end of file diff --git a/lan/lan_ro.json b/lan/lan_ro.json index e0f4f397..3fe81f0f 100644 --- a/lan/lan_ro.json +++ b/lan/lan_ro.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Urmează sistemul:", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "După resetare, amprentele încuietorii vor fi şterse. Sigur doriți să-l resetați?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "După resetare, telecomanda de blocare va fi ştersă. Vrei să-l resetezi?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "După resetare, telecomanda de blocare va fi ştersă. Vrei să-l resetezi?", + "版本说明": "Descrierea versiunii", } \ No newline at end of file diff --git a/lan/lan_ru.json b/lan/lan_ru.json index be2e5622..cfba1ebf 100644 --- a/lan/lan_ru.json +++ b/lan/lan_ru.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Следуйте системе", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "После сброса отпечатки пальцев замка будут удалены. Вы уверены, что хотите его перезагрузить?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "После сброса пульт дистанционного управления замком будет удален. А вы хотите его сбросить?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "После сброса пульт дистанционного управления замком будет удален. А вы хотите его сбросить?", + "版本说明": "Объяснение версии", } \ No newline at end of file diff --git a/lan/lan_sk.json b/lan/lan_sk.json index b72ccb15..7606e642 100644 --- a/lan/lan_sk.json +++ b/lan/lan_sk.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Sledovať systém", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Po resetovaní budú prstové odtlačky zámku vymazané. Ste si istí, že chcete obnoviť?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Po resetovaní bude diaľkové ovládanie zámku vymazané. Chcete ho obnoviť?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Po resetovaní bude diaľkové ovládanie zámku vymazané. Chcete ho obnoviť?", + "版本说明": "Popis verzie" } \ No newline at end of file diff --git a/lan/lan_sr_cyrl.json b/lan/lan_sr_cyrl.json index 381e1bcc..076b29b3 100644 --- a/lan/lan_sr_cyrl.json +++ b/lan/lan_sr_cyrl.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Пратите систем", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Након ресетовања, отисци прстију браве ће бити избрисани. Да ли сте сигурни да желите да га ресетујете?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Након ресетовања, даљински управљач браве ће бити избрисан. Да ли желите да га ресетујете?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Након ресетовања, даљински управљач браве ће бити избрисан. Да ли желите да га ресетујете?", + "版本说明": "Опис верзије" } \ No newline at end of file diff --git a/lan/lan_sv.json b/lan/lan_sv.json index b1f95839..c81b013b 100644 --- a/lan/lan_sv.json +++ b/lan/lan_sv.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Följ system", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Efter återställd, kommer låsets fingeravtryck tas bort. Är du säker på att du vill återställa den?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Efter återställd, fjärrkontrollen på låset tas bort. Vill du återställa den?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Efter återställd, fjärrkontrollen på låset tas bort. Vill du återställa den?", + "版本说明": "Versionsbeskrivning" } \ No newline at end of file diff --git a/lan/lan_th.json b/lan/lan_th.json index 45abbb64..bf4bdf0c 100644 --- a/lan/lan_th.json +++ b/lan/lan_th.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "ระบบติดตามผล", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "หลังจากรีเซ็ตแล้วลายนิ้วมือของล็อคจะถูกลบออกคุณแน่ใจว่าอยากจะรีเซ็ต?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "หลังจากรีเซ็ตแล้วรีโมทคอนโทรลของล็อคจะถูกลบออกคุณต้องการรีเซ็ตไหม" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "หลังจากรีเซ็ตแล้วรีโมทคอนโทรลของล็อคจะถูกลบออกคุณต้องการรีเซ็ตไหม", + "版本说明": "คำอธิบายรุ่น" } \ No newline at end of file diff --git a/lan/lan_tr.json b/lan/lan_tr.json index 53ae8ad3..035738ba 100644 --- a/lan/lan_tr.json +++ b/lan/lan_tr.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Sistemi takip et", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Sıfırlamadan sonra, kilidin parmak izleri silinecektir. Sıfırlamak istediğine emin misin?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Sıfırladıktan sonra, kilidin uzaktan kumandası silinecektir. Sıfırlamak ister misin?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Sıfırladıktan sonra, kilidin uzaktan kumandası silinecektir. Sıfırlamak ister misin?", + "版本说明": "Sürüm açıklaması", } \ No newline at end of file diff --git a/lan/lan_tw.json b/lan/lan_tw.json index 9b69c146..7347b2c4 100644 --- a/lan/lan_tw.json +++ b/lan/lan_tw.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "跟蹤系統", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "重置後,鎖的指紋將被刪除。 是否確實要重置它?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置後,鎖的遙控器將被刪除。 是否要重置它?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置後,鎖的遙控器將被刪除。 是否要重置它?", + "版本说明": "版本說明", } \ No newline at end of file diff --git a/lan/lan_uk.json b/lan/lan_uk.json index fc64e240..1df767a6 100644 --- a/lan/lan_uk.json +++ b/lan/lan_uk.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Система стеження за", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Після скидання відбитки пальців замка будуть видалені. Ви впевнені, що хочете скинути налаштування?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Після скидання пульт дистанційного керування замком буде видалено. Хочете його скинути?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Після скидання пульт дистанційного керування замком буде видалено. Хочете його скинути?", + "版本说明": "Опис версії", } \ No newline at end of file diff --git a/lan/lan_vi.json b/lan/lan_vi.json index b83db737..5e8939b7 100644 --- a/lan/lan_vi.json +++ b/lan/lan_vi.json @@ -1120,5 +1120,6 @@ "分简称": "M", "跟随系统": "Hệ thống theo dõi", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "Sau khi đặt lại, dấu vân tay của khóa sẽ bị xóa. Bạn có chắc chắn muốn thiết lập lại nó?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Sau khi đặt lại, điều khiển từ xa của khóa sẽ bị xóa. Bạn có muốn đặt lại không?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "Sau khi đặt lại, điều khiển từ xa của khóa sẽ bị xóa. Bạn có muốn đặt lại không?", + "版本说明": "Thông tin phiên bản" } \ No newline at end of file diff --git a/lan/lan_zh.json b/lan/lan_zh.json index ecb737fe..d5099701 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1120,5 +1120,6 @@ "分简称": "分", "跟随系统": "跟随系统", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "重置后,该锁的指纹都将被删除哦,确认要重置吗?", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?" + "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?", + "版本说明": "版本说明" } diff --git a/lib/login/login/app_get_version.dart b/lib/login/login/app_get_version.dart index fb738b60..522e2e72 100644 --- a/lib/login/login/app_get_version.dart +++ b/lib/login/login/app_get_version.dart @@ -29,10 +29,12 @@ class Data { Data.fromJson(Map json) { wechatServiceUrl = json['wechat_service_url']; appSiteUrl = json['app_site_url']; + appVersionHistoryUrl = json['app_version_history_url']; } String? wechatServiceUrl; String? appSiteUrl; + String? appVersionHistoryUrl; Map toJson() { final Map data = {}; diff --git a/lib/mine/about/about_page.dart b/lib/mine/about/about_page.dart index 91c2dd68..ba6f4f44 100755 --- a/lib/mine/about/about_page.dart +++ b/lib/mine/about/about_page.dart @@ -1,3 +1,6 @@ +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -9,7 +12,9 @@ import 'package:star_lock/mine/about/about_console.dart'; import '../../app_settings/app_colors.dart'; import '../../flavors.dart'; import '../../tools/commonItem.dart'; +import '../../tools/storage.dart'; import '../../tools/titleAppBar.dart'; +import '../../tools/wechat/wechatManageTool.dart'; class AboutPage extends StatefulWidget { const AboutPage({Key? key}) : super(key: key); @@ -80,6 +85,38 @@ class _AboutPageState extends State { Widget listView() { Widget view = Column( children: [ + CommonItem( + leftTitel: '版本说明'.tr, + rightTitle: '', + isHaveLine: false, + isHaveDirection: true, + action: () async { + WechatManageTool.getAppInfo(() async { + final String? appVersionHistoryBaseUrl = + await Storage.getString(appVersionHistoryUrl); + if (appVersionHistoryBaseUrl == null) { + return; + } + String brandName = ''; + if (Platform.isAndroid) { + final AndroidDeviceInfo androidDeviceInfo = + await DeviceInfoPlugin().androidInfo; + brandName = androidDeviceInfo.manufacturer; + } else { + final IosDeviceInfo iosDeviceInfo = + await DeviceInfoPlugin().iosInfo; + brandName = iosDeviceInfo.systemName ?? 'ios'; + } + final PackageInfo packageInfo = + await PackageInfo.fromPlatform(); + Navigator.pushNamed(context, Routers.webviewShowPage, + arguments: { + 'url': appVersionHistoryBaseUrl + + '?version=${packageInfo.version}&brandName=${brandName}', + 'title': '版本说明'.tr + }); + }); + }), CommonItem( leftTitel: '介绍'.tr, rightTitle: '', diff --git a/lib/tools/storage.dart b/lib/tools/storage.dart index b76f65c4..f4fbf998 100755 --- a/lib/tools/storage.dart +++ b/lib/tools/storage.dart @@ -30,7 +30,7 @@ const String saveLockMainListData = 'lockMainListData'; const String isOpenDeBug = 'isOpenDeBug'; //是否打开 debug const String automaticLockOffTime = 'automaticLockOffTime'; //自动关锁时间 const String associationUrl = 'associationUrl'; //ios跳转微信的 url - +const String appVersionHistoryUrl = 'appVersionHistoryUrl'; //是否同意隐私协议弹窗 class Storage { factory Storage() => _instance; diff --git a/lib/tools/wechat/wechatManageTool.dart b/lib/tools/wechat/wechatManageTool.dart index 9f77c6dc..fa548669 100644 --- a/lib/tools/wechat/wechatManageTool.dart +++ b/lib/tools/wechat/wechatManageTool.dart @@ -1,7 +1,6 @@ - - import '../../login/login/app_get_version.dart'; import '../../network/api_repository.dart'; +import '../storage.dart'; import 'customer_tool.dart'; import 'pay/wx_pay_tool.dart'; @@ -13,12 +12,12 @@ class WechatManageTool { static Future getAppInfo(void Function() action) async { // AppLog.log('AppFirstEnterHandle调用了获取App信息接口'); final GetAppInfo entity = await ApiRepository.to.getAppInfo(); - if(entity.errorCode == 0) { + if (entity.errorCode == 0) { + Storage.setString( + appVersionHistoryUrl, entity.data?.appVersionHistoryUrl ?? ''); CustomerTool.init(entity.data?.wechatServiceUrl ?? ''); WxPayTool.setAssociationUrl(entity.data!.appSiteUrl!); action(); } - } - -} \ No newline at end of file +} From 973a1384feb11d2944812fabc16e7e841ae1bab0 Mon Sep 17 00:00:00 2001 From: Liuyf Date: Thu, 16 Jan 2025 09:13:42 +0800 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9Eapp=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=91=E5=B8=83=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/login/login/app_get_version.dart | 2 +- lib/mine/about/about_page.dart | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/login/login/app_get_version.dart b/lib/login/login/app_get_version.dart index 522e2e72..de2a642c 100644 --- a/lib/login/login/app_get_version.dart +++ b/lib/login/login/app_get_version.dart @@ -29,7 +29,7 @@ class Data { Data.fromJson(Map json) { wechatServiceUrl = json['wechat_service_url']; appSiteUrl = json['app_site_url']; - appVersionHistoryUrl = json['app_version_history_url']; + appVersionHistoryUrl = json['appVersionHistoryUrl']; } String? wechatServiceUrl; diff --git a/lib/mine/about/about_page.dart b/lib/mine/about/about_page.dart index ba6f4f44..46632a87 100755 --- a/lib/mine/about/about_page.dart +++ b/lib/mine/about/about_page.dart @@ -117,6 +117,12 @@ class _AboutPageState extends State { }); }); }), + Divider( + height: 1, + color: AppColors.greyLineColor, + indent: 20.w, + endIndent: 20.w, + ), CommonItem( leftTitel: '介绍'.tr, rightTitle: '', From f0a5d142ad3b057d37cb1fa585a2da66bc2668f6 Mon Sep 17 00:00:00 2001 From: Liuyf Date: Thu, 16 Jan 2025 16:25:20 +0800 Subject: [PATCH 03/15] =?UTF-8?q?other=EF=BC=9A=E5=85=B6=E4=BB=96=E7=8E=AF?= =?UTF-8?q?=E5=A2=83ummeng=E5=92=8Cfirebase=20key=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/sky_dev/google-services.json | 48 ++++++++++++++++++++ android/app/src/sky_pre/google-services.json | 48 ++++++++++++++++++++ android/app/src/xhj_dev/google-services.json | 48 ++++++++++++++++++++ android/app/src/xhj_pre/google-services.json | 48 ++++++++++++++++++++ lib/flavors.dart | 32 ++++++------- 5 files changed, 208 insertions(+), 16 deletions(-) create mode 100644 android/app/src/sky_dev/google-services.json create mode 100644 android/app/src/sky_pre/google-services.json create mode 100644 android/app/src/xhj_dev/google-services.json create mode 100644 android/app/src/xhj_pre/google-services.json diff --git a/android/app/src/sky_dev/google-services.json b/android/app/src/sky_dev/google-services.json new file mode 100644 index 00000000..6eaa86af --- /dev/null +++ b/android/app/src/sky_dev/google-services.json @@ -0,0 +1,48 @@ +{ + "project_info": { + "project_number": "281500445726", + "project_id": "skychip2023-ecdff", + "storage_bucket": "skychip2023-ecdff.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:281500445726:android:ddf52ac7b7f83cf5c4d20f", + "android_client_info": { + "package_name": "com.skychip.lock.dev" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC-3-ABWuy9LrYyAw_KxDRto4DanQ0sq9g" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:281500445726:android:468195b9cc68dd6cc4d20f", + "android_client_info": { + "package_name": "com.starlock.lock.local" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC-3-ABWuy9LrYyAw_KxDRto4DanQ0sq9g" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/sky_pre/google-services.json b/android/app/src/sky_pre/google-services.json new file mode 100644 index 00000000..2a7a6dbe --- /dev/null +++ b/android/app/src/sky_pre/google-services.json @@ -0,0 +1,48 @@ +{ + "project_info": { + "project_number": "281500445726", + "project_id": "skychip2023-ecdff", + "storage_bucket": "skychip2023-ecdff.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:281500445726:android:ddf52ac7b7f83cf5c4d", + "android_client_info": { + "package_name": "com.skychip.lock.pre" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC-3-ABWuy9LrYyAw_KxDRto4DanQ" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:281500445726:android:468195b9cc68dd6cc", + "android_client_info": { + "package_name": "com.starlock.lock.local" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC-3-ABWuy9LrYyAw_KxDRto4DanQ0sq9g" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/xhj_dev/google-services.json b/android/app/src/xhj_dev/google-services.json new file mode 100644 index 00000000..791f2d92 --- /dev/null +++ b/android/app/src/xhj_dev/google-services.json @@ -0,0 +1,48 @@ +{ + "project_info": { + "project_number": "28150044todo", + "project_id": "skychip2023-etodo", + "storage_bucket": "skychip2023-etodo.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:281500445726:android:ddf52ac7b7f83cf5c4todo", + "android_client_info": { + "package_name": "com.xhjcn.lock" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC-3-ABWuy9LrYyAw_KxDRto4DanQ0todo" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:281500445726:android:468195b9cc68dd6cc4todo", + "android_client_info": { + "package_name": "com.xhjcn.lock.local" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC-3-ABWuy9LrYyAw_KxDRto4Dank9todo" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/src/xhj_pre/google-services.json b/android/app/src/xhj_pre/google-services.json new file mode 100644 index 00000000..791f2d92 --- /dev/null +++ b/android/app/src/xhj_pre/google-services.json @@ -0,0 +1,48 @@ +{ + "project_info": { + "project_number": "28150044todo", + "project_id": "skychip2023-etodo", + "storage_bucket": "skychip2023-etodo.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:281500445726:android:ddf52ac7b7f83cf5c4todo", + "android_client_info": { + "package_name": "com.xhjcn.lock" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC-3-ABWuy9LrYyAw_KxDRto4DanQ0todo" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:281500445726:android:468195b9cc68dd6cc4todo", + "android_client_info": { + "package_name": "com.xhjcn.lock.local" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyC-3-ABWuy9LrYyAw_KxDRto4Dank9todo" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/lib/flavors.dart b/lib/flavors.dart index 6479398a..5334def5 100755 --- a/lib/flavors.dart +++ b/lib/flavors.dart @@ -199,28 +199,28 @@ class F { switch (appFlavor) { case Flavor.local: return const UmengKey( - androidKey: '671244cf80464b33f6df9648', - iosKey: '671244ae80464b33f6df9646', + androidKey: 'local-671244cf80464b33f6df9648', + iosKey: 'local-671244ae80464b33f6df9646', channel: 'Product'); case Flavor.dev: return const UmengKey( - androidKey: '671244cf80464b33f6df9648', - iosKey: '671244ae80464b33f6df9646', + androidKey: 'dev-671244cf80464b33f6df9648', + iosKey: 'dev-671244ae80464b33f6df9646', channel: 'Product'); case Flavor.pre: return const UmengKey( - androidKey: '671244cf80464b33f6df9648', - iosKey: '671244ae80464b33f6df9646', + androidKey: 'pre-671244cf80464b33f6df9648', + iosKey: 'pre-671244ae80464b33f6df9646', channel: 'Product'); case Flavor.sky_dev: return const UmengKey( - androidKey: '671244cf80464b33f6df9648', - iosKey: '671244ae80464b33f6df9646', + androidKey: 'sky_dev-671244cf80464b33f6df9648', + iosKey: 'sky_dev-671244ae80464b33f6df9646', channel: 'Product'); case Flavor.sky_pre: return const UmengKey( - androidKey: '671244cf80464b33f6df9648', - iosKey: '671244ae80464b33f6df9646', + androidKey: 'sky_pre-671244cf80464b33f6df9648', + iosKey: 'sky_pre-671244ae80464b33f6df9646', channel: 'Product'); case Flavor.sky: return const UmengKey( @@ -229,13 +229,13 @@ class F { channel: 'Product'); case Flavor.xhj_dev: return const UmengKey( - androidKey: '671244cf80464b33f6df9648', - iosKey: '671244ae80464b33f6df9646', + androidKey: 'xhj_dev-671244cf80464b33f6df9648', + iosKey: 'xhj_dev-671244ae80464b33f6df9646', channel: 'Product'); case Flavor.xhj_pre: return const UmengKey( - androidKey: '671244cf80464b33f6df9648', - iosKey: '671244ae80464b33f6df9646', + androidKey: 'xhj_pre-671244cf80464b33f6df9648', + iosKey: 'xhj_pre-671244ae80464b33f6df9646', channel: 'Product'); case Flavor.xhj: return const UmengKey( @@ -244,8 +244,8 @@ class F { channel: 'Product'); default: return const UmengKey( - androidKey: '671244cf80464b33f6df9648', - iosKey: '671244ae80464b33f6df9646', + androidKey: 'default-671244cf80464b33f6df9648', + iosKey: 'default-671244ae80464b33f6df9646', channel: 'Product'); } } From e9921f1180725a6d82d74ff13c9236d25c0ce2d7 Mon Sep 17 00:00:00 2001 From: Liuyf Date: Mon, 20 Jan 2025 13:46:12 +0800 Subject: [PATCH 04/15] =?UTF-8?q?other:=20xhj=20google=E4=B8=8A=E6=9E=B6?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=9B=B4=E6=8D=A2=E5=8C=85=E5=90=8D=E5=92=8C?= =?UTF-8?q?=E7=AD=BE=E5=90=8D=EF=BC=8C=E9=98=B2=E6=AD=A2=E5=85=B3=E8=81=94?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle | 17 +++++++++++++++++ android/app/xhj_bundle.jks | Bin 0 -> 2706 bytes android/build.sh | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 android/app/xhj_bundle.jks diff --git a/android/app/build.gradle b/android/app/build.gradle index 587f16e3..87be9e46 100755 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -78,6 +78,13 @@ android { keyAlias = 'upload' keyPassword 'xhj8872' } + + xhj_bundle { + storeFile file("xhj_bundle.jks") + storePassword 'xhj8872' + keyAlias = 'xhj' + keyPassword 'xhj8872' + } } // ----- BEGIN flavorDimensions (autogenerated by flutter_flavorizr) ----- @@ -135,6 +142,16 @@ android { manifestPlaceholders.JPUSH_PKGNAME = "com.xhjcn.lock" proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-xhj.pro' } + + xhj_bundle { + dimension "flavor-type" + applicationId "ltd.xhjcn.lock" + signingConfig signingConfigs.xhj_bundle + resValue "string", "app_name", "Star Lock" + manifestPlaceholders.JPUSH_PKGNAME = "ltd.xhjcn.lock" + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-xhj.pro' + } + xhj_pre { dimension "flavor-type" applicationId "com.xhjcn.lock.pre" diff --git a/android/app/xhj_bundle.jks b/android/app/xhj_bundle.jks new file mode 100644 index 0000000000000000000000000000000000000000..50f0c2c2801e642741012f385c81ac26a9fdfaed GIT binary patch literal 2706 zcma);XE+;-7RQr_S*u3Xj#X+VRBbBcHYln#(bC#Uj2Jbe%_}HXQL0KyP_^l6g?MXJ z%^Fc!drPdU4y{q+_CEJMeV_a3-Vf(F&-44A|M~bo2TI_000J^W2^`ui?1~A@$?0_Dv1brgl2tggX*(!w#zt*C=&X4# z5UcLs&b}c~)Ls8qs?#P~K}43!Zl;mMNcR%;%82rCS(MplzN0I-vqkHn(cyu8+-y1uum zGlJ^8=!MgISrQ+xPsZwAyjPJZE=GDcPDsp!Wb7ZhwzLjpTa6wa&s3Ia6}F09AV9A1 zJD7y#aT|Y;r|*DF@&Y)Tc}XceW>@VX2`P3D9XLu_zlROMc(8Jd!?n9R2@|{fUMZ`M z=#|o~Hc97&lF@LW4!o&7 zH)Zv}5T*|x-csca6ltuwX7Y~LIC#Fb4*u}N$52wP&ymZlpB&aE$g*!0wVCUf?sJJb zEWJfRmyNj4XQ?Y~rjRd&y#mA>QK;@C_w^zyRugllI;tZ`X$`@KcDHuv_R#82uX zLm9Vg^-IP!yWlJ+25H;y^^XTq&9Jmt?kHkrT)~KG|Kxh>A#O>&-smZ- zym(-a(I^;gApb(cXXsLadNmUMIK?Qm**s&*Muee9r{lW=V}ym}MqTgaOsZ`42;URl22Iv|He|Y0rJg!t1iLWZH zRg#U=a5%Rau5O-W^208j<}S74v9GJac(P;0CSB?$>rc9??InbG@|WgrX{Y2>jP?7_ zT}g+e@1lJb4MvabUV+Q~Jcg%%=vtSxnK19i?vk|*tl=A#XH`6$8XK5ut7A`Uv*Im6 zq>1cPpU9Py+C)JhePl<22%0JO)>x`Qw2mWK_dDA=QfT=#?m1%ycPwoqzIqsir?ltZ zR}|SXZvbqJ2P4>pFp~cm=mmZY%Iu;>E4VT>pDaUwTy+|`_)I>r80qWIo1+sWvieb4 zS1rP{%$+V{8CS0bvHh@Dvo^oq?7HWk`{C(y5OAgE%eqO!%PB=sVf+uPYu7HxNa*m3 z7p;P?1l(YAi}VyL@hPBwy-bPP`f3=r3b7QYhHtS2APp`1+oDbR)`^|mnFnu5nz2jf zZ#%|qzL5rthv)PQ8hhVTRJI0pitHNh9+I0DRD5z9``cRJ&Bi(F$ ztP~k#ltgaVOTnB$1);8$0Y#He<5E?@A|+B<28xYOZh@xUNfT_drgr!_xp7bd)T{P%D* zRh_#a-!z2bps-SR_UbFrS?t)(ZmD($IpzVCvf18Za#= z0UZ2$h?Rv*0N?zDu7iMpU(NAv1^B-LS~Vd$x=39SW9;&51rl{{`9<(2;{OxSoyBuD zM#m^6BSD1R!~Gt=I|QbM0hZ>%Jxa)6&$#i*bQuYI8rAA}omkMw>7S*ZuqL4VrdOq+ zWe)$0=ID_0T70R*Ofx)|_VdOw?v$-_^Y&>MOp|=)y{mm_NG`ab?1InI5qN?bOS#B zHjPFSrYesYNc=isemtzHliAiLe$dxR zE!=Vla88c2paB!*Q zRw?tBuC58DKf(u6`OWeEhf&?B{4P;6oyW**(y)8hjE_817e@qlP5N9A4B_SZo+`+l z+~xkctaICUAmwyt{t*$1jCg<`qj+cBokeknr0_Clieri+Y+(WMUtsJOT*J-3#*>l-%Rqr@C5wO2N!UH|Vxd&eB=d*5g zncSpQmpCXre?HNttO0c{KP#6Hc&-w!?R;htQ`JegjxSSR736fwFQ=DJPoJK7+S^}o zQBEyDZa6rG5pzqsew(iLf#8G(inu0Y39@6-k}7VhytoMN>?7UhQUp`E>+Lg(mG}5m zFk@D%G^r!pfg@R<9x9H==STWjo!H7uF6TA9R4k41wl_wt5q_S(Q!E`+v}UWYb*9^= zw7S7L&D1vxFW;{IZPAF`;dDRU%SfT&Pc?Mo^+X~2S3aKof9MsbKqk{;bvn#W-L{=f zufczLG1B0bLd8I^~K zlexOLbM6Iz-uR(6YD|Iw&~sY$Q`EkwCT@!5SRr(0KuAp|8uun++Hux$*D6rGTj*H7 z-`5YCa&|B@wN7g}0&0BiwM^vk3^C;>M!JNanm~kbl1`mh-L76dDA{Zoydqg9>^T|q ze#3>72l#qnItsO!l6X#Rqp)UHBlWy}yuot2q1Cjyw~oRkbbE4-$!jRNU~C27N6ZT0 z+EmZ;pKEQ(3n=ug-zAHRRx#)?Ke@x!Q~T&A7$$xd%1@h)%rc{duhID@pmzEvKtP?& zpZ*;gfpQ}aJ&rU^#sNE;0kwp}pj^NIG!T#(0EP_5lR9JDiZ5eJ|LhbN+en%2kAF%M p= Date: Mon, 20 Jan 2025 14:13:56 +0800 Subject: [PATCH 05/15] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=AF=B9=E8=AE=B2?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E5=9B=BD=E9=99=85=E5=8C=96=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lan/lan_en.json | 4 ++++ lan/lan_keys.json | 4 ++++ lan/lan_zh.json | 4 ++++ .../configuringWifi/configuringWifi_logic.dart | 13 +++---------- .../videoLog/videoLog/videoLog_logic.dart | 9 +++++++++ .../lockDetail/videoLog/videoLog/videoLog_page.dart | 8 ++++++++ lib/network/start_chart_api.dart | 4 +--- .../handle/impl/udp_talk_accept_handler.dart | 1 - .../handle/impl/udp_talk_data_handler.dart | 2 +- .../handle/impl/udp_talk_hangup_handler.dart | 4 ++-- .../other/talke_data_over_time_timer_manager.dart | 2 +- .../other/talke_ping_over_time_timer_manager.dart | 2 +- .../talke_request_over_time_timer_manager.dart | 2 +- .../startChart/views/talkView/talk_view_logic.dart | 2 +- .../startChart/views/talkView/talk_view_page.dart | 6 +++--- 15 files changed, 43 insertions(+), 24 deletions(-) diff --git a/lan/lan_en.json b/lan/lan_en.json index b9a2faec..90e0294b 100644 --- a/lan/lan_en.json +++ b/lan/lan_en.json @@ -1121,5 +1121,9 @@ "分简称": "M", "跟随系统": "Follow system", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "After reset, the lock's fingerprints will be deleted. Are you sure you want to reset it?", + "通话未接通,已挂断": "Call not connected, hung up", + "通话异常中断": "Abnormal call interruption", + "通话连接失败": "Call connection failed", + "已挂断": "Hanging up", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "After reset, the remote control of the lock will be deleted. Do you want to reset it?" } diff --git a/lan/lan_keys.json b/lan/lan_keys.json index af51e200..1c8efc7d 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -1121,5 +1121,9 @@ "分简称": "分简称", "跟随系统": "跟随系统", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "重置后,该锁的指纹都将被删除哦,确认要重置吗?", + "通话未接通,已挂断": "通话未接通,已挂断", + "通话异常中断": "通话异常中断", + "通话连接失败": "通话连接失败", + "已挂断": "已挂断", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?" } diff --git a/lan/lan_zh.json b/lan/lan_zh.json index c42ecdbf..58e4a01b 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1121,5 +1121,9 @@ "分简称": "分", "跟随系统": "跟随系统", "重置后,该锁的指纹都将被删除哦,确认要重置吗?": "重置后,该锁的指纹都将被删除哦,确认要重置吗?", + "通话未接通,已挂断": "通话未接通,已挂断", + "通话异常中断": "通话异常中断", + "通话连接失败": "通话连接失败", + "已挂断": "已挂断", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?" } diff --git a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart index c8313cf0..c0622312 100755 --- a/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart +++ b/lib/main/lockDetail/lockSet/configuringWifi/configuringWifi/configuringWifi_logic.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:flutter_blue_plus/flutter_blue_plus.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; import 'package:network_info_plus/network_info_plus.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -151,11 +152,6 @@ class ConfiguringWifiLogic extends BaseGetXController { } state.sureBtnState.value = 1; - showBlueConnetctToastTimer(action: () { - dismissEasyLoading(); - state.sureBtnState.value = 0; - }); - final GetGatewayConfigurationEntity entity = await ApiRepository.to.getGatewayConfiguration(timeout: 60); if (entity.errorCode!.codeIsSuccessful) { @@ -191,6 +187,7 @@ class ConfiguringWifiLogic extends BaseGetXController { // 如果为空,则直接赋值 state.getGatewayConfigurationStr = "{\"userPeerld\": \"$appPeerId\"}"; } + BlueManage().blueSendData(BlueManage().connectDeviceName, (BluetoothConnectionState connectionState) async { if (connectionState == BluetoothConnectionState.connected) { @@ -199,11 +196,7 @@ class ConfiguringWifiLogic extends BaseGetXController { password: state.wifiPWDController.text, gatewayConfigurationStr: state.getGatewayConfigurationStr, ); - } else if (connectionState == BluetoothConnectionState.disconnected) { - state.sureBtnState.value = 0; - if (state.ifCurrentScreen.value == true) { - showBlueConnetctToast(); - } + EasyLoading.show(); } }, isAddEquipment: true); } diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart index eb8854e0..763b8d54 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart @@ -14,6 +14,15 @@ class VideoLogLogic extends BaseGetXController { ); if (entity.errorCode!.codeIsSuccessful) { state.videoLogList.value = entity.data!; + // state.videoLogList.value.forEach((element) { + // // 过滤掉 imagesUrl 和 videoUrl 都为 null 或空字符串的项 + // element.recordList = element.recordList! + // .where((record) => + // (record.imagesUrl != null && record.imagesUrl!.isNotEmpty) || + // (record.videoUrl != null && record.videoUrl!.isNotEmpty)) + // .toList(); + // }); + state.videoLogList.refresh(); } } diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart index 472e72b6..992243f0 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart @@ -345,6 +345,14 @@ class _VideoLogPageState extends State { return Image.network( recordData.imagesUrl!, fit: BoxFit.cover, + errorBuilder: + (BuildContext context, Object error, StackTrace? stackTrace) { + // 图片加载失败时显示错误图片 + return Image.asset( + 'images/icon_unHaveData.png', // 错误图片路径 + fit: BoxFit.cover, + ); + }, ); } } diff --git a/lib/network/start_chart_api.dart b/lib/network/start_chart_api.dart index bcccaf9a..3767f6ca 100644 --- a/lib/network/start_chart_api.dart +++ b/lib/network/start_chart_api.dart @@ -11,7 +11,7 @@ class StartChartApi extends BaseProvider { // 星图url final String _startChartHost = 'http://sls1-scd.star-lock.cn:8080'; - static StartChartApi get to => Get.find(); + static StartChartApi get to => Get.put(StartChartApi()); // 星图--注册节点 Future starChartRegisterNode({ @@ -68,6 +68,4 @@ class StartChartApi extends BaseProvider { ); return response; } - - } diff --git a/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart index 22d9fdd6..a47dce87 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_accept_handler.dart @@ -29,7 +29,6 @@ class UdpTalkAcceptHandler extends ScpMessageBaseHandle // 收到同意接听回复 final GenericResp genericResp = scpMessage.Payload; if (checkGenericRespSuccess(genericResp)) { - print('收到同意接听的回复'); // 停止同意接听的重发 startChartManage.stopTalkAcceptTimer(); // 接听之后增加期望音频的接收 diff --git a/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart index a70bc4f7..95d71e0e 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart @@ -109,7 +109,7 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle void _handleVideoH264(TalkData talkData) { final TalkDataH264Frame talkDataH264Frame = TalkDataH264Frame(); talkDataH264Frame.mergeFromBuffer(talkData.content); - AppLog.log('H264 TalkData :$talkDataH264Frame'); + // AppLog.log('H264 TalkData :$talkDataH264Frame'); talkDataRepository.addTalkData(talkData); } diff --git a/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart b/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart index 86d1e9b5..26e7d368 100644 --- a/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart +++ b/lib/talk/startChart/handle/impl/udp_talk_hangup_handler.dart @@ -21,7 +21,7 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle // // 如果不是接听中,不处理通话中挂断请求 // return; // } - print('收到通话中挂断请求'); + // 回复请求 replySuccessMessage(scpMessage); talkStatus.setHangingUpDuring(); @@ -34,7 +34,7 @@ class UdpTalkHangUpHandler extends ScpMessageBaseHandle talkePingOverTimeTimerManager.cancel(); talkDataOverTimeTimerManager.cancel(); - EasyLoading.showToast('已挂断'); + EasyLoading.showToast('已挂断'.tr); Get.back(); } diff --git a/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart b/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart index 0dcc235f..c566b4d4 100644 --- a/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart +++ b/lib/talk/startChart/handle/other/talke_data_over_time_timer_manager.dart @@ -28,7 +28,7 @@ class TalkDataOverTimeTimerManager { // 超时处理函数 static void _handleTalkeDataOverTime() { - EasyLoading.showToast('通话连接失败', duration: 2000.milliseconds); + EasyLoading.showToast('通话连接失败'.tr, duration: 2000.milliseconds); // 没有通话数据,发送挂断数据 StartChartManage().sendTalkHangupMessage(); StartChartManage().stopTalkPingMessageTimer(); diff --git a/lib/talk/startChart/handle/other/talke_ping_over_time_timer_manager.dart b/lib/talk/startChart/handle/other/talke_ping_over_time_timer_manager.dart index 4d0e0601..4da40500 100644 --- a/lib/talk/startChart/handle/other/talke_ping_over_time_timer_manager.dart +++ b/lib/talk/startChart/handle/other/talke_ping_over_time_timer_manager.dart @@ -28,7 +28,7 @@ class TalkePingOverTimeTimerManager { // 超时处理函数 static void _handleTalkePingOverTime() { if (talkStatus.status == TalkStatus.answeredSuccessfully) { - EasyLoading.showToast('通话异常中断', duration: 2000.milliseconds); + EasyLoading.showToast('通话异常中断'.tr, duration: 2000.milliseconds); // 停止发送通话保持的命令 StartChartManage().stopTalkPingMessageTimer(); StartChartManage().stopTalkExpectMessageTimer(); diff --git a/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart b/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart index 687d87fe..6868bfa8 100644 --- a/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart +++ b/lib/talk/startChart/handle/other/talke_request_over_time_timer_manager.dart @@ -29,7 +29,7 @@ class TalkeRequestOverTimeTimerManager { static void _handleTalkeRequestOverTime() { if (talkStatus.status == TalkStatus.passiveCallWaitingAnswer || talkStatus.status == TalkStatus.proactivelyCallWaitingAnswer) { - EasyLoading.showToast('通话未接通,以挂断', duration: 2000.milliseconds); + EasyLoading.showToast('通话未接通,已挂断'.tr, duration: 2000.milliseconds); // 超时未接听,发送挂断请求 StartChartManage().sendTalkRejectMessage(); talkStatus.setInitializationCompleted(); diff --git a/lib/talk/startChart/views/talkView/talk_view_logic.dart b/lib/talk/startChart/views/talkView/talk_view_logic.dart index 0db7091a..cf6eb32b 100644 --- a/lib/talk/startChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/startChart/views/talkView/talk_view_logic.dart @@ -303,7 +303,7 @@ class TalkViewLogic extends BaseGetXController { bluetoothDeviceName: BlueManage().connectDeviceName, openLockCommand: messageDetail, ); - showToast('已发送开门通知'); + showToast('正在开锁中...'.tr); } int _getUTCNetTime() { diff --git a/lib/talk/startChart/views/talkView/talk_view_page.dart b/lib/talk/startChart/views/talkView/talk_view_page.dart index 6d5da3a1..2ed193db 100644 --- a/lib/talk/startChart/views/talkView/talk_view_page.dart +++ b/lib/talk/startChart/views/talkView/talk_view_page.dart @@ -307,13 +307,13 @@ class _TalkViewPageState extends State Colors.white, longPress: () async { if (state.talkStatus.value == TalkStatus.answeredSuccessfully) { - print('开始录音'); + // 启动录音 logic.startProcessingAudio(); state.isLongPressing.value = true; } }, longPressUp: () async { - print('停止录音'); + // 停止录音 logic.stopProcessingAudio(); state.isLongPressing.value = false; }, @@ -334,7 +334,7 @@ class _TalkViewPageState extends State }), bottomBtnItemWidget( 'images/main/icon_lockDetail_monitoringUnlock.png', - '开锁', + '开锁'.tr, AppColors.mainColor, onClick: () { // if (UDPManage().remoteUnlock == 1) { From e2ef3bb2e927b0a6221b34a99f023944ed9cbf4f Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 20 Jan 2025 14:28:11 +0800 Subject: [PATCH 06/15] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=AF=B9=E8=AE=B2?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E5=9B=BD=E9=99=85=E5=8C=96=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lan/lan_en.json | 60 +++++++++---------- lan/lan_keys.json | 4 +- lan/lan_zh.json | 2 +- .../views/talkView/talk_view_page.dart | 2 +- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/lan/lan_en.json b/lan/lan_en.json index 30a82507..e07a619d 100644 --- a/lan/lan_en.json +++ b/lan/lan_en.json @@ -61,7 +61,7 @@ "请输入员工账号": "Enter Employee's Account", "批量授权锁": "Grant multiple locks", "授权管理员拥有操作这把锁的重要权限,请确保只发给我你信任的人": "The authorized administrator will have majority permission to operate this lock.", - "功能开启后,你将可以通过网关远程开锁。此功能的开启和关闭只能在锁附近通过手机蓝牙进行。":"This feature allows you to Unlock the Smart Lock Remotely via a Gateway.This Feature can ONLY be Turned ON or OFF via Bluetooth.", + "功能开启后,你将可以通过网关远程开锁。此功能的开启和关闭只能在锁附近通过手机蓝牙进行。": "This feature allows you to Unlock the Smart Lock Remotely via a Gateway.This Feature can ONLY be Turned ON or OFF via Bluetooth.", "排列方式": "List Type", "早到榜": "Early List", "迟到榜": "Late List", @@ -732,18 +732,18 @@ "请选择有效日": "Please select the effective day", "公司名字长度不能小于 6 ": "The length of the company name cannot be less than 6", "已是最新版本": "No updates", - "一":"One", - "二":"Two", - "三":"Three", - "四":"Four", - "五":"Five", - "六":"Six", - "日":"Sun", - "新建短信模版":"Creat SMS template", - "新建邮件模版":"Creat email template", - "自定义短信模版":"SMS template", - "自定义邮件模版":"Email template", - "名称":"Name", + "一": "One", + "二": "Two", + "三": "Three", + "四": "Four", + "五": "Five", + "六": "Six", + "日": "Sun", + "新建短信模版": "Creat SMS template", + "新建邮件模版": "Creat email template", + "自定义短信模版": "SMS template", + "自定义邮件模版": "Email template", + "名称": "Name", "星星锁": "Star lock", "无考勤记录": "No Records", "大家干劲十足": "Everyone comes in time", @@ -780,20 +780,20 @@ "该已锁被删除": "The locked is deleted", "授权管理员只能查看和管理自己下发的钥匙、密码等权限": "The authorized admin can only manage passcodes,ekeys and etccreated by himself.", "添加授权管理员": "Create Admin", - "导出记录":"Export records", - "选择时间段":"Select time period", - "导出":"Export", - "批量导出":"Batch export", - "读取记录":"Refresh Records", - "设备":"Device", - "消息":"Messages", - "智能分析":"Intelligent analytics", - "精准识别设备事件,过滤无效信息":"Accurately identify device events and filter out invalid information", - "系统设置":"System settings", - "系统的全局配置在此项内进行设置":"The global configuration of the system is set in this item", - "导出操作记录":"Export records", - "立即查看":"View", - "导出成功":"Exported successfully", + "导出记录": "Export records", + "选择时间段": "Select time period", + "导出": "Export", + "批量导出": "Batch export", + "读取记录": "Refresh Records", + "设备": "Device", + "消息": "Messages", + "智能分析": "Intelligent analytics", + "精准识别设备事件,过滤无效信息": "Accurately identify device events and filter out invalid information", + "系统设置": "System settings", + "系统的全局配置在此项内进行设置": "The global configuration of the system is set in this item", + "导出操作记录": "Export records", + "立即查看": "View", + "导出成功": "Exported successfully", "发送钥匙": "Send ekey", "进度": "Rate", "失败": "Failed", @@ -926,7 +926,7 @@ "或发生异常事件时": "or an abnormal event occurs", "逗留达到10秒": "Stay for 10 seconds", "约1.5米": "About 1.5 meters", - "随时":"Anytime", + "随时": "Anytime", "立即录像": "Record immediately", "录像时机": "Video timing", "有人出现时录像": "Record when someone appears", @@ -1094,7 +1094,7 @@ "支持的国家": "Supported countries", "支持的国家值": "USA, Canada, UK, Australia, India, Germany, France, Italy, Spain, Japan", "操作流程": "Operation process", - "操作流程值":"1 Add a lock and gateway with the Smart lock APP \n\n2 Enable the remote unlocking function of the lock in the APP (this function is turned off by default). If you do not have this option, the lock does not support Alexa \n\n3 Add skills to Alexa and authorize them with the Smart lock APP's account and password. After the authorization is successful, you can discover devices under the account \n\n4 Locate the lock in the Alexa app, turn on the voice unlock function, and set the language password \n\n5 The lock can be operated through Alexa", + "操作流程值": "1 Add a lock and gateway with the Smart lock APP \n\n2 Enable the remote unlocking function of the lock in the APP (this function is turned off by default). If you do not have this option, the lock does not support Alexa \n\n3 Add skills to Alexa and authorize them with the Smart lock APP's account and password. After the authorization is successful, you can discover devices under the account \n\n4 Locate the lock in the Alexa app, turn on the voice unlock function, and set the language password \n\n5 The lock can be operated through Alexa", "Google Home": "Google Home", "Action name": "Action name", "ScienerSmart": "ScienerSmart", @@ -1125,7 +1125,7 @@ "通话异常中断": "Abnormal call interruption", "通话连接失败": "Call connection failed", "已挂断": "Hanging up", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "After reset, the remote control of the lock will be deleted. Do you want to reset it?" + "正在说话...": "Talking now...", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "After reset, the remote control of the lock will be deleted. Do you want to reset it?", "版本说明": "Version description" } diff --git a/lan/lan_keys.json b/lan/lan_keys.json index 5405fdc4..dbeaa4d8 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -1125,7 +1125,7 @@ "通话异常中断": "通话异常中断", "通话连接失败": "通话连接失败", "已挂断": "已挂断", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?" + "正在说话...": "正在说话...", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?", - "版本说明": "版本说明", + "版本说明": "版本说明" } diff --git a/lan/lan_zh.json b/lan/lan_zh.json index bd4dc8d8..32abc2e1 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1125,7 +1125,7 @@ "通话异常中断": "通话异常中断", "通话连接失败": "通话连接失败", "已挂断": "已挂断", - "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?" + "正在说话...": "正在说话...", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?", "版本说明": "版本说明" } diff --git a/lib/talk/startChart/views/talkView/talk_view_page.dart b/lib/talk/startChart/views/talkView/talk_view_page.dart index 2ed193db..e63a8591 100644 --- a/lib/talk/startChart/views/talkView/talk_view_page.dart +++ b/lib/talk/startChart/views/talkView/talk_view_page.dart @@ -194,7 +194,7 @@ class _TalkViewPageState extends State Icon(Icons.mic, color: Colors.white, size: 24.w), SizedBox(width: 10.w), Text( - '正在说话...', + '正在说话...'.tr, style: TextStyle( fontSize: 20.sp, color: Colors.white), ), From 1c7315857742520ace3af221d9bc65655031b6f5 Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 20 Jan 2025 16:21:41 +0800 Subject: [PATCH 07/15] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/talk/startChart/entity/scp_message.dart | 256 +++++++++++++------- 1 file changed, 167 insertions(+), 89 deletions(-) diff --git a/lib/talk/startChart/entity/scp_message.dart b/lib/talk/startChart/entity/scp_message.dart index 411d9452..48a97f3b 100644 --- a/lib/talk/startChart/entity/scp_message.dart +++ b/lib/talk/startChart/entity/scp_message.dart @@ -149,122 +149,200 @@ class ScpMessage { static ScpMessage deserialize(Uint8List bytes) { final message = ScpMessage(); + final length = bytes.length; int offset = 0; - // String hexString = - // bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); - // // _log(text: 'result bytes hex: ${hexString}'); - // _log( - // text: - // '\n result bytes hex: ${hexString} \n payload hex: ${hexString.substring(210)}'); + // 提前检查字节数组长度是否足够 + if (length < 4 + 1 + 2 + 1 + 1 + 44 + 44 + 2 + 2 + 4) { + throw FormatException("Invalid message length"); + } + + // 使用 ByteData 读取多字节数据 + final byteData = ByteData.sublistView(bytes); // ProtocolFlag (4 bytes) - if (bytes.length - offset >= 4) { - message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4)); - offset += 4; - } else { - throw FormatException("Invalid ProtocolFlag length"); - } + message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4)); + offset += 4; // MessageType (1 byte) - if (bytes.length - offset >= 1) { - message.MessageType = bytes[offset]; - offset += 1; - } else { - throw FormatException("Invalid MessageType length"); - } + message.MessageType = bytes[offset]; + offset += 1; // MessageId (2 bytes, little-endian) - if (bytes.length - offset >= 2) { - message.MessageId = (bytes[offset + 1] << 8) | bytes[offset]; - offset += 2; - } else { - throw FormatException("Invalid MessageId length"); - } + message.MessageId = byteData.getUint16(offset, Endian.little); + offset += 2; // SpTotal (1 byte) - if (bytes.length - offset >= 1) { - message.SpTotal = bytes[offset]; - offset += 1; - } else { - throw FormatException("Invalid SpTotal length"); - } + message.SpTotal = bytes[offset]; + offset += 1; // SpIndex (1 byte) - if (bytes.length - offset >= 1) { - message.SpIndex = bytes[offset]; - offset += 1; - } else { - throw FormatException("Invalid SpIndex length"); - } + message.SpIndex = bytes[offset]; + offset += 1; - // FromPeerId (字符串,长度固定为44字节) - if (bytes.length - offset >= 44) { - message.FromPeerId = - utf8.decode(bytes.sublist(offset, offset + 44)).trimRight(); - offset += 44; - } else { - throw FormatException("Invalid FromPeerId length"); - } + // FromPeerId (44 bytes) + message.FromPeerId = + utf8.decode(bytes.sublist(offset, offset + 44)).trimRight(); + offset += 44; - // ToPeerId (字符串,长度固定为44字节) - if (bytes.length - offset >= 44) { - message.ToPeerId = - utf8.decode(bytes.sublist(offset, offset + 44)).trimRight(); - offset += 44; - } else { - throw FormatException("Invalid ToPeerId length"); - } + // ToPeerId (44 bytes) + message.ToPeerId = + utf8.decode(bytes.sublist(offset, offset + 44)).trimRight(); + offset += 44; // PayloadType (2 bytes, little-endian) - if (bytes.length - offset >= 2) { - message.PayloadType = (bytes[offset + 1] << 8) | bytes[offset]; - offset += 2; - } else { - throw FormatException("Invalid PayloadType length"); - } + message.PayloadType = byteData.getUint16(offset, Endian.little); + offset += 2; // PayloadCRC (2 bytes, little-endian) - if (bytes.length - offset >= 2) { - message.PayloadCRC = (bytes[offset + 1] << 8) | bytes[offset]; - offset += 2; - } else { - throw FormatException("Invalid PayloadCRC length"); - } + message.PayloadCRC = byteData.getUint16(offset, Endian.little); + offset += 2; // PayloadLength (4 bytes, little-endian) - if (bytes.length - offset >= 4) { - message.PayloadLength = (bytes[offset] | - (bytes[offset + 1] << 8) | - (bytes[offset + 2] << 16) | - (bytes[offset + 3] << 24)); // 修正为 little-endian - offset += 4; - } else { - throw FormatException("Invalid PayloadLength length"); - } + message.PayloadLength = byteData.getUint32(offset, Endian.little); + offset += 4; - // 处理其他类型的Payload - if (message.PayloadLength != null && - bytes.length - offset >= message.PayloadLength!) { - final sublist = bytes.sublist(offset, offset + message.PayloadLength!); - offset += message.PayloadLength!; - message.Payload = _handlePayLoad( - payloadType: message.PayloadType ?? 0, - messageType: message.MessageType ?? 0, - byte: sublist, - offset: offset, - PayloadLength: message.PayloadLength, - spIndex: message.SpIndex, - spTotal: message.SpTotal, - messageId: message.MessageId, - ); - } else { + // 检查 Payload 长度是否有效 + if (message.PayloadLength == null || + length - offset < message.PayloadLength!) { throw FormatException("Invalid Payload or PayloadLength"); } + // 处理 Payload + final payloadBytes = bytes.sublist(offset, offset + message.PayloadLength!); + offset += message.PayloadLength!; + message.Payload = _handlePayLoad( + payloadType: message.PayloadType ?? 0, + messageType: message.MessageType ?? 0, + byte: payloadBytes, + offset: offset, + PayloadLength: message.PayloadLength, + spIndex: message.SpIndex, + spTotal: message.SpTotal, + messageId: message.MessageId, + ); + return message; } + // static ScpMessage deserialize(Uint8List bytes) { + // final message = ScpMessage(); + // int offset = 0; + // + // // String hexString = + // // bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); + // // // _log(text: 'result bytes hex: ${hexString}'); + // // _log( + // // text: + // // '\n result bytes hex: ${hexString} \n payload hex: ${hexString.substring(210)}'); + // + // // ProtocolFlag (4 bytes) + // if (bytes.length - offset >= 4) { + // message.ProtocolFlag = utf8.decode(bytes.sublist(offset, offset + 4)); + // offset += 4; + // } else { + // throw FormatException("Invalid ProtocolFlag length"); + // } + // + // // MessageType (1 byte) + // if (bytes.length - offset >= 1) { + // message.MessageType = bytes[offset]; + // offset += 1; + // } else { + // throw FormatException("Invalid MessageType length"); + // } + // + // // MessageId (2 bytes, little-endian) + // if (bytes.length - offset >= 2) { + // message.MessageId = (bytes[offset + 1] << 8) | bytes[offset]; + // offset += 2; + // } else { + // throw FormatException("Invalid MessageId length"); + // } + // + // // SpTotal (1 byte) + // if (bytes.length - offset >= 1) { + // message.SpTotal = bytes[offset]; + // offset += 1; + // } else { + // throw FormatException("Invalid SpTotal length"); + // } + // + // // SpIndex (1 byte) + // if (bytes.length - offset >= 1) { + // message.SpIndex = bytes[offset]; + // offset += 1; + // } else { + // throw FormatException("Invalid SpIndex length"); + // } + // + // // FromPeerId (字符串,长度固定为44字节) + // if (bytes.length - offset >= 44) { + // message.FromPeerId = + // utf8.decode(bytes.sublist(offset, offset + 44)).trimRight(); + // offset += 44; + // } else { + // throw FormatException("Invalid FromPeerId length"); + // } + // + // // ToPeerId (字符串,长度固定为44字节) + // if (bytes.length - offset >= 44) { + // message.ToPeerId = + // utf8.decode(bytes.sublist(offset, offset + 44)).trimRight(); + // offset += 44; + // } else { + // throw FormatException("Invalid ToPeerId length"); + // } + // + // // PayloadType (2 bytes, little-endian) + // if (bytes.length - offset >= 2) { + // message.PayloadType = (bytes[offset + 1] << 8) | bytes[offset]; + // offset += 2; + // } else { + // throw FormatException("Invalid PayloadType length"); + // } + // + // // PayloadCRC (2 bytes, little-endian) + // if (bytes.length - offset >= 2) { + // message.PayloadCRC = (bytes[offset + 1] << 8) | bytes[offset]; + // offset += 2; + // } else { + // throw FormatException("Invalid PayloadCRC length"); + // } + // + // // PayloadLength (4 bytes, little-endian) + // if (bytes.length - offset >= 4) { + // message.PayloadLength = (bytes[offset] | + // (bytes[offset + 1] << 8) | + // (bytes[offset + 2] << 16) | + // (bytes[offset + 3] << 24)); // 修正为 little-endian + // offset += 4; + // } else { + // throw FormatException("Invalid PayloadLength length"); + // } + // + // // 处理其他类型的Payload + // if (message.PayloadLength != null && + // bytes.length - offset >= message.PayloadLength!) { + // final sublist = bytes.sublist(offset, offset + message.PayloadLength!); + // offset += message.PayloadLength!; + // message.Payload = _handlePayLoad( + // payloadType: message.PayloadType ?? 0, + // messageType: message.MessageType ?? 0, + // byte: sublist, + // offset: offset, + // PayloadLength: message.PayloadLength, + // spIndex: message.SpIndex, + // spTotal: message.SpTotal, + // messageId: message.MessageId, + // ); + // } else { + // throw FormatException("Invalid Payload or PayloadLength"); + // } + // + // return message; + // } + // 根据不同payloadType序列化对应的payload结构体 static dynamic _handlePayLoad({ required int payloadType, From 9527f8e019eda9fb659270dae8fb6cd3328f9e78 Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 20 Jan 2025 16:22:01 +0800 Subject: [PATCH 08/15] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E4=B8=AD=E5=9B=BE=E7=89=87=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E6=98=BE=E7=A4=BA=E7=9A=84=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main/lockDetail/doorLockLog/doorLockLog_page.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart index dc1cd3eb..3634ae4e 100755 --- a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart +++ b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart @@ -406,6 +406,14 @@ class _DoorLockLogPageState extends State with RouteAware { return Image.network( recordData.imagesUrl!, fit: BoxFit.cover, + errorBuilder: + (BuildContext context, Object error, StackTrace? stackTrace) { + // 图片加载失败时显示错误图片 + return Image.asset( + 'images/icon_unHaveData.png', // 错误图片路径 + fit: BoxFit.cover, + ); + }, ); } From 9504a97bde7c9678e70b5dcc3d86cd102e25be3e Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 20 Jan 2025 16:23:01 +0800 Subject: [PATCH 09/15] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E5=AF=B9=E8=AE=B2?= =?UTF-8?q?=E6=97=B6=E7=9A=84=E9=80=9A=E8=AF=9D=E8=AE=A1=E6=97=B6=E3=80=81?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=AF=B9=E8=AE=B2=E6=97=B6=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E6=97=8B=E8=BD=AC=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/talkView/talk_view_logic.dart | 21 ++++++---- .../views/talkView/talk_view_page.dart | 38 ++++++++++++++++--- .../views/talkView/talk_view_state.dart | 3 +- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/lib/talk/startChart/views/talkView/talk_view_logic.dart b/lib/talk/startChart/views/talkView/talk_view_logic.dart index cf6eb32b..310a3c4d 100644 --- a/lib/talk/startChart/views/talkView/talk_view_logic.dart +++ b/lib/talk/startChart/views/talkView/talk_view_logic.dart @@ -50,7 +50,6 @@ class TalkViewLogic extends BaseGetXController { int audioFrameIntervalMs = 20; // 初始帧间隔设置为45毫秒(约22FPS) int minFrameIntervalMs = 30; // 最小帧间隔(约33 FPS) int maxFrameIntervalMs = 100; // 最大帧间隔(约1 FPS) - // int maxFrameIntervalMs = 100; // 最大帧间隔(约10 FPS) /// 初始化音频播放器 void _initFlutterPcmSound() { @@ -118,6 +117,17 @@ class TalkViewLogic extends BaseGetXController { case TalkStatus.end: _handleInvalidTalkStatus(); break; + case TalkStatus.answeredSuccessfully: + state.oneMinuteTimeTimer?.cancel(); // 取消旧定时器 + state.oneMinuteTimeTimer ??= + Timer.periodic(const Duration(seconds: 1), (Timer t) { + state.oneMinuteTime.value++; + if (state.oneMinuteTime.value >= 60) { + t.cancel(); // 取消定时器 + state.oneMinuteTime.value = 0; + } + }); + break; default: // 其他状态的处理 break; @@ -160,12 +170,6 @@ class TalkViewLogic extends BaseGetXController { /// 动态调整帧间隔 void _adjustFrameInterval() { int newFrameIntervalMs = frameIntervalMs; - if (state.networkStatus.value == NetworkStatus.lagging) { - bufferSize = 60; // 增大缓冲区 - } else { - bufferSize = 40; // 恢复默认缓冲区大小 - } - if (state.videoBuffer.length < 10 && frameIntervalMs < maxFrameIntervalMs) { // 如果缓冲区较小且帧间隔小于最大值,则增加帧间隔 frameIntervalMs += 5; @@ -442,7 +446,8 @@ class TalkViewLogic extends BaseGetXController { _syncTimer = null; // 释放定时器引用 _audioTimer?.cancel(); _audioTimer = null; // 释放定时器引用 - + state.oneMinuteTimeTimer?.cancel(); + state.oneMinuteTimeTimer = null; stopProcessingAudio(); super.onClose(); } diff --git a/lib/talk/startChart/views/talkView/talk_view_page.dart b/lib/talk/startChart/views/talkView/talk_view_page.dart index e63a8591..604b0f30 100644 --- a/lib/talk/startChart/views/talkView/talk_view_page.dart +++ b/lib/talk/startChart/views/talkView/talk_view_page.dart @@ -107,13 +107,13 @@ class _TalkViewPageState extends State canPop: false, child: RepaintBoundary( key: state.globalKey, - child: Transform.rotate( - angle: - state.rotateAngle.value * (pi / 180), // 旋转 90 度 - child: Transform.scale( - scale: scale, // 动态计算的缩放比例 + child: SizedBox.expand( + child: RotatedBox( + quarterTurns: -1, child: Image.memory( state.listData.value, + width: ScreenUtil().scaleWidth, + height: ScreenUtil().scaleHeight, gaplessPlayback: true, fit: BoxFit.cover, filterQuality: FilterQuality.high, @@ -139,6 +139,34 @@ class _TalkViewPageState extends State style: TextStyle(color: Colors.black, fontSize: 26.sp), )) : Container()), + Obx( + () => state.listData.value.isNotEmpty + ? Positioned( + top: ScreenUtil().statusBarHeight + 75.h, + width: 1.sw, + child: Obx( + () { + final String sec = (state.oneMinuteTime.value % 60) + .toString() + .padLeft(2, '0'); + final String min = (state.oneMinuteTime.value ~/ 60) + .toString() + .padLeft(2, '0'); + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '$min:$sec', + style: TextStyle( + fontSize: 26.sp, color: Colors.white), + ), + ], + ); + }, + ), + ) + : Container(), + ), Positioned( bottom: 10.w, child: Container( diff --git a/lib/talk/startChart/views/talkView/talk_view_state.dart b/lib/talk/startChart/views/talkView/talk_view_state.dart index ccf85967..21d6db4c 100644 --- a/lib/talk/startChart/views/talkView/talk_view_state.dart +++ b/lib/talk/startChart/views/talkView/talk_view_state.dart @@ -37,8 +37,7 @@ class TalkViewState { RxList listAudioData = [].obs; //得到的音频流字节数据 GlobalKey globalKey = GlobalKey(); - late Timer oneMinuteTimeTimer = - Timer(const Duration(seconds: 1), () {}); // 定时器超过60秒关闭当前界面 + Timer? oneMinuteTimeTimer; // 定时器超过60秒关闭当前界面 RxInt oneMinuteTime = 0.obs; // 定时器秒数 // 定时器如果发送了接听的命令 而没收到回复就每秒重复发送10次 From c8b305a4f240eaa21ea2a7b3d0ff6d5b766e92af Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 21 Jan 2025 10:24:47 +0800 Subject: [PATCH 10/15] =?UTF-8?q?fix:=E8=A7=86=E9=A2=91=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=80=BB=E8=BE=91=E3=80=81=E8=A7=86=E9=A2=91?= =?UTF-8?q?/=E5=9B=BE=E7=89=87=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gradle/wrapper/gradle-wrapper.properties | 3 +- lan/lan_en.json | 1 + lan/lan_keys.json | 1 + lan/lan_zh.json | 1 + .../doorLockLog/doorLockLog_page.dart | 28 +- .../editVideoLog/editVideoLog_logic.dart | 71 +++- .../editVideoLog/editVideoLog_page.dart | 391 ++++++++++++++---- .../videoLog/videoLog/videoLog_entity.dart | 26 +- .../videoLog/videoLog/videoLog_logic.dart | 43 +- .../videoLog/videoLog/videoLog_page.dart | 43 +- .../videoLogDetail/controlsOverlay_page.dart | 7 +- .../videoLogDetail/videoLogDetail_page.dart | 75 ++-- .../widget/full_screenImage_page.dart | 14 +- .../videoLog/widget/video_thumbnail.dart | 19 +- 14 files changed, 540 insertions(+), 183 deletions(-) diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index cb24abda..0971a052 100755 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +#distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-7.4-all.zip diff --git a/lan/lan_en.json b/lan/lan_en.json index e07a619d..6d57fbc0 100644 --- a/lan/lan_en.json +++ b/lan/lan_en.json @@ -1126,6 +1126,7 @@ "通话连接失败": "Call connection failed", "已挂断": "Hanging up", "正在说话...": "Talking now...", + "下载完成,请到相册查看": "Download completed, please go to the album to view", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "After reset, the remote control of the lock will be deleted. Do you want to reset it?", "版本说明": "Version description" } diff --git a/lan/lan_keys.json b/lan/lan_keys.json index dbeaa4d8..d99c1b05 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -1126,6 +1126,7 @@ "通话连接失败": "通话连接失败", "已挂断": "已挂断", "正在说话...": "正在说话...", + "下载完成,请到相册查看": "下载完成,请到相册查看", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?", "版本说明": "版本说明" } diff --git a/lan/lan_zh.json b/lan/lan_zh.json index 32abc2e1..e26b13ce 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1126,6 +1126,7 @@ "通话连接失败": "通话连接失败", "已挂断": "已挂断", "正在说话...": "正在说话...", + "下载完成,请到相册查看": "下载完成,请到相册查看", "重置后,该锁的遥控都将被删除哦,确认要重置吗?": "重置后,该锁的遥控都将被删除哦,确认要重置吗?", "版本说明": "版本说明" } diff --git a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart index 3634ae4e..fca6b402 100755 --- a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart +++ b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart @@ -403,17 +403,23 @@ class _DoorLockLogPageState extends State with RouteAware { } _buildImageItem(RecordListData recordData) { - return Image.network( - recordData.imagesUrl!, - fit: BoxFit.cover, - errorBuilder: - (BuildContext context, Object error, StackTrace? stackTrace) { - // 图片加载失败时显示错误图片 - return Image.asset( - 'images/icon_unHaveData.png', // 错误图片路径 - fit: BoxFit.cover, - ); - }, + return RotatedBox( + quarterTurns: -1, + child: Image.network( + recordData.imagesUrl!, + fit: BoxFit.cover, + errorBuilder: + (BuildContext context, Object error, StackTrace? stackTrace) { + // 图片加载失败时显示错误图片 + return RotatedBox( + quarterTurns: -1, + child: Image.asset( + 'images/icon_unHaveData.png', // 错误图片路径 + fit: BoxFit.cover, + ), + ); + }, + ), ); } diff --git a/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_logic.dart b/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_logic.dart index f6d1dacd..8ad36896 100755 --- a/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_logic.dart +++ b/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_logic.dart @@ -1,4 +1,10 @@ +import 'dart:io'; + +import 'package:dio/dio.dart'; import 'package:get/get.dart'; +import 'package:image_gallery_saver/image_gallery_saver.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; @@ -9,18 +15,20 @@ class EditVideoLogLogic extends BaseGetXController { EditVideoLogState state = EditVideoLogState(); Future deleteLockCloudStorageList() async { - final VersionUndateEntity entity = await ApiRepository.to.deleteLockCloudStorageList( + final VersionUndateEntity entity = + await ApiRepository.to.deleteLockCloudStorageList( recordIds: state.selectVideoLogList.value.map((e) => e.recordId).toList(), ); if (entity.errorCode!.codeIsSuccessful) { - state.selectVideoLogList.value.clear(); showToast('删除成功'.tr); - getLockCloudStorageList(); + await getLockCloudStorageList(); + state.selectVideoLogList.clear(); } } Future getLockCloudStorageList() async { - final VideoLogEntity entity = await ApiRepository.to.getLockCloudStorageList( + final VideoLogEntity entity = + await ApiRepository.to.getLockCloudStorageList( lockId: state.getLockId.value, ); if (entity.errorCode!.codeIsSuccessful) { @@ -28,4 +36,59 @@ class EditVideoLogLogic extends BaseGetXController { state.videoLogList.refresh(); } } + + Future downloadAndSaveToGallery(String url, String fileName) async { + try { + // 请求存储权限 + if (await _requestPermission()) { + final dio = Dio(); + final directory = await getTemporaryDirectory(); + final filePath = '${directory.path}/$fileName'; + + // 下载文件 + await dio.download( + url, + filePath, + onReceiveProgress: (received, total) { + if (total != -1) { + final progress = (received / total) * 100; + print('下载进度: $progress%'); + } + }, + ); + + // 保存到图库 + if (fileName.endsWith('.jpg') || fileName.endsWith('.png')) { + // 保存图片 + final result = await ImageGallerySaver.saveFile(filePath); + if (result['isSuccess']) { + print('图片已保存到图库'); + } else { + print('图片保存失败'); + } + } else if (fileName.endsWith('.mp4')) { + // 保存视频 + final result = await ImageGallerySaver.saveFile(filePath); + if (result['isSuccess']) { + print('视频已保存到图库'); + } else { + print('视频保存失败'); + } + } + + // 删除临时文件 + await File(filePath).delete(); + } else { + print('存储权限被拒绝'); + } + } catch (e) { + print('下载或保存文件失败: $e'); + } + } + +// 请求存储权限 + Future _requestPermission() async { + final status = await Permission.storage.request(); + return status.isGranted; + } } diff --git a/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart b/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart index d7957341..c52a90d5 100755 --- a/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart +++ b/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart @@ -1,10 +1,12 @@ - import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/appRouters.dart'; import 'package:star_lock/main/lockDetail/videoLog/editVideoLog/editVideoLog_state.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; import 'package:star_lock/tools/dateTool.dart'; import '../../../../app_settings/app_colors.dart'; @@ -97,6 +99,7 @@ class _EditVideoLogPageState extends State { double itemW = (1.sw - 15.w * 4) / 3; double itemH = (1.sw - 15.w * 4) / 3 + 40.h; + Widget mainListView(int index, CloudStorageData itemData) { return GridView.builder( padding: EdgeInsets.only(left: 15.w, right: 15.w), @@ -114,116 +117,322 @@ class _EditVideoLogPageState extends State { childAspectRatio: itemW / itemH), itemBuilder: (BuildContext context, int index) { final RecordListData recordData = itemData.recordList![index]; - return videoItem(recordData, index); + return videoItem(recordData); }, ); } - Widget videoItem(RecordListData recordData, int index) { - return Container( - width: itemW, - height: itemH, - color: Colors.white, - child: GestureDetector( - onTap: () { - recordData.isSelect = !recordData.isSelect!; - if (recordData.isSelect! == true) { - state.selectVideoLogList.add(recordData); - } else { - state.selectVideoLogList.remove(recordData); - } - setState(() {}); - }, - child: Stack( - children: [ - Column( - children: [ - Container( - width: itemW, - height: itemW, - margin: const EdgeInsets.all(0), - color: Colors.white, - child: ClipRRect( - borderRadius: BorderRadius.circular(10.w), - child: Image( - fit: BoxFit.cover, - image: Image.network(recordData.imagesUrl ?? - 'images/icon_video_placeholder.jpg') - .image), - ), - ), - SizedBox(height: 5.h), - Text( - DateTool() - .dateToYMDHNString(recordData.operateDate.toString()), - textAlign: TextAlign.center, - style: TextStyle(fontSize: 18.sp)) - ], - ), - Positioned( - top: 0.w, - right: 0.w, - child: Image( - width: 36.w, - height: 36.w, - image: state.selectVideoLogList.value.contains(recordData) - ? const AssetImage('images/icon_round_select.png') - : const AssetImage('images/icon_round_unSelect.png'))) - ], - )), - ); - } + // Widget videoItem(RecordListData recordData, int index) { + // return Container( + // width: itemW, + // height: itemH, + // color: Colors.white, + // child: GestureDetector( + // onTap: () { + // recordData.isSelect = !recordData.isSelect!; + // if (recordData.isSelect! == true) { + // state.selectVideoLogList.add(recordData); + // } else { + // state.selectVideoLogList.remove(recordData); + // } + // setState(() {}); + // }, + // child: Stack( + // children: [ + // Column( + // children: [ + // Container( + // width: itemW, + // height: itemW, + // margin: const EdgeInsets.all(0), + // color: Colors.white, + // child: ClipRRect( + // borderRadius: BorderRadius.circular(10.w), + // child: Image( + // fit: BoxFit.cover, + // image: Image.network(recordData.imagesUrl ?? + // 'images/icon_video_placeholder.jpg') + // .image), + // ), + // ), + // SizedBox(height: 5.h), + // Text( + // DateTool() + // .dateToYMDHNString(recordData.operateDate.toString()), + // textAlign: TextAlign.center, + // style: TextStyle(fontSize: 18.sp)) + // ], + // ), + // Positioned( + // top: 0.w, + // right: 0.w, + // child: Image( + // width: 36.w, + // height: 36.w, + // image: state.selectVideoLogList.value.contains(recordData) + // ? const AssetImage('images/icon_round_select.png') + // : const AssetImage('images/icon_round_unSelect.png'))) + // ], + // )), + // ); + // } Widget bottomBottomBtnWidget() { return SizedBox( width: 1.sw, - child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + child: + Row(mainAxisAlignment: MainAxisAlignment.center, children: [ bottomBtnItemWidget( - 'images/main/icon_lockDetail_monitoringDownloadVideo.png', - '下载'.tr, - Colors.white, () { - if (state.selectVideoLogList.value.isNotEmpty) { - Get.toNamed(Routers.videoLogDownLoadPage, arguments: >{ - 'downloadVideoLogList': state.selectVideoLogList.value - }); - } else { - logic.showToast('请选择要下载的视频'); - } - }), + 'images/main/icon_lockDetail_monitoringDownloadVideo.png', + '下载'.tr, + Colors.white, + _onDownLoadClick, + ), SizedBox(width: 100.w), bottomBtnItemWidget( - 'images/main/icon_lockDetail_monitoringDeletVideo.png', - '删除'.tr, - AppColors.mainColor, () { - if (state.selectVideoLogList.value.isNotEmpty) { - logic.deleteLockCloudStorageList(); - } else { - logic.showToast('请选择要删除的视频'.tr); - } - }) + 'images/main/icon_lockDetail_monitoringDeletVideo.png', + '删除'.tr, + AppColors.mainColor, + _onDelClick, + ) ]), ); } + Future _onDownLoadClick() async { + if (state.selectVideoLogList.value.isNotEmpty) { + double _progress = 0.0; + // 开始下载 + // 显示进度条 + EasyLoading.showProgress(_progress, status: '加载数据中'.tr); + + // 模拟进度更新 + for (int i = 0; i <= state.selectVideoLogList.length - 1; i++) { + final item = state.selectVideoLogList.value[i]; + + // 判断 imagesUrl 是否为空 + if (item.imagesUrl != null && item.imagesUrl!.isNotEmpty) { + await logic.downloadAndSaveToGallery(item.imagesUrl!, 'image_$i.jpg'); + } + + // 判断 videoUrl 是否为空 + if (item.videoUrl != null && item.videoUrl!.isNotEmpty) { + await logic.downloadAndSaveToGallery(item.videoUrl!, 'video_$i.mp4'); + } + + // 更新进度 + _progress = (i + 1) / state.selectVideoLogList.length; + EasyLoading.showProgress(_progress, status: '加载数据中'.tr); + } + + // 加载完成后隐藏进度条 + EasyLoading.dismiss(); + EasyLoading.showSuccess('下载完成,请到相册查看'.tr); + state.selectVideoLogList.clear(); + setState(() {}); + // Get.toNamed(Routers.videoLogDownLoadPage, + // arguments: >{ + // 'downloadVideoLogList': state.selectVideoLogList.value + // }); + } else { + logic.showToast('请选择要下载的视频'); + } + } + + Future _onDelClick() async { + if (state.selectVideoLogList.value.isNotEmpty) { + // 弹出自定义确认对话框 + bool confirmDelete = await showDialog( + context: context, + builder: (BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + '确认删除'.tr, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 16), + Text('确定要删除选中的视频吗?'.tr), + SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () { + // 用户点击取消,返回 false + Navigator.of(context).pop(false); + }, + child: Text('取消'.tr), + ), + SizedBox(width: 8), + ElevatedButton( + onPressed: () { + // 用户点击确认,返回 true + Navigator.of(context).pop(true); + }, + child: Text('确认'.tr), + ), + ], + ), + ], + ), + ), + ); + }, + ); + + // 如果用户确认删除,执行删除逻辑 + if (confirmDelete == true) { + await logic.deleteLockCloudStorageList(); + } + } else { + logic.showToast('请选择要删除的视频'.tr); + } + } + Widget bottomBtnItemWidget( - String iconUrl, String name, Color backgroundColor, Function() onClick) { + String iconUrl, + String name, + Color backgroundColor, + Future Function() onClick, + ) { final double wh = 40.w; return GestureDetector( onTap: onClick, child: SizedBox( - height: 140.h, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox(height: 30.w), - Image.asset(iconUrl, width: wh, height: wh, fit: BoxFit.fitWidth), - SizedBox(height: 10.w), - Expanded( - child: Text(name, - style: TextStyle(fontSize: 22.sp), - textAlign: TextAlign.center)) - ], - )), + height: 140.h, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: 30.w), + Image.asset(iconUrl, width: wh, height: wh, fit: BoxFit.fitWidth), + SizedBox(height: 10.w), + Expanded( + child: Text(name, + style: TextStyle(fontSize: 22.sp), + textAlign: TextAlign.center), + ) + ], + ), + ), + ); + } + + Widget videoItem(RecordListData recordData) { + return GestureDetector( + onTap: () { + if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) { + Get.toNamed(Routers.videoLogDetailPage, arguments: { + 'recordData': recordData, + 'videoDataList': state.videoLogList.value + }); + } else if (recordData.imagesUrl != null && + recordData.imagesUrl!.isNotEmpty) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => FullScreenImagePage( + imageUrl: recordData.imagesUrl!, + ), + ), + ); + } + }, + child: Stack( + children: [ + SizedBox( + width: itemW, + height: itemH, + child: Column( + children: [ + Container( + width: itemW, + height: itemW, + margin: const EdgeInsets.all(0), + color: Colors.white, + child: ClipRRect( + borderRadius: BorderRadius.circular(10.w), + child: _buildImageOrVideoItem(recordData), + ), + ), + SizedBox(height: 5.h), + Text( + DateTool() + .dateToYMDHNString(recordData.operateDate.toString()), + textAlign: TextAlign.center, + style: TextStyle(fontSize: 18.sp), + ) + ], + ), + ), + Positioned( + top: 0.w, + right: 0.w, + child: GestureDetector( + onTap: () { + recordData.isSelect = !recordData.isSelect!; + if (recordData.isSelect! == true) { + state.selectVideoLogList.add(recordData); + } else { + state.selectVideoLogList.remove(recordData); + } + setState(() {}); + }, + child: Image( + width: 36.w, + height: 36.w, + image: state.selectVideoLogList.value.contains(recordData) + ? const AssetImage('images/icon_round_select.png') + : const AssetImage('images/icon_round_unSelect.png'), + ), + ), + ) + ], + ), + ); + } + + _buildImageOrVideoItem(RecordListData recordData) { + if (recordData.videoUrl != null && recordData.videoUrl!.isNotEmpty) { + return _buildVideoItem(recordData); + } else { + return _buildImageItem(recordData); + } + } + + _buildVideoItem(RecordListData recordData) { + return VideoThumbnail(videoUrl: recordData.videoUrl!); + } + + _buildImageItem(RecordListData recordData) { + return RotatedBox( + quarterTurns: -1, + child: Image.network( + recordData.imagesUrl!, + fit: BoxFit.cover, + errorBuilder: + (BuildContext context, Object error, StackTrace? stackTrace) { + // 图片加载失败时显示错误图片 + return RotatedBox( + quarterTurns: -1, + child: Image.asset( + 'images/icon_unHaveData.png', // 错误图片路径 + fit: BoxFit.cover, + ), + ); + }, + ), ); } } diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_entity.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_entity.dart index 9e8dd9a2..17c9514b 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_entity.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_entity.dart @@ -1,3 +1,6 @@ +import 'dart:convert'; +import 'dart:typed_data'; + class VideoLogEntity { int? errorCode; String? description; @@ -61,21 +64,28 @@ class RecordListData { int? operateDate; String? imagesUrl; String? videoUrl; + Uint8List? thumbnailData; // 将视频封面改为 Uint8List 类型 int? recordType; bool? isSelect = false; - RecordListData( - {this.recordId, - this.operateDate, - this.imagesUrl, - this.videoUrl, - this.recordType}); + RecordListData({ + this.recordId, + this.operateDate, + this.imagesUrl, + this.videoUrl, + this.thumbnailData, // 视频封面数据 + this.recordType, + }); RecordListData.fromJson(Map json) { recordId = json['recordId']; operateDate = json['operateDate']; imagesUrl = json['imagesUrl']; videoUrl = json['videoUrl']; + // 如果 JSON 中包含 base64 编码的图片数据,可以解码为 Uint8List + if (json['thumbnailData'] != null) { + thumbnailData = base64Decode(json['thumbnailData']); + } recordType = json['recordType']; } @@ -85,6 +95,10 @@ class RecordListData { data['operateDate'] = operateDate; data['imagesUrl'] = imagesUrl; data['videoUrl'] = videoUrl; + // 将 Uint8List 编码为 base64 字符串 + if (thumbnailData != null) { + data['thumbnailData'] = base64Encode(thumbnailData!); + } data['recordType'] = recordType; return data; } diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart index 763b8d54..41124660 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; +import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; @@ -14,19 +15,45 @@ class VideoLogLogic extends BaseGetXController { ); if (entity.errorCode!.codeIsSuccessful) { state.videoLogList.value = entity.data!; - // state.videoLogList.value.forEach((element) { - // // 过滤掉 imagesUrl 和 videoUrl 都为 null 或空字符串的项 - // element.recordList = element.recordList! - // .where((record) => - // (record.imagesUrl != null && record.imagesUrl!.isNotEmpty) || - // (record.videoUrl != null && record.videoUrl!.isNotEmpty)) - // .toList(); - // }); + state.videoLogList.value.forEach((element) { + // 过滤掉 imagesUrl 和 videoUrl 都为 null 或空字符串的项 + element.recordList = element.recordList! + .where((record) => + (record.imagesUrl != null && record.imagesUrl!.isNotEmpty) || + (record.videoUrl != null && record.videoUrl!.isNotEmpty)) + .toList(); + + // // 为 videoUrl 不为空的项设置封面 + // for (var record in element.recordList!) { + // if (record.videoUrl != null && record.videoUrl!.isNotEmpty) { + // _setVideoThumbnail(record); // 设置视频封面 + // } + // } + }); state.videoLogList.refresh(); } } + // Future _setVideoThumbnail(RecordListData record) async { + // try { + // final thumbnailData = await getVideoThumbnail(record.videoUrl!); + // record.thumbnailData = thumbnailData; // 设置视频封面数据 + // } catch (e) { + // print('获取视频封面失败: $e'); + // } + // } + // + // Future getVideoThumbnail(String videoUrl) async { + // final thumbnail = await VideoThumbnail.thumbnailData( + // video: videoUrl, + // imageFormat: ImageFormat.JPEG, + // maxWidth: 128, // 缩略图的最大宽度 + // quality: 25, // 缩略图的质量(0-100) + // ); + // return thumbnail; + // } + @override onReady() { super.onReady(); diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart index 992243f0..994f7383 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart @@ -228,15 +228,18 @@ class _VideoLogPageState extends State { child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(state.isNavLocal.value == true ? '已下载'.tr : '全部视频'.tr, - style: TextStyle(fontSize: 26.sp, fontWeight: FontWeight.w500)), + Text( + state.isNavLocal.value == true ? '已下载'.tr : '全部视频'.tr, + style: TextStyle(fontSize: 26.sp, fontWeight: FontWeight.w500), + ), Expanded(child: SizedBox(width: 10.w)), IconButton( icon: Image( - width: 40.w, - height: 40.w, - image: const AssetImage( - 'images/main/icon_lockDetail_monitoringEditVoice.png')), + width: 40.w, + height: 40.w, + image: const AssetImage( + 'images/main/icon_lockDetail_monitoringEditVoice.png'), + ), iconSize: 30, color: Colors.black54, onPressed: () { @@ -342,17 +345,23 @@ class _VideoLogPageState extends State { } _buildImageItem(RecordListData recordData) { - return Image.network( - recordData.imagesUrl!, - fit: BoxFit.cover, - errorBuilder: - (BuildContext context, Object error, StackTrace? stackTrace) { - // 图片加载失败时显示错误图片 - return Image.asset( - 'images/icon_unHaveData.png', // 错误图片路径 - fit: BoxFit.cover, - ); - }, + return RotatedBox( + quarterTurns: -1, + child: Image.network( + recordData.imagesUrl!, + fit: BoxFit.cover, + errorBuilder: + (BuildContext context, Object error, StackTrace? stackTrace) { + // 图片加载失败时显示错误图片 + return RotatedBox( + quarterTurns: -1, + child: Image.asset( + 'images/icon_unHaveData.png', // 错误图片路径 + fit: BoxFit.cover, + ), + ); + }, + ), ); } } diff --git a/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart b/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart index 665aed93..c90cc379 100755 --- a/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart +++ b/lib/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart @@ -148,9 +148,10 @@ class _ControlsOverlayState extends State { // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - DateTool().dateToYMDHNString( - widget.recordData.operateDate.toString()), - style: TextStyle(color: Colors.white, fontSize: 20.sp)), + DateTool().dateToYMDHNString( + widget.recordData.operateDate.toString()), + style: TextStyle(color: Colors.white, fontSize: 20.sp), + ), // Expanded(child: SizedBox(width: 10.w)), // Container( // width: 50.w, diff --git a/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart b/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart index 16e4c12f..bd680cab 100755 --- a/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart +++ b/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; @@ -72,37 +73,35 @@ class _VideoLogDetailPageState extends State { ? Column( children: [ Container( + color: Colors.black, height: 500.h, - decoration: BoxDecoration(color: Colors.black), - child: AspectRatio( - aspectRatio: 16 / 9, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - FittedBox( - child: SizedBox( - width: state.videoController.value.size.width, - height: state.videoController.value.size.height, - child: VideoPlayer(state.videoController), - ), - fit: BoxFit.cover, + width: 1.sw, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + RotatedBox( + quarterTurns: -1, + child: AspectRatio( + aspectRatio: state.videoController.value.size.width / + state.videoController.value.size.height, + child: VideoPlayer(state.videoController), ), - ControlsOverlay( - controller: state.videoController, - recordData: state.recordData.value, + ), + ControlsOverlay( + controller: state.videoController, + recordData: state.recordData.value, + ), + if (state.videoController.value.isPlaying || + state.videoController.value.isBuffering) + Container() + else + VideoProgressIndicator( + state.videoController, + colors: VideoProgressColors( + playedColor: AppColors.mainColor), + allowScrubbing: true, ), - if (state.videoController.value.isPlaying || - state.videoController.value.isBuffering) - Container() - else - VideoProgressIndicator( - state.videoController, - colors: VideoProgressColors( - playedColor: AppColors.mainColor), - allowScrubbing: true, - ), - ], - ), + ], ), ), _buildOther(), @@ -170,9 +169,23 @@ class _VideoLogDetailPageState extends State { } _buildImageItem(RecordListData recordData) { - return Image.network( - recordData.imagesUrl!, - fit: BoxFit.cover, + return RotatedBox( + quarterTurns: 1, + child: Image.network( + recordData.imagesUrl!, + fit: BoxFit.cover, + errorBuilder: + (BuildContext context, Object error, StackTrace? stackTrace) { + // 图片加载失败时显示错误图片 + return RotatedBox( + quarterTurns: -1, + child: Image.asset( + 'images/icon_unHaveData.png', // 错误图片路径 + fit: BoxFit.cover, + ), + ); + }, + ), ); } diff --git a/lib/main/lockDetail/videoLog/widget/full_screenImage_page.dart b/lib/main/lockDetail/videoLog/widget/full_screenImage_page.dart index 9c516439..f2da5bf9 100644 --- a/lib/main/lockDetail/videoLog/widget/full_screenImage_page.dart +++ b/lib/main/lockDetail/videoLog/widget/full_screenImage_page.dart @@ -10,9 +10,17 @@ class FullScreenImagePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - body: Container( - child: PhotoView( - imageProvider: NetworkImage(imageUrl), + body: GestureDetector( + onTap: (){ + Navigator.pop(context); // 点击图片返回 + }, + child: Container( + child: RotatedBox( + quarterTurns: -1, + child: PhotoView( + imageProvider: NetworkImage(imageUrl), + ), + ), ), ), ); diff --git a/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart b/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart index de2259a6..06b63b59 100644 --- a/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart +++ b/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart @@ -49,14 +49,17 @@ class _VideoThumbnailState extends State { children: [ // 如果视频已经初始化,则显示视频玩家 _controller.value.isInitialized - ? AspectRatio( - aspectRatio: 1 / 1, // 强制正方形比例 - child: FittedBox( - fit: BoxFit.cover, // 确保视频封面铺满空间 - child: SizedBox( - width: _controller.value.size.width, - height: _controller.value.size.height, - child: VideoPlayer(_controller), + ? RotatedBox( + quarterTurns: -1, + child: AspectRatio( + aspectRatio: 1 / 1, // 强制正方形比例 + child: FittedBox( + fit: BoxFit.cover, // 确保视频封面铺满空间 + child: SizedBox( + width: _controller.value.size.width, + height: _controller.value.size.height, + child: VideoPlayer(_controller), + ), ), ), ) From 592940c3bacdf45bf7cc4f77e91bc0f32ae5d3d1 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 21 Jan 2025 10:25:40 +0800 Subject: [PATCH 11/15] =?UTF-8?q?fix:=E8=A7=86=E9=A2=91=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=80=BB=E8=BE=91=E3=80=81=E8=A7=86=E9=A2=91?= =?UTF-8?q?/=E5=9B=BE=E7=89=87=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 0971a052..37ece221 100755 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,5 +2,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -#distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip -distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip + From 4f6781a0b01b948a88655aea72da711e4ff3ceea Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 21 Jan 2025 10:26:15 +0800 Subject: [PATCH 12/15] =?UTF-8?q?fix:=E8=A7=86=E9=A2=91=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E6=97=B6=E9=9C=80=E8=A6=81=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?dio=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.lock | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 2cd964da..c1ebb21f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -401,7 +401,7 @@ packages: source: hosted version: "7.0.2" dio: - dependency: transitive + dependency: "direct main" description: name: dio sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" diff --git a/pubspec.yaml b/pubspec.yaml index dcb93df9..25d16da7 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -268,7 +268,7 @@ dependencies: fixnum: ^1.1.1 # 图片预览 photo_view: ^0.15.0 - + dio: ^4.0.6 # 网络请求库 From de6d7bca580b58ff4fbd301cdc4613cd6709dab4 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 21 Jan 2025 14:09:09 +0800 Subject: [PATCH 13/15] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=B8=AD=E7=9A=84=E8=A7=86=E9=A2=91=E7=BC=A9?= =?UTF-8?q?=E7=95=A5=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gradle/wrapper/gradle-wrapper.properties | 4 +- .../doorLockLog/doorLockLog_page.dart | 4 +- .../editVideoLog/editVideoLog_page.dart | 61 +----------- .../videoLog/videoLog/videoLog_logic.dart | 26 ----- .../videoLog/videoLog/videoLog_page.dart | 4 +- .../videoLogDetail/videoLogDetail_page.dart | 4 +- .../videoLog/widget/video_thumbnail.dart | 76 --------------- .../widget/video_thumbnail_image.dart | 97 +++++++++++++++++++ 8 files changed, 109 insertions(+), 167 deletions(-) delete mode 100644 lib/main/lockDetail/videoLog/widget/video_thumbnail.dart create mode 100644 lib/main/lockDetail/videoLog/widget/video_thumbnail_image.dart diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 37ece221..0971a052 100755 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,5 +2,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip - +#distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-7.4-all.zip diff --git a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart index fca6b402..05bbf80d 100755 --- a/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart +++ b/lib/main/lockDetail/doorLockLog/doorLockLog_page.dart @@ -9,7 +9,7 @@ import 'package:star_lock/main/lockDetail/doorLockLog/doorLockLog_state.dart'; import 'package:star_lock/main/lockDetail/doorLockLog/exportRecordDialog/exportRecordDialog_page.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; -import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/EasyRefreshTool.dart'; import 'package:star_lock/tools/advancedCalendar/src/widget.dart'; import 'package:star_lock/tools/commonDataManage.dart'; @@ -399,7 +399,7 @@ class _DoorLockLogPageState extends State with RouteAware { } _buildVideoItem(RecordListData recordData) { - return VideoThumbnail(videoUrl: recordData.videoUrl!); + return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { diff --git a/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart b/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart index c52a90d5..86faa5b8 100755 --- a/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart +++ b/lib/main/lockDetail/videoLog/editVideoLog/editVideoLog_page.dart @@ -6,7 +6,7 @@ import 'package:star_lock/appRouters.dart'; import 'package:star_lock/main/lockDetail/videoLog/editVideoLog/editVideoLog_state.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; -import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/dateTool.dart'; import '../../../../app_settings/app_colors.dart'; @@ -241,61 +241,8 @@ class _EditVideoLogPageState extends State { Future _onDelClick() async { if (state.selectVideoLogList.value.isNotEmpty) { - // 弹出自定义确认对话框 - bool confirmDelete = await showDialog( - context: context, - builder: (BuildContext context) { - return Dialog( - backgroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - '确认删除'.tr, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - SizedBox(height: 16), - Text('确定要删除选中的视频吗?'.tr), - SizedBox(height: 24), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - TextButton( - onPressed: () { - // 用户点击取消,返回 false - Navigator.of(context).pop(false); - }, - child: Text('取消'.tr), - ), - SizedBox(width: 8), - ElevatedButton( - onPressed: () { - // 用户点击确认,返回 true - Navigator.of(context).pop(true); - }, - child: Text('确认'.tr), - ), - ], - ), - ], - ), - ), - ); - }, - ); - - // 如果用户确认删除,执行删除逻辑 - if (confirmDelete == true) { - await logic.deleteLockCloudStorageList(); - } + await logic.deleteLockCloudStorageList(); + setState(() {}); } else { logic.showToast('请选择要删除的视频'.tr); } @@ -412,7 +359,7 @@ class _EditVideoLogPageState extends State { } _buildVideoItem(RecordListData recordData) { - return VideoThumbnail(videoUrl: recordData.videoUrl!); + return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart index 41124660..b19264a5 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_logic.dart @@ -22,38 +22,12 @@ class VideoLogLogic extends BaseGetXController { (record.imagesUrl != null && record.imagesUrl!.isNotEmpty) || (record.videoUrl != null && record.videoUrl!.isNotEmpty)) .toList(); - - // // 为 videoUrl 不为空的项设置封面 - // for (var record in element.recordList!) { - // if (record.videoUrl != null && record.videoUrl!.isNotEmpty) { - // _setVideoThumbnail(record); // 设置视频封面 - // } - // } }); state.videoLogList.refresh(); } } - // Future _setVideoThumbnail(RecordListData record) async { - // try { - // final thumbnailData = await getVideoThumbnail(record.videoUrl!); - // record.thumbnailData = thumbnailData; // 设置视频封面数据 - // } catch (e) { - // print('获取视频封面失败: $e'); - // } - // } - // - // Future getVideoThumbnail(String videoUrl) async { - // final thumbnail = await VideoThumbnail.thumbnailData( - // video: videoUrl, - // imageFormat: ImageFormat.JPEG, - // maxWidth: 128, // 缩略图的最大宽度 - // quality: 25, // 缩略图的质量(0-100) - // ); - // return thumbnail; - // } - @override onReady() { super.onReady(); diff --git a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart index 994f7383..7911a215 100755 --- a/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart +++ b/lib/main/lockDetail/videoLog/videoLog/videoLog_page.dart @@ -6,7 +6,7 @@ import 'package:star_lock/flavors.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_state.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; -import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/dateTool.dart'; import 'package:star_lock/tools/noData.dart'; import 'package:video_player/video_player.dart'; @@ -341,7 +341,7 @@ class _VideoLogPageState extends State { } _buildVideoItem(RecordListData recordData) { - return VideoThumbnail(videoUrl: recordData.videoUrl!); + return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { diff --git a/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart b/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart index bd680cab..619d0539 100755 --- a/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart +++ b/lib/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_page.dart @@ -8,7 +8,7 @@ import 'package:star_lock/main/lockDetail/videoLog/videoLog/videoLog_entity.dart import 'package:star_lock/main/lockDetail/videoLog/videoLogDetail/controlsOverlay_page.dart'; import 'package:star_lock/main/lockDetail/videoLog/videoLogDetail/videoLogDetail_state.dart'; import 'package:star_lock/main/lockDetail/videoLog/widget/full_screenImage_page.dart'; -import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail.dart'; +import 'package:star_lock/main/lockDetail/videoLog/widget/video_thumbnail_image.dart'; import 'package:star_lock/tools/dateTool.dart'; import 'package:video_player/video_player.dart'; @@ -165,7 +165,7 @@ class _VideoLogDetailPageState extends State { } _buildVideoItem(RecordListData recordData) { - return VideoThumbnail(videoUrl: recordData.videoUrl!); + return VideoThumbnailImage(videoUrl: recordData.videoUrl!); } _buildImageItem(RecordListData recordData) { diff --git a/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart b/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart deleted file mode 100644 index 06b63b59..00000000 --- a/lib/main/lockDetail/videoLog/widget/video_thumbnail.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:video_player/video_player.dart'; - -class VideoThumbnail extends StatefulWidget { - final String videoUrl; - - VideoThumbnail({required this.videoUrl}); - - @override - _VideoThumbnailState createState() => _VideoThumbnailState(); -} - -class _VideoThumbnailState extends State { - late VideoPlayerController _controller; - late Future _initializeVideoPlayerFuture; - - @override - void initState() { - super.initState(); - // 创建并初始化 VideoPlayerController - _controller = VideoPlayerController.network(widget.videoUrl) - ..initialize().then((_) { - // 当视频控制器初始化完成后,更新UI以便显示第一帧 - setState(() {}); - }); - } - - @override - void dispose() { - // 清理资源 - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return GestureDetector( - // onTap: () { - // setState(() { - // if (_controller.value.isPlaying) { - // _controller.pause(); - // } else { - // _controller.play(); - // } - // }); - // }, - child: Stack( - alignment: Alignment.center, - children: [ - // 如果视频已经初始化,则显示视频玩家 - _controller.value.isInitialized - ? RotatedBox( - quarterTurns: -1, - child: AspectRatio( - aspectRatio: 1 / 1, // 强制正方形比例 - child: FittedBox( - fit: BoxFit.cover, // 确保视频封面铺满空间 - child: SizedBox( - width: _controller.value.size.width, - height: _controller.value.size.height, - child: VideoPlayer(_controller), - ), - ), - ), - ) - : Center( - child: CircularProgressIndicator(), // 加载中显示转圈 - ), - if (!_controller.value.isPlaying && _controller.value.isInitialized) - Icon(Icons.play_arrow_rounded, - size: 80, color: Colors.white.withOpacity(0.8)), - ], - ), - ); - } -} diff --git a/lib/main/lockDetail/videoLog/widget/video_thumbnail_image.dart b/lib/main/lockDetail/videoLog/widget/video_thumbnail_image.dart new file mode 100644 index 00000000..4f119569 --- /dev/null +++ b/lib/main/lockDetail/videoLog/widget/video_thumbnail_image.dart @@ -0,0 +1,97 @@ +import 'dart:io'; // 导入 dart:io 以使用 File 类 +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:path_provider/path_provider.dart'; // 导入 path_provider +import 'package:video_thumbnail/video_thumbnail.dart'; // 导入 video_thumbnail + +class VideoThumbnailImage extends StatefulWidget { + final String videoUrl; + + VideoThumbnailImage({required this.videoUrl}); + + @override + _VideoThumbnailState createState() => _VideoThumbnailState(); +} + +class _VideoThumbnailState extends State { + final Map _thumbnailCache = {}; // 缩略图缓存 + late Future _thumbnailFuture; // 用于存储缩略图生成的 Future + + @override + void initState() { + super.initState(); + _thumbnailFuture = _generateThumbnail(); // 在 initState 中初始化 Future + } + + // 生成缩略图 + Future _generateThumbnail() async { + try { + // 检查缓存中是否已有缩略图 + if (_thumbnailCache.containsKey(widget.videoUrl)) { + return _thumbnailCache[widget.videoUrl]; + } + + // 获取临时目录路径 + final tempDir = await getTemporaryDirectory(); + final thumbnailPath = await VideoThumbnail.thumbnailFile( + video: widget.videoUrl, + // 视频 URL + thumbnailPath: tempDir.path, + // 缩略图保存路径 + imageFormat: ImageFormat.JPEG, + // 缩略图格式 + maxHeight: 200, + // 缩略图最大高度 + quality: 100, // 缩略图质量 (0-100) + ); + + // 更新缓存 + _thumbnailCache[widget.videoUrl] = thumbnailPath!; + return thumbnailPath; + } catch (e) { + print('Failed to generate thumbnail: $e'); + return null; + } + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _thumbnailFuture, // 生成缩略图的 Future + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + // 加载中显示转圈 + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError || !snapshot.hasData) { + // 加载失败或没有数据时显示提示 + return Image.asset( + 'images/icon_unHaveData.png', // 错误图片路径 + fit: BoxFit.cover, + ); + } else { + // 加载成功,显示缩略图 + final thumbnailPath = snapshot.data!; + return Stack( + alignment: Alignment.center, + children: [ + RotatedBox( + quarterTurns: -1, + child: Image.file( + File(thumbnailPath), // 显示生成的缩略图 + width: 200, + height: 200, + fit: BoxFit.cover, + ), + ), + Icon( + Icons.play_arrow_rounded, + size: 80, + color: Colors.white.withOpacity(0.8), + ), + ], + ); + } + }, + ); + } +} From e990a0806b11aa70697e2c3d3f3c09174f6bfb1a Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 21 Jan 2025 14:09:21 +0800 Subject: [PATCH 14/15] =?UTF-8?q?fix:=E5=A2=9E=E5=8A=A0=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=B8=AD=E7=9A=84=E8=A7=86=E9=A2=91=E7=BC=A9?= =?UTF-8?q?=E7=95=A5=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.lock | 8 ++++++++ pubspec.yaml | 1 + 2 files changed, 9 insertions(+) diff --git a/pubspec.lock b/pubspec.lock index c1ebb21f..da22a6a3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1785,6 +1785,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + video_thumbnail: + dependency: "direct main" + description: + name: video_thumbnail + sha256: "3455c189d3f0bb4e3fc2236475aa84fe598b9b2d0e08f43b9761f5bc44210016" + url: "https://pub.dev" + source: hosted + version: "0.5.3" visibility_detector: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 25d16da7..66b1588e 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -269,6 +269,7 @@ dependencies: # 图片预览 photo_view: ^0.15.0 dio: ^4.0.6 # 网络请求库 + video_thumbnail: ^0.5.3 From f28237c7c7946e74a3cdd5f5c697ecce713de9c6 Mon Sep 17 00:00:00 2001 From: Liuyf Date: Tue, 21 Jan 2025 14:34:40 +0800 Subject: [PATCH 15/15] =?UTF-8?q?other=EF=BC=9A=E4=B8=B4=E6=97=B6=E6=89=93?= =?UTF-8?q?=E5=8C=85sky=20pre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitlab-ci.yml | 1 + ios/build.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1704ba4b..92747b72 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,6 +20,7 @@ variables: - if: $CI_COMMIT_BRANCH == "release" - if: $CI_COMMIT_BRANCH =~ /feat_[a-zA-Z]+/ - if: $CI_COMMIT_BRANCH == "canary_release" + - if: $CI_COMMIT_BRANCH == "develop_liyi" - if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z]+\.[0-9]+)?$/ .notify_rule: diff --git a/ios/build.sh b/ios/build.sh index a8a977bf..79239db5 100755 --- a/ios/build.sh +++ b/ios/build.sh @@ -23,7 +23,7 @@ elif [[ "${ENV_BUILD_BRANCH}" == "develop" ]]; then echo "===build dev===${NEXT_VERSION}" bundle exec fastlane beta flavor:xhj env:Dev --verbose bundle exec fastlane beta flavor:sky env:Dev --verbose -elif [[ "${ENV_BUILD_BRANCH}" == "release" ]] || [[ "${ENV_BUILD_BRANCH}" == "feat_devops" ]] ; then +elif [[ "${ENV_BUILD_BRANCH}" == "release" ]] || [[ "${ENV_BUILD_BRANCH}" == "feat_devops" ]] || [[ "${ENV_BUILD_BRANCH}" == "develop_liyi" ]] ; then echo "===build pre===${NEXT_VERSION}" bundle exec fastlane beta flavor:xhj env:Pre --verbose bundle exec fastlane beta flavor:sky env:Pre --verbose