Kaynağa Gözat

feat:“同步2025.04.22“

soobin 4 ay önce
ebeveyn
işleme
472c694990
51 değiştirilmiş dosya ile 6734 ekleme ve 1535 silme
  1. BIN
      src/assets/device/operIcon/payment.png
  2. 9 3
      src/assets/language/en.json
  3. 14 8
      src/assets/language/es.json
  4. 13 7
      src/assets/language/fr.json
  5. 9 3
      src/assets/language/ja.json
  6. 14 8
      src/assets/language/pt.json
  7. 9 3
      src/assets/language/ru.json
  8. 1765 0
      src/assets/language/uk.json
  9. 17 11
      src/assets/language/zh.json
  10. BIN
      src/assets/order/spunSugar/goods/BS01.png
  11. BIN
      src/assets/order/spunSugar/goods/BS02.png
  12. BIN
      src/assets/order/spunSugar/goods/BS03.png
  13. BIN
      src/assets/order/spunSugar/goods/BS04.png
  14. BIN
      src/assets/order/spunSugar/goods/BS05.png
  15. 33 1
      src/common/js/countries-en.js
  16. 32 0
      src/common/js/countries.js
  17. 2 1
      src/common/js/utils.js
  18. 10 0
      src/components/NavBar.vue
  19. 3 1
      src/components/SimpleHeader.vue
  20. 86 31
      src/components/commom/kDialog/index.vue
  21. 111 32
      src/components/dateSelectList/index.vue
  22. 192 67
      src/components/typeDownMenu/index.vue
  23. 14 14
      src/router/index.js
  24. 10 0
      src/service/device/index.js
  25. 10 20
      src/service/huifuMch/index.js
  26. 1 4
      src/service/joinpayMch/index.js
  27. 0 12
      src/service/purse/indes.js
  28. 37 0
      src/service/purse/index.js
  29. 0 8
      src/service/taskMessage/index.js
  30. 46 39
      src/utils/i18n.js
  31. 44 36
      src/views/accountPer/add.vue
  32. 16 0
      src/views/advertManage/adSet.vue
  33. 65 45
      src/views/apkManage/add.vue
  34. 1168 0
      src/views/bindBankCard/index.vue
  35. 3 3
      src/views/device/alarmClean/index.vue
  36. 209 60
      src/views/device/alarmClock.vue
  37. 203 45
      src/views/device/alarmClockSet/index.vue
  38. 428 182
      src/views/device/deviceOper.vue
  39. 1 1
      src/views/device/doSugar.vue
  40. 785 247
      src/views/device/index.vue
  41. 221 0
      src/views/device/payment/index.vue
  42. 2 2
      src/views/device/returnCoin/index.vue
  43. 3 0
      src/views/orderCenter/index.vue
  44. 319 74
      src/views/purse/index.vue
  45. 740 0
      src/views/purse/withdrawList.vue
  46. 2 1
      src/views/role/add.vue
  47. 61 139
      src/views/settlement/index.vue
  48. 0 9
      src/views/taskMessage/joinpayMchCheck/info/index.less
  49. 0 389
      src/views/taskMessage/joinpayMchCheck/info/index.vue
  50. 8 24
      src/views/user.vue
  51. 19 5
      vue.config.js

BIN
src/assets/device/operIcon/payment.png


+ 9 - 3
src/assets/language/en.json

@@ -89,6 +89,7 @@
     "accountAddedSuccessfully": "Account added",
     "accountNameExists": "Account exists",
     "failedToAddAccount": "Add failed",
+    "delTips": "Delete this account? This cannot be undone.",
     "successfullyDeletedTheAccount": "Account deleted",
     "failedToDeleteTheAccount": "Delete failed",
     "accountPermission": "Permissions",
@@ -577,7 +578,7 @@
     "position": "GPS",
     "viewPositioning": "View Location",
     "restartAndroid": "Restart UI",
-    "alramClean": "Maintenance",
+    "alarmClean": "Maintenance",
     "returnCoin": "Refund Coins",
     "returnCoinPage": {
       "amount": "Refund Amount",
@@ -605,6 +606,10 @@
     "stick": "Sticks",
     "water": "Water",
     "wasteWater": "Waste",
+    "chocolate": "Chocolate",
+    "cheese": "Cheese",
+    "peach": "Peach",
+    "caramel": "Caramel",
     "sentSuccessfully": "Sent",
     "turnOffSleep": "Sleep Mode",
     "turnOnSleep": "Active",
@@ -1701,7 +1706,7 @@
     "content": "Toggle feature?",
     "successfully": "Command sent. Refresh in 5s"
   },
-  "alramClean": {
+  "alarmClean": {
     "openCleanFunction": "Maintenance Mode: On",
     "closeCleanFunction": "Maintenance Mode: Off",
     "openStatus": "Maintenance Alerts: On",
@@ -1754,6 +1759,7 @@
     "C24": "Cooling Mode (Ice Cream)",
     "C25": "Mixing Mode (Ice Cream)",
     "C26": "Freshness Mode (Ice Cream)",
-    "C27": "Defrost Mode (Ice Cream)"
+    "C27": "Defrost Mode (Ice Cream)",
+    "C28": "Edit Payment Method"
   }
 }

+ 14 - 8
src/assets/language/es.json

@@ -89,6 +89,7 @@
         "accountAddedSuccessfully": "Cuenta añadida",
         "accountNameExists": "Cuenta existe",
         "failedToAddAccount": "Error al añadir",
+        "delTips": "¿Eliminar cuenta? Acción irreversible.",
         "successfullyDeletedTheAccount": "Cuenta eliminada",
         "failedToDeleteTheAccount": "Error al eliminar",
         "accountPermission": "Permisos",
@@ -577,7 +578,7 @@
         "position": "Ubicación",
         "viewPositioning": "Ver ubicación",
         "restartAndroid": "Reiniciar pantalla",
-        "alramClean": "Limpieza",
+        "alarmClean": "Limpieza",
         "returnCoin": "Devolución monedas",
         "returnCoinPage": {
             "amount": "Cantidad",
@@ -605,6 +606,10 @@
         "stick": "Palitos",
         "water": "Agua",
         "wasteWater": "Residuos",
+        "chocolate": "Chocolate",
+        "cheese": "Queso",
+        "peach": "Melocotón",
+        "caramel": "Caramelo",
         "sentSuccessfully": "Solicitud enviada",
         "turnOffSleep": "Modo descanso",
         "turnOnSleep": "Modo activo",
@@ -930,7 +935,7 @@
         "leavBlanToIndiNoModi": "Dejar vacío = sin cambios",
         "confirmPasswordLabel": "Confirmar contraseña",
         "confirmPasswordPlaceholder": "Repetir contraseña",
-        "mailboxPlaceholder": "contacto@empresa.com",
+        "mailboxPlaceholder": "email",
         "telephonePlaceholder": "+34 600 000 000",
         "merchantFilingNumberLabel": "N° registro",
         "merchantFilingNumberPlaceholder": "Ej: REG-123",
@@ -1191,7 +1196,7 @@
         "huifuContactMobilePlaceholder": "+34 600 000 000",
         "huifuContactMobileMessage": "Teléfono inválido",
         "huifuContactEmail": "Email contacto",
-        "huifuContactEmailPlaceholder": "contacto@empresa.com",
+        "huifuContactEmailPlaceholder": "",
         "huifuContactEmailMessage": "Email inválido",
         "huifuBusinessAddress": "Dirección comercial",
         "huifuBusinessAddressPlaceholder": "Seleccionar provincia",
@@ -1387,7 +1392,7 @@
         "phoneRequired": "Requerido",
         "emailWordSpan": "Email registrado",
         "emailLabel": "Email",
-        "emailPlaceholder": "contacto@empresa.com",
+        "emailPlaceholder": "email",
         "emailRequired": "Requerido",
         "seedVerCode": "Enviar código",
         "codePlaceholder": "Ej: 123456",
@@ -1440,7 +1445,7 @@
         "codePlaceholder": "Ej: 123456",
         "codeRequired": "Requerido",
         "emailLabel": "Email",
-        "emailPlaceholder": "contacto@empresa.com",
+        "emailPlaceholder": "email",
         "emailRequired": "Requerido",
         "emailCodeLabel": "Código email",
         "emailCodePlaceholder": "Ej: ABCD12",
@@ -1511,7 +1516,7 @@
         "phoneNumber": "Teléfono",
         "phoneNumberPlace": "+34 600 000 000",
         "mailbox": "Email",
-        "mailboxPlace": "contacto@empresa.com",
+        "mailboxPlace": "email",
         "associateParent": "Responsable superior",
         "superiorAccount": "Cuenta superior",
         "associateParentPlace": "Ej: resp_123",
@@ -1700,7 +1705,7 @@
         "content": "¿Cambiar estado?",
         "successfully": "Actualizado. Espere 5 seg."
     },
-    "alramClean": {
+    "alarmClean": {
         "openCleanFunction": "Limpieza: Activada",
         "closeCleanFunction": "Limpieza: Desactivada",
         "openStatus": "Recordatorio: ON",
@@ -1753,6 +1758,7 @@
         "C24": "Refrigeración (Helado)",
         "C25": "Mezcla (Helado)",
         "C26": "Conservación (Helado)",
-        "C27": "Descongelación (Helado)"
+        "C27": "Descongelación (Helado)",
+        "C28": "Cambiar pago"
     }
 }

+ 13 - 7
src/assets/language/fr.json

@@ -89,6 +89,7 @@
         "accountAddedSuccessfully": "Compte créé",
         "accountNameExists": "Compte existe déjà",
         "failedToAddAccount": "Échec création",
+        "delTips": "Supprimer ce compte ? Action irréversible.",
         "successfullyDeletedTheAccount": "Compte supprimé",
         "failedToDeleteTheAccount": "Échec suppression",
         "accountPermission": "Permissions",
@@ -577,7 +578,7 @@
         "position": "Position",
         "viewPositioning": "Voir position",
         "restartAndroid": "Redémarrer écran",
-        "alramClean": "Nettoyage",
+        "alarmClean": "Nettoyage",
         "returnCoin": "Remboursement",
         "returnCoinPage": {
             "amount": "Quantité",
@@ -605,6 +606,10 @@
         "stick": "Bâtonnet",
         "water": "Eau",
         "wasteWater": "Eaux usées",
+        "chocolate": "Chocolat",
+        "cheese": "Fromage",
+        "peach": "Pêche",
+        "caramel": "Caramel",
         "sentSuccessfully": "Envoyé",
         "turnOffSleep": "Veille activée",
         "turnOnSleep": "Veille désactivée",
@@ -1191,7 +1196,7 @@
         "huifuContactMobilePlaceholder": "Ex: 06 12 34 56 78",
         "huifuContactMobileMessage": "Format invalide",
         "huifuContactEmail": "Email",
-        "huifuContactEmailPlaceholder": "contact@exemple.com",
+        "huifuContactEmailPlaceholder": "Email",
         "huifuContactEmailMessage": "Email invalide",
         "huifuBusinessAddress": "Adresse commerciale",
         "huifuBusinessAddressPlaceholder": "Sélectionner région",
@@ -1418,7 +1423,7 @@
         "phoneRequired": "Numéro requis",
         "emailWordSpan": "Email enregistré (International)",
         "emailLabel": "Email",
-        "emailPlaceholder": "contact@exemple.com",
+        "emailPlaceholder": "Email",
         "emailRequired": "Email requis",
         "seedVerCode": "Envoyer code",
         "codePlaceholder": "Code à 6 chiffres",
@@ -1471,7 +1476,7 @@
         "codePlaceholder": "Code à 6 chiffres",
         "codeRequired": "Code requis",
         "emailLabel": "Email",
-        "emailPlaceholder": "contact@exemple.com",
+        "emailPlaceholder": "Email",
         "emailRequired": "Email requis",
         "emailCodeLabel": "Code de vérification",
         "emailCodePlaceholder": "Code reçu par email",
@@ -1542,7 +1547,7 @@
         "phoneNumber": "Téléphone",
         "phoneNumberPlace": "Ex: 06 12 34 56 78",
         "mailbox": "Email",
-        "mailboxPlace": "contact@exemple.com",
+        "mailboxPlace": "Email",
         "associateParent": "Responsable affilié",
         "superiorAccount": "Compte responsable",
         "associateParentPlace": "Saisir ID responsable",
@@ -1731,7 +1736,7 @@
         "content": "Confirmer changement ?",
         "successfully": "Requête envoyée - Actualiser dans 5s"
     },
-    "alramClean": {
+    "alarmClean": {
         "openCleanFunction": "Nettoyage : Activé",
         "closeCleanFunction": "Nettoyage : Désactivé",
         "openStatus": "Rappels nettoyage : Activés",
@@ -1784,6 +1789,7 @@
         "C24": "Réfrigération (Glace)",
         "C25": "Mélange (Glace)",
         "C26": "Conservation (Glace)",
-        "C27": "Décongélation (Glace)"
+        "C27": "Décongélation (Glace)",
+        "C28": "Modifier paiement"
     }
 }

+ 9 - 3
src/assets/language/ja.json

@@ -88,6 +88,7 @@
         "accountAddedSuccessfully": "アカウントの追加完了",
         "accountNameExists": "アカウント名がすでに存在",
         "failedToAddAccount": "アカウントの追加に失敗",
+        "delTips": "アカウントを削除しますか?取り消せません。",
         "successfullyDeletedTheAccount": "アカウントの削除完了",
         "failedToDeleteTheAccount": "アカウントの削除失敗",
         "accountPermission": "アカウント権限",
@@ -571,7 +572,7 @@
         "position": "位置情報",
         "viewPositioning": "位置情報を見る",
         "restartAndroid": "画面を再起動",
-        "alramClean": "機器洗浄",
+        "alarmClean": "機器洗浄",
         "returnCoin": "硬貨を払い戻す",
         "returnCoinPage": {
             "amount": "数です",
@@ -599,6 +600,10 @@
         "stick": "スティック",
         "water": "浄水",
         "wasteWater": "汚水",
+        "chocolate": "チョコレート",
+        "cheese": "チーズ",
+        "peach": "桃",
+        "caramel": "キャラメル",
         "sentSuccessfully": "リクエスト送信完了",
         "turnOffSleep": "スリープ中",
         "turnOnSleep": "スリープしていない",
@@ -1692,7 +1697,7 @@
         "content": "スイッチを切り替えますか?",
         "successfully": "送信に成功しました。数秒待ってから再入力してください"
     },
-    "alramClean": {
+    "alarmClean": {
         "openCleanFunction": "洗浄機能です:オン",
         "closeCleanFunction": "洗浄機能です:オフ",
         "openStatus": "装置のクリーニングリマインダースイッチの状態:オン",
@@ -1745,6 +1750,7 @@
         "C24": "冷却モード(アイスクリーム)",
         "C25": "攪拌モード(アイスクリーム)",
         "C26": "鮮度保持(アイスクリーム)",
-        "C27": "解凍モード(アイスクリーム)"
+        "C27": "解凍モード(アイスクリーム)",
+        "C28": "支払い方法変更"
     }
 }

+ 14 - 8
src/assets/language/pt.json

@@ -89,6 +89,7 @@
         "accountAddedSuccessfully": "Conta criada",
         "accountNameExists": "Usuário existente",
         "failedToAddAccount": "Erro ao criar",
+        "delTips": "Excluir conta? Ação irreversível.",
         "successfullyDeletedTheAccount": "Conta excluída",
         "failedToDeleteTheAccount": "Erro ao excluir",
         "accountPermission": "Permissões",
@@ -577,7 +578,7 @@
         "position": "GPS",
         "viewPositioning": "Ver Localização",
         "restartAndroid": "Reiniciar Touchscreen",
-        "alramClean": "Limpeza Automática",
+        "alarmClean": "Limpeza Automática",
         "returnCoin": "Reembolso Remoto",
         "returnCoinPage": {
             "amount": "Quantidade",
@@ -605,6 +606,10 @@
         "stick": "Palito",
         "water": "Água",
         "wasteWater": "Água Residual",
+        "chocolate": "Chocolate",
+        "cheese": "Queijo",
+        "peach": "Pêssego",
+        "caramel": "Caramelo",
         "sentSuccessfully": "Comando Enviado",
         "turnOffSleep": "Modo Repouso Ativo",
         "turnOnSleep": "Modo Repouso Inativo",
@@ -930,7 +935,7 @@
         "leavBlanToIndiNoModi": "Deixe em branco para manter",
         "confirmPasswordLabel": "Confirmar Senha",
         "confirmPasswordPlaceholder": "Repita a senha",
-        "mailboxPlaceholder": "Ex: email@dominio.com",
+        "mailboxPlaceholder": "Email",
         "telephonePlaceholder": "Ex: +55 11 99999-9999",
         "merchantFilingNumberLabel": "CNPJ Registrado",
         "merchantFilingNumberPlaceholder": "Ex: 12.345.678/0001-99",
@@ -1191,7 +1196,7 @@
         "huifuContactMobilePlaceholder": "Ex: +55 11 99999-9999",
         "huifuContactMobileMessage": "Formato inválido",
         "huifuContactEmail": "E-mail",
-        "huifuContactEmailPlaceholder": "Ex: contato@empresa.com",
+        "huifuContactEmailPlaceholder": "E-mail",
         "huifuContactEmailMessage": "E-mail inválido",
         "huifuBusinessAddress": "Endereço Comercial",
         "huifuBusinessAddressPlaceholder": "Selecione",
@@ -1387,7 +1392,7 @@
         "phoneRequired": "Digite o número",
         "emailWordSpan": "E-mail internacional cadastrado",
         "emailLabel": "E-mail",
-        "emailPlaceholder": "Ex: email@dominio.com",
+        "emailPlaceholder": "E-mail",
         "emailRequired": "Digite o e-mail",
         "seedVerCode": "Enviar Código",
         "codePlaceholder": "Ex: 123456",
@@ -1440,7 +1445,7 @@
         "codePlaceholder": "Ex: 123456",
         "codeRequired": "Digite o código",
         "emailLabel": "E-mail",
-        "emailPlaceholder": "Ex: email@dominio.com",
+        "emailPlaceholder": "E-mail",
         "emailRequired": "Campo obrigatório",
         "emailCodeLabel": "Código por E-mail",
         "emailCodePlaceholder": "Ex: ABCD12",
@@ -1511,7 +1516,7 @@
         "phoneNumber": "Celular",
         "phoneNumberPlace": "Ex: +55 11 99999-9999",
         "mailbox": "E-mail",
-        "mailboxPlace": "Ex: email@dominio.com",
+        "mailboxPlace": "E-mail",
         "associateParent": "Superior Associado",
         "superiorAccount": "Conta Superior",
         "associateParentPlace": "Ex: admin_principal",
@@ -1700,7 +1705,7 @@
         "content": "Confirmar alteração?",
         "successfully": "Comando enviado - Atualize em 5s"
     },
-    "alramClean": {
+    "alarmClean": {
         "openCleanFunction": "Limpeza Automática: Ativada",
         "closeCleanFunction": "Limpeza Automática: Desativada",
         "openStatus": "Lembrete Limpeza: Ativado",
@@ -1753,6 +1758,7 @@
         "C24": "Resfriamento (Sorvete)",
         "C25": "Mistura (Sorvete)",
         "C26": "Conservação (Sorvete)",
-        "C27": "Descongelamento (Sorvete)"
+        "C27": "Descongelamento (Sorvete)",
+        "C28": "Alterar pagamento"
     }
 }

+ 9 - 3
src/assets/language/ru.json

@@ -89,6 +89,7 @@
         "accountAddedSuccessfully": "Аккаунт добавлен",
         "accountNameExists": "Аккаунт существует",
         "failedToAddAccount": "Ошибка добавления",
+        "delTips": "Удалить аккаунт? Отменить нельзя.",
         "successfullyDeletedTheAccount": "Аккаунт удален",
         "failedToDeleteTheAccount": "Ошибка удаления",
         "accountPermission": "Права доступа",
@@ -577,7 +578,7 @@
         "position": "Гео",
         "viewPositioning": "Просмотр гео",
         "restartAndroid": "Перезапуск",
-        "alramClean": "Очистка",
+        "alarmClean": "Очистка",
         "returnCoin": "Возврат",
         "returnCoinPage": {
             "amount": "Кол-во",
@@ -605,6 +606,10 @@
         "stick": "Палочки",
         "water": "Вода",
         "wasteWater": "Стоки",
+        "chocolate": "Шоколад",
+        "cheese": "Сыр",
+        "peach": "Персик",
+        "caramel": "Карамель",
         "sentSuccessfully": "Отправлено",
         "turnOffSleep": "Сон zzZ",
         "turnOnSleep": "Активно",
@@ -1731,7 +1736,7 @@
         "content": "Подтвердите изменение",
         "successfully": "Успешно. Обновите страницу через 5 сек."
     },
-    "alramClean": {
+    "alarmClean": {
         "openCleanFunction": "Функция очистки: Включена",
         "closeCleanFunction": "Функция очистки: Выключена",
         "openStatus": "Напоминания об очистке: Вкл.",
@@ -1784,6 +1789,7 @@
         "C24": "Охлаждение (Мороженое)",
         "C25": "Перемешивание (Мороженое)",
         "C26": "Сохранение свежести (Мороженое)",
-        "C27": "Разморозка (Мороженое)"
+        "C27": "Разморозка (Мороженое)",
+        "C28": "Изменить оплату"
     }
 }

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1765 - 0
src/assets/language/uk.json


+ 17 - 11
src/assets/language/zh.json

@@ -89,6 +89,7 @@
     "accountAddedSuccessfully": "添加账号成功",
     "accountNameExists": "账号名已存在",
     "failedToAddAccount": "添加账号失败",
+    "delTips": "确定要删除该账号吗?此操作不可恢复!",
     "successfullyDeletedTheAccount": "删除账号成功",
     "failedToDeleteTheAccount": "删除账号失败",
     "accountPermission": "账号权限",
@@ -336,13 +337,13 @@
     "closed": "已关闭",
     "weekday2": "工作日",
     "weekend2": "周末",
-    "monday": "一",
-    "tuesday": "二",
-    "wednesday": "三",
-    "thursday": "四",
-    "friday": "五",
-    "saturday": "六",
-    "sunday": "日",
+    "monday": "一",
+    "tuesday": "二",
+    "wednesday": "三",
+    "thursday": "四",
+    "friday": "五",
+    "saturday": "六",
+    "sunday": "日",
     "deletionSucceeded": "删除成功",
     "commonOperations": "远程操作",
     "equipmentNo": "设备编号",
@@ -366,7 +367,7 @@
     "openRemind": "提醒",
     "openRemindOut": "是否切换外门开关?",
     "openRemindIn": "是否切换内门开关?",
-    "remoteSugarMaking": "远程做糖",
+    "remoteSugarMaking": "远程制作",
     "remoteProduction": "远程制作",
     "modulation": "音量调节",
     "equipmentRecharge": "设备充值",
@@ -577,7 +578,7 @@
     "position": "定位",
     "viewPositioning": "查看定位",
     "restartAndroid": "重启触摸屏",
-    "alramClean": "设备清洗",
+    "alarmClean": "设备清洗",
     "returnCoin": "远程退币",
     "returnCoinPage": {
       "amount": "退币数量",
@@ -605,6 +606,10 @@
     "stick": "棍子",
     "water": "清水",
     "wasteWater": "废水",
+    "chocolate": "巧克力",
+    "cheese": "芝士",
+    "peach": "水蜜桃",
+    "caramel": "焦糖",
     "sentSuccessfully": "发送请求成功",
     "turnOffSleep": "睡眠中zzZ",
     "turnOnSleep": "未睡眠",
@@ -1701,7 +1706,7 @@
     "content": "是否切换开关?",
     "successfully": "发送成功,请等待几秒后重新进入查看"
   },
-  "alramClean": {
+  "alarmClean": {
     "openCleanFunction": "设备清洗功能:开启",
     "closeCleanFunction": "设备清洗功能:关闭",
     "openStatus": "设备清洗提醒开关状态:开启",
@@ -1754,6 +1759,7 @@
     "C24": "制冷模式(冰淇淋)",
     "C25": "搅拌模式(冰淇淋)",
     "C26": "保鲜模式(冰淇淋)",
-    "C27": "解冻模式(冰淇淋)"
+    "C27": "解冻模式(冰淇淋)",
+    "C28": "修改支付方式"
   }
 }

BIN
src/assets/order/spunSugar/goods/BS01.png


BIN
src/assets/order/spunSugar/goods/BS02.png


BIN
src/assets/order/spunSugar/goods/BS03.png


BIN
src/assets/order/spunSugar/goods/BS04.png


BIN
src/assets/order/spunSugar/goods/BS05.png


+ 33 - 1
src/common/js/countries-en.js

@@ -1352,7 +1352,7 @@ export const countriesDataEn = [
       { text: "Iași", value: "Iași" },
       { text: "Constanța", value: "Constanța" },
       { text: "Brașov", value: "Brașov" },
-      { text: "Galați", value: "Galați" }
+      { text: "Galați", value: "Galați" },
     ],
   },
   {
@@ -1754,6 +1754,19 @@ export const countriesDataEn = [
     ],
   },
   {
+    text: "Syria",
+    value: "SY",
+    children: [
+      { text: "Damascus", value: "Damascus" },
+      { text: "Aleppo", value: "Aleppo" },
+      { text: "Latakia", value: "Latakia" },
+      { text: "Hama", value: "Hama" },
+      { text: "Deir ez-Zor", value: "Deir ez-Zor" },
+      { text: "Idlib", value: "Idlib" },
+      { text: "Daraa", value: "Daraa" },
+    ],
+  },
+  {
     text: "Tajikistan",
     value: "TJ",
     children: [
@@ -1896,6 +1909,25 @@ export const countriesDataEn = [
       { text: "Odessa", value: "Odessa" },
       { text: "Dnipro", value: "Dnipro" },
       { text: "Lviv", value: "Lviv" },
+      { text: "Zaporizhzhia", value: "Zaporizhzhia" },
+      { text: "Vinnytsia", value: "Vinnytsia" },
+      { text: "Khmelnytskyi", value: "Khmelnytskyi" },
+      { text: "Cherkasy", value: "Cherkasy" },
+      { text: "Poltava", value: "Poltava" },
+      { text: "Sumy", value: "Sumy" },
+      { text: "Chernihiv", value: "Chernihiv" },
+      { text: "Zhytomyr", value: "Zhytomyr" },
+      { text: "Rivne", value: "Rivne" },
+      { text: "Lutsk", value: "Lutsk" },
+      { text: "Ternopil", value: "Ternopil" },
+      { text: "Ivano-Frankivsk", value: "Ivano-Frankivsk" },
+      { text: "Uzhhorod", value: "Uzhhorod" },
+      { text: "Chernivtsi", value: "Chernivtsi" },
+      { text: "Kherson", value: "Kherson" },
+      { text: "Mykolaiv", value: "Mykolaiv" },
+      { text: "Kryvyi Rih", value: "Kryvyi Rih" },
+      { text: "Mariupol", value: "Mariupol" },
+      { text: "Sievierodonetsk", value: "Sievierodonetsk" },
     ],
   },
   {

+ 32 - 0
src/common/js/countries.js

@@ -1755,6 +1755,19 @@ export const countriesData = [
     ],
   },
   {
+    text: "叙利亚",
+    value: "SY",
+    children: [
+      { text: "大马士革", value: "Damascus" },
+      { text: "阿勒颇", value: "Aleppo" },
+      { text: "拉塔基亚", value: "Latakia" },
+      { text: "哈马", value: "Hama" },
+      { text: "代尔祖尔", value: "Deir ez-Zor" },
+      { text: "伊德利卜", value: "Idlib" },
+      { text: "德拉", value: "Daraa" },
+    ],
+  },
+  {
     text: "塔吉克斯坦",
     value: "TJ",
     children: [
@@ -1897,6 +1910,25 @@ export const countriesData = [
       { text: "敖德萨", value: "Odessa" },
       { text: "第聂伯罗", value: "Dnipro" },
       { text: "利沃夫", value: "Lviv" },
+      { text: "扎波罗热", value: "Zaporizhzhia" },
+      { text: "文尼察", value: "Vinnytsia" },
+      { text: "赫梅利尼茨基", value: "Khmelnytskyi" },
+      { text: "切尔卡瑟", value: "Cherkasy" },
+      { text: "波尔塔瓦", value: "Poltava" },
+      { text: "苏梅", value: "Sumy" },
+      { text: "切尔尼戈夫", value: "Chernihiv" },
+      { text: "日托米尔", value: "Zhytomyr" },
+      { text: "罗夫诺", value: "Rivne" },
+      { text: "卢茨克", value: "Lutsk" },
+      { text: "捷尔诺波尔", value: "Ternopil" },
+      { text: "伊万诺-弗兰科夫斯克", value: "Ivano-Frankivsk" },
+      { text: "乌日霍罗德", value: "Uzhhorod" },
+      { text: "切尔诺夫策", value: "Chernivtsi" },
+      { text: "赫尔松", value: "Kherson" },
+      { text: "尼古拉耶夫", value: "Mykolaiv" },
+      { text: "克里维里赫", value: "Kryvyi Rih" },
+      { text: "马里乌波尔", value: "Mariupol" },
+      { text: "北顿涅茨克", value: "Sievierodonetsk" },
     ],
   },
   {

+ 2 - 1
src/common/js/utils.js

@@ -56,7 +56,8 @@ export const remoteMenus = {
   "C24": t("remote.C24"),
   "C25": t("remote.C25"),
   "C26": t("remote.C26"),
-  "C27": t("remote.C27")
+  "C27": t("remote.C27"),
+  "C28": t("remote.C28"),
 }
 
 // 判断值是否是数字 true:数值型的,false:非数值型

+ 10 - 0
src/components/NavBar.vue

@@ -50,4 +50,14 @@ export default {
 
 <style lang="less" scoped>
 @import "../common/style/mixin";
+.nav-bar {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 50px;
+  background: white;
+  box-shadow: 0 -2px 12px rgba(77,106,221,0.1);
+  z-index: 100;
+}
 </style>

+ 3 - 1
src/components/SimpleHeader.vue

@@ -83,7 +83,8 @@ import frFR from "vant/es/locale/lang/fr-FR";
 import esES from "vant/es/locale/lang/es-ES";
 // 引入葡萄牙语语言包
 import ptBR from "vant/es/locale/lang/pt-BR";
-
+// 引入乌克兰语语言包
+import ukUA from "vant/es/locale/lang/uk-UA";
 export default {
   props: {
     name: {
@@ -143,6 +144,7 @@ export default {
       { code: 'fr', label: 'Français', vant: frFR, flag: 'https://flagcdn.com/fr.svg' },
       { code: 'es', label: 'Español', vant: esES, flag: 'https://flagcdn.com/es.svg' },
       { code: 'pt', label: 'Português', vant: ptBR, flag: 'https://flagcdn.com/pt.svg' },
+      { code: 'uk', label: 'Українська', vant: ukUA, flag: 'https://flagcdn.com/ua.svg' }
     ]);
 
     // 当前语言

+ 86 - 31
src/components/commom/kDialog/index.vue

@@ -1,26 +1,20 @@
 <template>
-  <div class="kDialogIdx">
-    <!-- 通知弹窗 -->
-    <van-dialog
-      closeOnClickOverlay
-      v-model:show="dialogShow"
-      :title="dialogTitle"
-      :showConfirmButton="false"
-      :showCancelButton="false"
-    >
-      <div class="operCheckBox">
-        <div class="operCheckCon">
-          <div class="l-flex-center">
-            {{ dialogContent }}
-          </div>
+  <!-- 通知弹窗 -->
+  <div class="k-dialog">
+    <van-dialog close-on-click-overlay v-model:show="dialogShow" :title="dialogTitle" :show-confirm-button="false"
+      :show-cancel-button="false">
+      <div class="dialog-content">
+        <div class="content-main">
+          <div class="text-content">{{ dialogContent }}</div>
           <slot name="content"></slot>
-          <div :class="(cancelBtnTxt&&confirmBtnTxt)?'flex-row justify-between':'l-flex-center'" class="block6">
-            <div v-if="cancelBtnTxt" class="mod7 flex-col" @click="cancelClk">
-              <span class="info5">{{ cancelBtnTxt }}</span>
-            </div>
-            <div v-if="confirmBtnTxt" class="mod8 flex-col" @click="confirmClk">
-              <span class="info6">{{ confirmBtnTxt }}</span>
-            </div>
+
+          <div class="action-buttons" :class="{ 'space-between': cancelBtnTxt && confirmBtnTxt }">
+            <button v-if="cancelBtnTxt" class="btn cancel-btn" @click="cancelClk">
+              {{ cancelBtnTxt }}
+            </button>
+            <button v-if="confirmBtnTxt" class="btn confirm-btn" @click="confirmClk">
+              {{ confirmBtnTxt }}
+            </button>
           </div>
         </div>
       </div>
@@ -35,7 +29,7 @@
  *
  */
 import { ref } from "vue";
-import {styleUrl} from "../../../common/js/utils";
+import { styleUrl } from "../../../common/js/utils";
 export default {
   props: {
     // 弹窗标题
@@ -59,14 +53,14 @@ export default {
       default: "",
     },
     // 是否点击取消就会关闭弹窗
-    isCloseForCancel:{
-      type:Boolean,
-      default:true,
+    isCloseForCancel: {
+      type: Boolean,
+      default: true,
     },
     // 是否点击确定就会关闭弹窗
-    isCloseForConfirm:{
-      type:Boolean,
-      default:true,
+    isCloseForConfirm: {
+      type: Boolean,
+      default: true,
     },
   },
   setup(props, ctx) {
@@ -81,14 +75,14 @@ export default {
     };
     // 点击左侧按钮
     const cancelClk = () => {
-      if(props.isCloseForCancel){
+      if (props.isCloseForCancel) {
         closeDialog();
       }
       ctx.emit("cancelclk", "左侧按钮111");
     };
     // 点击右侧按钮
     const confirmClk = () => {
-      if(props.isCloseForConfirm){
+      if (props.isCloseForConfirm) {
         closeDialog();
       }
       ctx.emit("confirmclk", "右侧按钮222");
@@ -107,5 +101,66 @@ export default {
 </script>
 
 <style lang="less" scoped>
-@import "@/common/style/common.less";
+.k-dialog {
+  --primary-color: #2c87c8;
+  --text-color-light: #ffffff;
+  --border-color: #d7d7e2;
+
+  .dialog-content {
+    padding: 0 10px;
+    padding-top: 10px;
+
+    .content-main {
+      padding-top: 10px;
+      border-top: 1px solid var(--border-color);
+
+      .text-content {
+        color: #404d74;
+        font-size: 13px;
+        text-align: center;
+        line-height: 1.5;
+        padding: 0 1rem;
+      }
+
+      .action-buttons {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        gap: 15px;
+        margin: 20px 35px;
+
+        &.space-between {
+          justify-content: space-between;
+        }
+
+        .btn {
+          border-radius: 20px;
+          padding: 8px 20px;
+          font-size: 13px;
+          font-family: PingFangSC-Medium;
+          border: 1px solid transparent;
+          cursor: pointer;
+          transition: opacity 0.2s;
+          min-width: 80px;
+          text-align: center;
+
+          &:active {
+            opacity: 0.8;
+          }
+        }
+
+        .cancel-btn {
+          border-color: var(--primary-color);
+          color: var(--primary-color);
+          background: transparent;
+        }
+
+        .confirm-btn {
+          background-color: var(--primary-color);
+          color: var(--text-color-light);
+        }
+      }
+    }
+  }
+}
 </style>

+ 111 - 32
src/components/dateSelectList/index.vue

@@ -1,41 +1,31 @@
 <template>
-  <div class="dateSelectListBox flex-col">
-    <div class="Tabs1 flex-col">
-      <div class="timeTabBox">
-        <div class="timeTab" :class="{ active: timeType === '0' }" @click="timeChange('0')">
-          {{ $t('dateSelectList.today') }}</div>
-        <div class="timeTab" :class="{ active: timeType === '1' }" @click="timeChange('1')">
-          {{ $t('dateSelectList.yesterday') }}</div>
-        <div class="timeTab" :class="{ active: timeType === '2' }" @click="timeChange('2')">
-          {{ $t('dateSelectList.thisWeek') }}</div>
-        <div class="timeTab" :class="{ active: timeType === '3' }" @click="timeChange('3')">
-          {{ $t('dateSelectList.thisMonth') }}</div>
-        <div class="timeTab" :class="{ active: timeType === '4' }" @click="timeChange('4')">
-          {{ $t('dateSelectList.other') }}
-          <div class="block3 flex-col"></div>
-        </div>
-        <!-- 日期选择 -->
-        <van-calendar color="#2c87c8" v-model:show="calendarShow" type="range" :max-range="186" :show-confirm="false"
-          :allow-same-day="true" :min-date="minDate" :max-date="maxDate" @confirm="calendarConfirm" />
-        <!-- 选择统计类型 -->
-        <van-popup v-model:show="timeTypeShow" position="bottom">
-          <van-picker :title="$t('dateSelectList.timeType')" :columns="timeTypeList" @confirm="timeTypeConfirm"
-            @cancel="timeTypeCancel" />
-        </van-popup>
-        <!-- 按月统计 -->
-        <van-popup v-model:show="monthDateShow" position="bottom">
-          <van-date-picker v-model="monthDate" :title="$t('dateSelectList.monthDate')" :min-date="minDate" :max-date="maxDate" @confirm="monthDateConfirm" @cancel="monthDateCancel"
-            :columns-type="monthDateType" />
-        </van-popup>
-      </div>
-    </div>
+  <div class="date-selector">
+    <nav class="time-tabs">
+      <button v-for="tab in tabs" :key="tab.id" class="tab-item" :class="{ active: timeType === tab.id }"
+        @click="timeChange(tab.id)">
+        {{ $t(`dateSelectList.${tab.labelKey}`) }}
+        <span v-if="tab.id === '4'" class="dropdown-indicator"></span>
+      </button>
+    </nav>
+
+    <!-- 日期选择器 -->
+    <van-calendar color="var(--primary-color)" v-model:show="calendarShow" type="range" :max-range="366"
+      :show-confirm="false" :allow-same-day="true" :min-date="minDate" :max-date="maxDate" @confirm="calendarConfirm" />
+
+    <!-- 类型选择弹出层 -->
+    <van-popup v-model:show="timeTypeShow" position="bottom">
+      <van-picker :title="$t('dateSelectList.timeType')" :columns="timeTypeList" @confirm="timeTypeConfirm"
+        @cancel="timeTypeCancel" />
+    </van-popup>
+    <!-- 按月统计 -->
+    <van-calendar color="#2c87c8" v-model:show="monthDateShow" type="range" :max-range="366" :show-confirm="false"
+      :allow-same-day="true" :min-date="minDate" :max-date="maxDate" @confirm="monthDateConfirm" />
   </div>
 </template>
 
 <script>
 import { ref } from "vue";
 import dateUtil from "../../utils/dateUtil";
-import { styleUrl } from "../../common/js/utils";
 import { getLoginUser } from "@/common/js/utils";
 // import { showToast } from "vant";
 import { useI18n } from 'vue-i18n';
@@ -46,7 +36,13 @@ export default {
   components: {},
   setup(props, { emit }) {
     // 加载样式
-    styleUrl('dateSelectList');
+    const tabs = [
+      { id: '0', labelKey: 'today' },
+      { id: '1', labelKey: 'yesterday' },
+      { id: '2', labelKey: 'thisWeek' },
+      { id: '3', labelKey: 'thisMonth' },
+      { id: '4', labelKey: 'other' }
+    ]
     const { t } = useI18n();
     const minDate = new Date(2022, 0, 1);
     const maxDate = new Date();
@@ -217,6 +213,7 @@ export default {
       monthDateConfirm,
       monthDateCancel,
       monthDate,
+      tabs,
     };
   },
 };
@@ -224,4 +221,86 @@ export default {
 
 <style lang="less" scoped>
 @import "../../common/style/common";
+.date-selector {
+  --primary-color: #2c87c8;
+  --border-color: #b9bad0;
+  --text-primary: #404d74;
+  --bg-active: var(--primary-color);
+  --tab-height: 38px;
+
+  padding: 0 10px;
+  margin: 0 auto;
+
+  .time-tabs {
+    display: flex;
+    background: #fff;
+    border-radius: 4px;
+    border: 1px solid var(--border-color);
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    overflow: hidden;
+
+    .tab-item {
+      flex: 1;
+      position: relative;
+      height: var(--tab-height);
+      padding: 0 12px;
+      border: none;
+      background: transparent;
+      color: var(--text-primary);
+      font-size: 13px;
+      white-space: nowrap;
+      cursor: pointer;
+      transition: all 0.2s ease;
+      border-right: 1px solid var(--border-color);
+
+      &:last-child {
+        border-right: none;
+      }
+
+      &:hover {
+        background-color: rgba(77, 106, 221, 0.1);
+      }
+
+      &.active {
+        background: var(--bg-active);
+        color: #fff;
+        font-weight: 500;
+
+        &::after {
+          content: "";
+          position: absolute;
+          bottom: -5px;
+          left: 50%;
+          transform: translateX(-50%);
+          border-left: 6px solid transparent;
+          border-right: 6px solid transparent;
+          border-top: 6px solid var(--bg-active);
+        }
+
+        .dropdown-indicator {
+          border-top-color: #fff;
+        }
+      }
+
+      .dropdown-indicator {
+        display: inline-block;
+        margin-left: 4px;
+        border-left: 4px solid transparent;
+        border-right: 4px solid transparent;
+        border-top: 4px solid var(--text-primary);
+        transition: border-color 0.2s;
+      }
+    }
+  }
+
+  // 适配移动端
+  @media (max-width: 480px) {
+    .time-tabs {
+      .tab-item {
+        font-size: 12px;
+        padding: 0 5px;
+      }
+    }
+  }
+}
 </style>

+ 192 - 67
src/components/typeDownMenu/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <van-dropdown-menu class="titleMenu" swipe-threshold="3" active-color="#2c87c8">
+  <van-dropdown-menu class="titleMenu" swipe-threshold="3" :overlay="false"  active-color="#2c87c8">
     <!-- 用户 -->
     <van-dropdown-item v-if="isShowAdmin()" :title="adminTypeTitle" v-model="adminType" :options="adminList"
       @change="adminTypeChange" />
@@ -24,7 +24,7 @@
 </template>
 
 <script>
-import { onMounted, toRefs, reactive, computed, ref } from "vue";
+import { onMounted, toRefs, computed, reactive, ref } from "vue";
 import { getAdminList, getEquipmentList } from '@/service/typeSelectList';
 import { getLoginUser } from '@/common/js/utils';
 import { useI18n } from 'vue-i18n';
@@ -43,12 +43,24 @@ export default {
     const user = getLoginUser(); // 获取登录用户
 
     const { t } = useI18n();
+    // 用户类型
+    const userType = ref(user.ifForeign);
+    // 支付方式类型选择
+    const payTypeStatus = ref(false);
     // 支付方式
     const paymentType = ref(null);
     // 支付方式标题
-    const paymentTypeTitle = computed(() => (t('typeSelectList.paymentMethod')));
+    const paymentTypeTitle = computed(() => {
+      if (!payTypeStatus.value) {
+        return t('typeSelectList.paymentMethod'); // 未选择时的原始标题
+      }
+      const selected = payList.value.find(
+        item => item.value === searchParams.payType
+      );
+      return selected ? selected.text : t('typeSelectList.paymentMethod');
+    });
     // 支付方式列表
-    const payList = computed(() => (user.ifForeign === '0' ? [
+    const payList = computed(() => (userType.value === '0' ? [
       { text: t('typeSelectList.whole'), value: '' },
       { text: t('typeSelectList.mainSweepOfAlipay'), value: 'ALIPAY_NATIVE' },
       { text: t('typeSelectList.weChatScanning'), value: 'WEIXIN_NATIVE' },
@@ -66,71 +78,84 @@ export default {
     ]));
     // 选择支付方式
     const paymentTypeChange = (value) => {
-      paymentTypeTitle.value = payList.value.find(payList => payList.value === value).text;
+      payTypeStatus.value = true;
       searchParams.payType = value;
       outputDate();
     }
 
-
+    // 公司平台选择
+    const companyTypeStatus = ref(false);
     // 公司平台
     const companyType = ref(null);
     // 公司平台标题
-    const companyTypeTitle = computed(() =>(t('typeSelectList.companies')));
+    const companyTypeTitle = computed(() => {
+      if (!companyTypeStatus.value) {
+        return t('typeSelectList.companies'); // 未选择时的原始标题
+      }
+      const selected = companyList.value.find(
+        item => item.value === searchParams.companyType
+      );
+      return selected ? selected.text : t('typeSelectList.companies');
+    });
     // 公司平台列表
-    const companyList = computed(() =>[
+    const companyList = computed(() => [
       { text: t('typeSelectList.whole'), value: '' },
       { text: t('typeSelectList.sz'), value: '0' },
       { text: t('typeSelectList.sc'), value: '1' },
     ]);
     // 选择公司平台
     const companyTypeChange = (value) => {
-      companyTypeTitle.value = companyList.value.find(companyList => companyList.value === value).text;
+      companyTypeStatus.value = true;
       searchParams.companyType = value;
       outputDate();
     }
 
+    // 账号类型选择
+    const foreignTypeStatus = ref(false);
     // 账号类型
     const foreignType = ref(null);
     // 账号类型标题
-    const foreignTypeTitle = computed(() =>(t('typeSelectList.ifForeignes')));
+    const foreignTypeTitle = computed(() => {
+      if (!foreignTypeStatus.value) {
+        return t('typeSelectList.ifForeignes'); // 未选择时的原始标题
+      }
+      const selected = foreignList.value.find(
+        item => item.value === userType.value
+      );
+      return selected ? selected.text : t('typeSelectList.ifForeignes');
+    });
     // 账号地区列表
-    const foreignList = computed(() =>[
+    const foreignList = computed(() => [
       { text: t('typeSelectList.mainland'), value: '0' },
       { text: t('typeSelectList.overseas'), value: '1' },
     ]);
     // 选择账号类型
     const foreignTypeChange = (value) => {
-      foreignTypeTitle.value = foreignList.value.find(foreignList => foreignList.value === value).text;
-      if (value == "0") {
-        payList.value = [
-          { text: t('typeSelectList.whole'), value: '' },
-          { text: t('typeSelectList.mainSweepOfAlipay'), value: 'ALIPAY_NATIVE' },
-          { text: t('typeSelectList.weChatScanning'), value: 'WEIXIN_NATIVE' },
-          { text: t('typeSelectList.antiScanningOfAlipay'), value: 'ALIPAY_CARD' },
-          { text: t('typeSelectList.weChatBackScanning'), value: 'WEIXIN_CARD' },
-          { text: t('typeSelectList.eCNYBackeScanning'), value: 'ECNY_CARD' },
-        ];
-      } else {
-        payList.value = [
-          { text: t('typeSelectList.whole'), value: '' },
-          { text: t('typeSelectList.noPaymentRequired'), value: 0 },
-          { text: t('typeSelectList.coin'), value: 1 },
-          { text: t('typeSelectList.notes'), value: 2 },
-          { text: t('typeSelectList.coinsNotes'), value: 3 },
-          { text: t('typeSelectList.creditCard'), value: 4 },
-          { text: t('typeSelectList.electronicPayment'), value: 5 },
-        ];
+      if (userType.value != value) {
+        searchParams.payType = '';
       }
+      foreignTypeStatus.value = true;
+      userType.value = value;
       searchParams.ifForeign = value;
       outputDate();
     }
 
+    // 设备类型选择
+    const machineTypeStatus = ref(false);
     // 设备类型
     const machineType = ref(null);
     // 设备类型标题
-    const machineTypeTitle = computed(() =>(t('typeSelectList.machines')));
+    const machineTypeTitle = computed(() => {
+      if (!machineTypeStatus.value) {
+        return t('typeSelectList.machines'); // 未选择时的原始标题
+      }
+      const selected = machineList.value.find(
+        item => item.value === searchParams.machineType
+      );
+      return selected !== null ? selected.text : t('typeSelectList.machines');
+    });
     // 设备类型列表
-    const machineList = computed(() =>[
+    const machineList = computed(() => [
       { text: t('typeSelectList.whole'), value: '' },
       { text: t('typeSelectList.MG'), value: '0' },
       { text: t('typeSelectList.POP'), value: '1' },
@@ -138,7 +163,7 @@ export default {
     ]);
     // 选择设备类型
     const machineTypeChange = (value) => {
-      machineTypeTitle.value = machineList.value.find(machineList => machineList.value === value).text;
+      machineTypeStatus.value = true;
       searchParams.machineType = value;
       outputDate();
     }
@@ -146,21 +171,17 @@ export default {
     // 设备筛选
     const deviceType = ref(null);
     // 设备筛选标题
-    const deviceTypeTitle = computed(() =>(t('typeSelectList.allDevices')));
+    const deviceTypeTitle = ref(t('typeSelectList.allDevices'));
     // 设备列表
-    const deviceList = ref([
-      {
-        text: t('typeSelectList.allDevices'),
-        value: ''
-      }
-    ]);
+    const deviceList = ref([]);
     // 获取设备列表
     const getDeviceListFun = async () => {
       const { data } = await getEquipmentList({ adminId: user.id });
       if (data.code === '00000') {
-        data.data.map(item => {
-          deviceList.value.push({ text: item.name != null ? item.name : item.clientId, value: item.id });
+        deviceList.value = data.data.map(item => {
+          return { text: item.name != null ? item.name : item.clientId, value: item.id }
         });
+        deviceList.value.unshift({ text: t('typeSelectList.allDevices'), value: '' });
       }
     }
     // 设备选择
@@ -174,12 +195,22 @@ export default {
       outputDate();
     }
 
+    // 订单状态选择
+    const orderStatusStatus = ref(false);
     // 订单状态
     const orderStatus = ref(null);
     // 订单状态标题
-    const orderStatusTitle = computed(() =>(t('typeSelectList.orderStatus')));
+    const orderStatusTitle = computed(() => {
+      if (!orderStatusStatus.value) {
+        return t('typeSelectList.orderStatus'); // 未选择时的原始标题
+      }
+      const selected = orderStatusList.value.find(
+        item => item.value === searchParams.status
+      );
+      return selected ? selected.text : t('typeSelectList.orderStatus');
+    });
     // 订单状态列表
-    const orderStatusList = computed(() =>[
+    const orderStatusList = computed(() => [
       { text: t('typeSelectList.whole'), value: '' },
       { text: t('typeSelectList.unpaid'), value: 0 },
       { text: t('typeSelectList.paid'), value: 1 },
@@ -188,7 +219,7 @@ export default {
     ]);
     // 选择订单状态
     const orderStatusChange = (value) => {
-      orderStatusTitle.value = orderStatusList.value.find(orderStatusList => orderStatusList.value === value).text;
+      orderStatusStatus.value = true;
       searchParams.status = value;
       outputDate();
     }
@@ -208,33 +239,14 @@ export default {
         });
       }
     }
+    // 选择商户
     const adminTypeChange = (value) => {
-      console.log(value);
       adminTypeTitle.value = adminList.value.find(adminList => adminList.value === value).text;
       searchParams.adminType = (adminTypeTitle.value === t('typeSelectList.allSuboUsers')) ? 'all' : '';
       searchParams.userName = (adminTypeTitle.value === t('typeSelectList.allSuboUsers')) ? 'all' : (adminTypeTitle.value === t('typeSelectList.thisMerchant')) ? user.username : adminTypeTitle.value;
       searchParams.adminId = (value === ('this' || 'all') ? null : value);
       searchParams.ifForeign = adminList.value.find(adminList => adminList.value === value).ifForeign;
-      if (searchParams.ifForeign == "0") {
-        payList.value = [
-          { text: t('typeSelectList.whole'), value: '' },
-          { text: t('typeSelectList.mainSweepOfAlipay'), value: 'ALIPAY_NATIVE' },
-          { text: t('typeSelectList.weChatScanning'), value: 'WEIXIN_NATIVE' },
-          { text: t('typeSelectList.antiScanningOfAlipay'), value: 'ALIPAY_CARD' },
-          { text: t('typeSelectList.weChatBackScanning'), value: 'WEIXIN_CARD' },
-          { text: t('typeSelectList.eCNYBackeScanning'), value: 'ECNY_CARD' },
-        ];
-      } else {
-        payList.value = [
-          { text: t('typeSelectList.whole'), value: '' },
-          { text: t('typeSelectList.noPaymentRequired'), value: 0 },
-          { text: t('typeSelectList.coin'), value: 1 },
-          { text: t('typeSelectList.notes'), value: 2 },
-          { text: t('typeSelectList.coinsNotes'), value: 3 },
-          { text: t('typeSelectList.creditCard'), value: 4 },
-          { text: t('typeSelectList.electronicPayment'), value: 5 },
-        ];
-      }
+      userType.value = searchParams.ifForeign;
       outputDate();
     }
 
@@ -327,4 +339,117 @@ export default {
 
 <style lang="less" scoped>
 @import "@/common/style/common.less";
+
+.titleMenu {
+  --card-bg: #ffffff;
+  --card-radius: 12px;
+  --card-shadow: 0 4px 20px rgba(77, 106, 221, 0.1);
+  --title-color: #404d74;
+  --active-color: #2c87c8;
+  --border-color: #eef0fa;
+  --item-padding: 16px 24px;
+
+  margin: 10px;
+  border-radius: var(--card-radius);
+  box-shadow: var(--card-shadow);
+  background: var(--card-bg);
+  overflow: visible;
+  /* 修复裁剪问题 */
+  position: relative;
+  /* 创建定位上下文 */
+
+  :deep(.van-dropdown-menu__bar) {
+    height: auto;
+    background: transparent;
+    padding: 0px 5px;
+  }
+
+  :deep(.van-dropdown-menu__item) {
+    flex: 1;
+    min-width: 82px;
+    position: relative;
+    padding: 8px 0px;
+
+    &:not(:last-child)::after {
+      content: '';
+      position: absolute;
+      right: 0;
+      top: 50%;
+      transform: translateY(-50%);
+      width: 1px;
+      height: 24px;
+      background: var(--border-color);
+    }
+  }
+
+  :deep(.van-dropdown-menu__title) {
+    display: flex !important;
+    align-items: center;
+    justify-content: space-between;
+    color: var(--title-color);
+    font-size: 10px;
+    font-weight: 500;
+    transition: all 0.5s;
+    width: auto !important;
+
+    &::after {
+      content: '';
+      position: relative !important;
+      right: 0 !important;
+      top: 0 !important;
+      transform: none !important;
+      display: inline-block;
+      width: 0;
+      height: 0;
+      border: 5px solid;
+      border-color: var(--title-color) transparent transparent;
+      margin-left: 8px;
+      margin-top: 3px;
+      order: 1;
+      transition: transform 0.5s;
+    }
+
+    &--active {
+      color: var(--active-color);
+
+      &::after {
+        border-color: var(--active-color) transparent transparent;
+        transform: rotate(-180deg) translateY(2px) !important;
+      }
+    }
+  }
+
+  :deep(.van-dropdown-item) {
+    position: static;
+
+    &__content {
+      top: calc(100% + 4px) !important;
+      left: 0 !important;
+      right: 0 !important;
+      transform: none !important;
+      border-radius: var(--card-radius);
+      box-shadow: var(--card-shadow);
+      border: 0;
+      max-height: 60vh;
+      z-index: 9999;
+      /* 确保层级 */
+    }
+  }
+
+  @media (max-width: 480px) {
+    margin: 10px;
+    border-radius: 8px;
+
+    :deep(.van-dropdown-menu__title) {
+      padding: 2px 4px !important;
+      font-size: 12px;
+
+      &::after {
+        margin-left: 2px;
+        margin-top: 4px;
+        border-width: 4px;
+      }
+    }
+  }
+}
 </style>

+ 14 - 14
src/router/index.js

@@ -364,20 +364,6 @@ const router = createRouter({
       component: () => import("@/views/taskMessage/equipment"),
       meta: { index: 1 },
     },
-    // 提现审批
-    {
-      path: "/taskJoinPayMchCheck",
-      name: "taskJoinPayMchCheck",
-      component: () => import("@/views/taskMessage/joinpayMchCheck"),
-      meta: { index: 1 },
-    },
-    // 提现审批详情
-    {
-      path: "/taskJoinPayMchCheckInfo",
-      name: "taskJoinPayMchCheckInfo",
-      component: () => import("@/views/taskMessage/joinpayMchCheck/info"),
-      meta: { index: 1 },
-    },
     // 分销审批
     {
       path: "/taskProportion",
@@ -518,6 +504,20 @@ const router = createRouter({
       component: () => import("@/views/purse/index"),
       meta: { index: 1 },
     },
+    // 修改支付方式
+    {
+      path: "/payment",
+      name: "payment",
+      component: () => import("@/views/device/payment/index"),
+      meta: { index: 1 },
+    },
+    // 提现列表
+    {
+      path: "/withdrawList",
+      name: "withdrawList",
+      component: () => import("@/views/purse/withdrawList"),
+      meta: { index: 1 },
+    },
     // apk管理,广告管理,订单导出 不是所有的帐号能看到
   ],
 });

+ 10 - 0
src/service/device/index.js

@@ -330,3 +330,13 @@ export function getReturnCoinList(params) {
 export function applyReturnCoin(params) {
   return axios.post(`/SZWL-SERVER/returnCoinRecord/apply`, params);
 }
+
+// 查询设备闹钟列表
+export function getAlaramClockByDevice(params) {
+  return axios.get(`/SZWL-SERVER/tAlarmClock/getList?${stringToUrl(params)}`);
+}
+
+// 修改闹钟状态
+export function updateAlaramClockStatus(params) {
+  return axios.post(`/SZWL-SERVER/tAlarmClock/updataStatus`, params);
+}

+ 10 - 20
src/service/huifuMch/index.js

@@ -22,16 +22,6 @@ export function getHuifuMchCheck(params) {
     return axios.get(`/SZWL-SERVER/tHuifuMch/getHuifuMchCheck?${stringToUrl(params)}`);
 }
 
-// 上传材料图片
-export function uploadPic(params) {
-    return axios.post(`/SZWL-SERVER/tHuifuMch/uploadPic`, params);
-}
-
-// 新上传材料图片
-export function newUploadPic(params) {
-    return axios.post(`/SZWL-SERVER/tHuifuMch/newUploadPic`, params);
-}
-
 // 提交审核
 export function submitHuifuCheck(params) {
     return axios.post(`/SZWL-SERVER/tHuifuMch/submitCheck`, params);
@@ -42,11 +32,6 @@ export function updateMerchant(params) {
     return axios.post(`/SZWL-SERVER/tHuifuMch/updateMerchant`, params);
 }
 
-// 发送验证码
-export function sendSms(params) {
-    return axios.get(`/SZWL-SERVER/tHuifuMch/sendSms?${stringToUrl(params)}`);
-}
-
 // 获取商户号
 export function getHuifuId(params) {
     return axios.get(`/SZWL-SERVER/tHuifuMch/getHuifuId?${stringToUrl(params)}`);
@@ -57,13 +42,18 @@ export function auditMerchantUpdate(params) {
     return axios.post(`/SZWL-SERVER/tHuifuMch/auditMerchantUpdate`, params);
 }
 
-// 汇付账号修改审批
-export function auditUpdateMerchant(params) {
-    return axios.get(`/SZWL-SERVER/tHuifuMch/auditUpdateMerchant?${stringToUrl(params)}`);
-}
-
 // 查询账户余额
 export function checkBalance(params) {
     return axios.get(`/SZWL-SERVER/tHuifuMch/checkBalance?${stringToUrl(params)}`);
 }
 
+// 查询商户业务
+export function getMerchantBusiness(params) {
+    return axios.get(`/SZWL-SERVER/tHuifuMch/getHuifuMch?${stringToUrl(params)}`);
+}
+
+// 增加取现业务
+export function addWithdraw(params) {
+    return axios.get(`/SZWL-SERVER/tHuifuMch/addCashBusiness?${stringToUrl(params)}`);
+}
+

+ 1 - 4
src/service/joinpayMch/index.js

@@ -25,10 +25,7 @@ export function updateApproveStatus(params) {
 export function altMchSign(params) {
   return axios.get(`/SZWL-SERVER/tJoinpayMch/altMchSign?${stringToUrl(params)}`);
 }
-// 汇付账号入驻审批
-export function auditAddMerchant(params) {
-  return axios.get(`/SZWL-SERVER/tHuifuMch/auditAddMerchant?${stringToUrl(params)}`);
-}
+
 // 更新汇付签约状态
 export function updateConStat(params) {
   return axios.post(`/SZWL-SERVER/tHuifuMch/updateConStat`, params);

+ 0 - 12
src/service/purse/indes.js

@@ -1,12 +0,0 @@
-import axios from "../../utils/axios";
-import { stringToUrl } from '@/common/js/utils';
-
-// MQTT发送消息
-export function sendMqttMessage(params) {
-  return axios.post(`/SZWL-SERVER/purse/balance`, params);
-}
-
-// 获取余额
-export function getBalance(params) {
-  return axios.get(`/SZWL-SERVER/purse/balance?${stringToUrl(params)}`);
-}

+ 37 - 0
src/service/purse/index.js

@@ -0,0 +1,37 @@
+import axios from "../../utils/axios";
+import { stringToUrl } from '@/common/js/utils';
+
+// MQTT发送消息
+export function sendMqttMessage(params) {
+  return axios.post(`/SZWL-SERVER/purse/balance`, params);
+}
+
+// 获取余额
+export function getBalance(params) {
+  return axios.get(`/SZWL-SERVER/purse/balance?${stringToUrl(params)}`);
+}
+
+// 提现
+export function withdraw(params) {
+  return axios.post(`/SZWL-SERVER/purse/withdraw`, params);
+}
+
+// 提现记录
+export function withdrawRecord(params) {
+  return axios.post(`/SZWL-SERVER/purse/withdrawRecordList`, params);
+}
+
+// 导出提现记录
+export function exportWithdrawRecord(params) {
+  return axios.post(`/SZWL-SERVER/purse/exportWithdrawRecord`, params, { responseType: 'blob' });
+}
+
+// 查询提现状态
+export function withdrawStatus(params) {
+  return axios.get(`/SZWL-SERVER/purse/withdrawStatus?${stringToUrl(params)}`);
+}
+
+// 证照识别
+export function idCardRecognition(params) {
+  return axios.post(`/SZWL-SERVER/purse/ocrImage`, params);
+}

+ 0 - 8
src/service/taskMessage/index.js

@@ -17,14 +17,6 @@ export function gettJoinpayMchCheckInfo(params) {
 export function changetJoinpayMchCheckStatus(params) {
   return axios.get(`/SZWL-SERVER/tJoinpayMchCheck/shenhe?${stringToUrl(params)}`);
 }
-// 汇付账号入驻审批
-export function auditAddMerchant(params) {
-  return axios.get(`/SZWL-SERVER/tHuifuMch/auditAddMerchant?${stringToUrl(params)}`);
-}
-// 汇付账号修改审批
-export function auditUpdateMerchant(params) {
-  return axios.get(`/SZWL-SERVER/tHuifuMch/auditUpdateMerchant?${stringToUrl(params)}`);
-}
 // 获取设备列表
 export function getEquipmentList(params) {
   return axios.get(`/SZWL-SERVER/tEquipment/listEquipment?${stringToUrl(params)}`);

+ 46 - 39
src/utils/i18n.js

@@ -14,55 +14,60 @@ import frFR from "vant/es/locale/lang/fr-FR";
 import esES from "vant/es/locale/lang/es-ES";
 // 引入葡萄牙语语言包
 import ptBR from "vant/es/locale/lang/pt-BR";
+// 引入乌克兰语语言包
+import ukUA from "vant/es/locale/lang/uk-UA";
 
-const curLang = localStorage.getItem('curLang');
-let language = 'en';
+const curLang = localStorage.getItem("curLang");
+let language = "en";
 // 储存语言,方便中英切换
 
 if (curLang) {
-    language = curLang;
-    localStorage.setItem('curLang', curLang);
+  language = curLang;
+  localStorage.setItem("curLang", curLang);
 } else {
-    language = navigatorLanguage();
-    localStorage.setItem('curLang', navigatorLanguage());
+  language = navigatorLanguage();
+  localStorage.setItem("curLang", navigatorLanguage());
 }
 
 const i18n = createI18n({
-    //多语言实例
-    legacy: false,
-    globalInjection: true,
-    // 默认语言
-    locale: localStorage.getItem("curLang")
-      ? localStorage.getItem("curLang")
-      : "en",
-    // 关闭控制台警告
-    silentFallbackWarn: true,
-    messages: {
-      en: require("../assets/language/en.json"), //英文包
-      zh: require("../assets/language/zh.json"), //中文包
-      ja: require("../assets/language/ja.json"), //日文包
-      ru: require("../assets/language/ru.json"), //俄语包
-      fr: require("../assets/language/fr.json"), //法语包
-      es: require("../assets/language/es.json"), //西班牙语包
-      pt: require("../assets/language/pt.json"), //葡萄牙语包
-    },
-  });
+  //多语言实例
+  legacy: false,
+  globalInjection: true,
+  // 默认语言
+  locale: localStorage.getItem("curLang")
+    ? localStorage.getItem("curLang")
+    : "en",
+  // 关闭控制台警告
+  silentFallbackWarn: true,
+  messages: {
+    en: require("../assets/language/en.json"), //英文包
+    zh: require("../assets/language/zh.json"), //中文包
+    ja: require("../assets/language/ja.json"), //日文包
+    ru: require("../assets/language/ru.json"), //俄语包
+    fr: require("../assets/language/fr.json"), //法语包
+    es: require("../assets/language/es.json"), //西班牙语包
+    pt: require("../assets/language/pt.json"), //葡萄牙语包
+    uk: require("../assets/language/uk.json"), //乌克兰语包
+  },
+});
 
 // 判断中英文,切换vant语言包
-if (language === 'en') {
-    Locale.use('en-US', enUS);
-} else if (language === 'ja') {
-    Locale.use('ja-JP', jaJP);
-} else if (language === 'ru') {
-    Locale.use('ru-RU', ruRU);
-} else if (language === 'fr') {
-    Locale.use('fr-FR', frFR);
-} else if (language === 'es') {
-    Locale.use('es-ES', esES);
-} else if (language === 'pt') {
-    Locale.use('pt-BR', ptBR);
+if (language === "en") {
+  Locale.use("en-US", enUS);
+} else if (language === "ja") {
+  Locale.use("ja-JP", jaJP);
+} else if (language === "ru") {
+  Locale.use("ru-RU", ruRU);
+} else if (language === "fr") {
+  Locale.use("fr-FR", frFR);
+} else if (language === "es") {
+  Locale.use("es-ES", esES);
+} else if (language === "pt") {
+  Locale.use("pt-BR", ptBR);
+} else if (language === "uk") {
+  Locale.use("uk-UA", ukUA);
 } else {
-    Locale.use('zh-CN', zhCN);
+  Locale.use("zh-CN", zhCN);
 }
 
 // 监听语言切换
@@ -90,8 +95,10 @@ i18n.global.onBeforeLanguageSwitch = (lang) => {
     case "pt-BR":
       Locale.use("pt-BR", ptBR);
       break;
+    case "uk-UA":
+      Locale.use("uk-UA", ukUA);
+      break;
   }
 };
 
 export default i18n;
-

+ 44 - 36
src/views/accountPer/add.vue

@@ -6,16 +6,19 @@
       <van-form @submit="onSubmit" class="modern-form">
         <!-- 表单字段 -->
         <van-field v-model="username" :label="$t('accountPer.usernameLabel')"
-          :placeholder="$t('accountPer.usernamePlaceholder')" left-icon="user-o" class="modern-field" />
+          :placeholder="$t('accountPer.usernamePlaceholder')" left-icon="user-o" class="modern-field"
+          :rules="[{ required: true, message: $t('accountPer.usernamePlaceholder') }]" />
 
         <van-field v-model="password" type="password" :label="$t('accountPer.passwordLabel')"
           :placeholder="passwordPlaceholder" left-icon="lock" class="modern-field" />
 
         <van-field v-model="name" :label="$t('accountPer.nameLabel')" :placeholder="$t('accountPer.namePlaceholder')"
-          left-icon="contact" class="modern-field" />
+          left-icon="contact" class="modern-field"
+          :rules="[{ required: true, message: $t('accountPer.namePlaceholder') }]" />
 
         <van-field v-model="phone" :label="$t('accountPer.phoneLabel')" :placeholder="$t('accountPer.phonePlaceholder')"
-          left-icon="phone" class="modern-field" />
+          left-icon="phone" class="modern-field"
+          :rules="[{ required: true, message: $t('accountPer.phonePlaceholder') }]" />
 
         <!-- 类型选择 -->
         <van-field name="radio" v-if="user.type === 0" class="radio-field">
@@ -30,7 +33,7 @@
         <!-- 角色选择 -->
         <van-field v-model="roleText" is-link readonly :label="$t('accountPer.roleLabel')"
           :placeholder="$t('accountPer.rolePlaceholder')" left-icon="friends-o" class="modern-field"
-          @click="roleShow = true" />
+          @click="roleShow = true" :rules="[{ required: true, message: $t('accountPer.rolePlaceholder') }]" />
 
         <!-- 启用开关 -->
         <van-field class="switch-field">
@@ -45,11 +48,13 @@
         <!-- 设备管理 -->
         <van-field v-model="cofficentForm.equipmentNames" :label="$t('accountPer.manageMachinesLabel')"
           :placeholder="$t('accountPer.manageMachinesPlaceholder')" left-icon="cluster-o" class="modern-field" readonly
-          clearable @click="busiEquipInpClk">
+          clearable @click="busiEquipInpClk"
+          :rules="[{ required: true, message: $t('accountPer.manageMachinesPlaceholder') }]">
           <template #right-icon>
             <div class="field-icons">
-              <van-icon v-if="cofficentForm.equipmentNames" name="clear" @click="cofficentForm.equipmentNames = ''; equipmentIds = ''" />
-              <van-icon name="arrow" @click="busiEquipInpClk"/>
+              <van-icon v-if="cofficentForm.equipmentNames" name="clear"
+                @click="cofficentForm.equipmentNames = ''; equipmentIds = ''" />
+              <van-icon name="arrow" @click="busiEquipInpClk" />
             </div>
           </template>
         </van-field>
@@ -81,7 +86,7 @@
 import kSelectPop from "../../components/commom/kSelectPop/index.vue";
 import { onMounted, reactive, toRefs, ref } from "vue";
 import sHeader from "../../components/SimpleHeader";
-import { showFailToast, showSuccessToast, showToast, showNotify } from 'vant';
+import { showFailToast, showSuccessToast, showToast, showNotify, showConfirmDialog } from 'vant';
 import {
   getSysRoleList,
   getEquipmentList,
@@ -89,7 +94,7 @@ import {
   updataLoginUser,
   deleteLoginUser,
 } from "../../service/accountPar/index";
-import { getLoginUser, styleUrl } from "../../common/js/utils";
+import { getLoginUser } from "../../common/js/utils";
 import md5 from "js-md5";
 import { useRouter } from "vue-router";
 import { useI18n } from "vue-i18n";
@@ -127,15 +132,13 @@ export default {
       isEnabled: true,
       roleList: "",
       equipmentIds: "",
-      companyType: "0",
+      companyType: "1",
     });
     const cofficentForm = ref({
       equipmentNames: "",
     });
     const pageTitle = ref("");
     onMounted(async () => {
-      // 加载样式
-      styleUrl('accountPer');
       let accoutPerSet = localStorage.getItem("accoutPerSet");
       if (accoutPerSet) {
         pageTitle.value = t("accountPer.modifyAccount");
@@ -228,11 +231,9 @@ export default {
       }
       params.roleList = [params.roleList];
       if (pageTitle.value === t("accountPer.modifyAccount")) {
-        // delete params.password;
         const { data } = await updataLoginUser(params);
         if (data.code === "00000") {
           showSuccessToast(t("accountPer.successfullyModifiedTheAccount"));
-          // router.push("/accountPer");
           router.replace("/accountPer");
         } else {
           showFailToast(t("accountPer.failedToModifyTheAccount"), data.message);
@@ -241,7 +242,6 @@ export default {
         const { data } = await addLoginUser(params);
         if (data.code === "00000") {
           showSuccessToast(t("accountPer.accountAddedSuccessfully"));
-          // router.push("/accountPer");
           router.replace("/accountPer");
         } else if (data.code === 'A0201') {
           showToast(t("accountPer.accountNameExists"));
@@ -250,18 +250,25 @@ export default {
         }
       }
     };
-    const deleteLoginUserFun = async () => {
-      const params = {
-        adminId: user.id,
-        id: addParams.id,
-      };
-      const { data } = await deleteLoginUser(params);
-      if (data.code === "00000") {
-        showSuccessToast(t("accountPer.successfullyDeletedTheAccount"));
-        router.push("/accountPer");
-      } else {
-        showFailToast(t("accountPer.failedToDeleteTheAccount"), data.message);
-      }
+    const deleteLoginUserFun = () => {
+      showConfirmDialog({
+        title: t('user.tips'),
+        message: t('accountPer.delTips'),
+      }).then(async () => {
+        const params = {
+          adminId: user.id,
+          id: addParams.id,
+        };
+        const { data } = await deleteLoginUser(params);
+        if (data.code === "00000") {
+          showSuccessToast(t("accountPer.successfullyDeletedTheAccount"));
+          setTimeout(() => {
+            router.go(0);
+          }, 1000);
+        } else {
+          showFailToast(t("accountPer.failedToDeleteTheAccount"), data.message);
+        }
+      });
     };
     // 点击机器列表
     const busiEquipInpClk = () => {
@@ -327,17 +334,17 @@ export default {
     margin-bottom: 16px;
     border-radius: 8px;
     background: #f8f9ff;
-    
+
     :deep(.van-field__label) {
       color: #666;
       font-size: 14px;
     }
-    
+
     :deep(.van-field__control) {
       color: #333;
       font-size: 14px;
     }
-    
+
     :deep(.van-field__left-icon) {
       color: @primary-color;
       margin-right: 8px;
@@ -353,9 +360,10 @@ export default {
   .radio-group {
     display: flex;
     gap: 24px;
-    
+
     .radio-item {
       margin: 0;
+
       :deep(.van-radio__label) {
         color: #333;
       }
@@ -366,11 +374,11 @@ export default {
     :deep(.van-field__body) {
       padding: 8px 0;
     }
-    
+
     .switch-container {
       display: flex;
       align-items: center;
-      
+
       .switch-label {
         margin-left: 12px;
         color: #333;
@@ -384,13 +392,13 @@ export default {
     display: flex;
     flex-direction: column;
     gap: 16px;
-    
+
     .submit-btn {
       background: @primary-color;
       width: 100%;
       height: 44px;
     }
-    
+
     .delete-btn {
       background: @danger-color;
       width: 100%;
@@ -402,7 +410,7 @@ export default {
     display: flex;
     align-items: center;
     gap: 8px;
-    
+
     .van-icon {
       color: #c0c4cc;
       font-size: 18px;

+ 16 - 0
src/views/advertManage/adSet.vue

@@ -241,6 +241,22 @@ export default {
         name: "SBC320en",
         id: "SBC320en",
       },
+      {
+        name: "SBM10ch",
+        id: "SBM10ch",
+      },
+      {
+        name: "SBM10en",
+        id: "SBM10en",
+      },
+      {
+        name: "EF210ch",
+        id: "EF210ch",
+      },
+      {
+        name: "EF210en",
+        id: "EF210en",
+      },
     ]);
     const busiPopFieldName = reactive({
       text: "name",

+ 65 - 45
src/views/apkManage/add.vue

@@ -4,39 +4,39 @@
     <van-form show-error-message @submit="onSubmit">
       <div class="cust_vantBorder">
         <div class="kBordBott">
-          <van-field type="number" colon :border="false" required v-model="cofficentForm.version" clearable name="version"
-            :label="$t('apkManage.add.version')" :placeholder="$t('apkManage.add.versionPlace')" :rules="[
-              {
-                required: true,
-                message: $t('apkManage.add.versionPlace'),
-              },
-            ]" />
+          <van-field type="number" colon :border="false" required v-model="cofficentForm.version" clearable
+            name="version" :label="$t('apkManage.add.version')" :placeholder="$t('apkManage.add.versionPlace')" :rules="[
+      {
+        required: true,
+        message: $t('apkManage.add.versionPlace'),
+      },
+    ]" />
         </div>
         <div class="kBordBott">
           <van-field colon :border="false" required v-model="cofficentForm.versionName" clearable name="versionName"
             :label="$t('apkManage.add.versionName')" :placeholder="$t('apkManage.add.versionNamePlace')" :rules="[
-              {
-                required: true,
-                message: $t('apkManage.add.versionNamePlace'),
-              },
-            ]" />
+      {
+        required: true,
+        message: $t('apkManage.add.versionNamePlace'),
+      },
+    ]" />
         </div>
         <div class="kBordBott">
           <van-field colon :border="false" required @click-input="busiInpClk" readonly clearable
             v-model="cofficentForm.modelName" name="modelName" :label="$t('apkManage.add.model')"
             :placeholder="$t('apkManage.add.modelPlace')" :rules="[
-              {
-                required: true,
-                message: $t('apkManage.add.modelPlace'),
-                trigger: ['onChange', 'onSubmit'],
-              },
-            ]">
+      {
+        required: true,
+        message: $t('apkManage.add.modelPlace'),
+        trigger: ['onChange', 'onSubmit'],
+      },
+    ]">
             <template #right-icon>
               <div class="l-flex-RC">
                 <van-icon v-if="cofficentForm.modelName" @click="
-                  cofficentForm.modelName = '';
-                cofficentForm.model = '';
-                " class="o-mr-6" name="clear" />
+      cofficentForm.modelName = '';
+    cofficentForm.model = '';
+    " class="o-mr-6" name="clear" />
                 <van-icon @click="busiInpClk" name="arrow-down" />
               </div>
             </template>
@@ -46,12 +46,12 @@
       <div class="kBordBott">
         <van-field colon :border="false" required clearable name="isForce" :label="$t('apkManage.add.forceUpdate')"
           :placeholder="$t('apkManage.add.forceUpdatePlace')" :rules="[
-            {
-              required: true,
-              message: $t('apkManage.add.forceUpdatePlace'),
-              trigger: ['onChange', 'onSubmit'],
-            },
-          ]">
+      {
+        required: true,
+        message: $t('apkManage.add.forceUpdatePlace'),
+        trigger: ['onChange', 'onSubmit'],
+      },
+    ]">
           <template #input>
             <van-radio-group v-model="cofficentForm.isForce" direction="horizontal">
               <van-radio name="true">{{ $t('apkManage.add.yes') }}</van-radio>
@@ -62,32 +62,32 @@
       </div>
       <div class="cust_vantBorder">
         <div class="kBordBott">
-          <van-field type="number" colon :border="false" required v-model="cofficentForm.apkSize" clearable name="apkSize"
-            :label="$t('apkManage.add.apkSize')" :placeholder="$t('apkManage.add.apkSizePlace')" :rules="[
-              {
-                required: true,
-                message: $t('apkManage.add.apkSizePlace'),
-              },
-            ]" />
+          <van-field type="number" colon :border="false" required v-model="cofficentForm.apkSize" clearable
+            name="apkSize" :label="$t('apkManage.add.apkSize')" :placeholder="$t('apkManage.add.apkSizePlace')" :rules="[
+      {
+        required: true,
+        message: $t('apkManage.add.apkSizePlace'),
+      },
+    ]" />
         </div>
         <div class="kBordBott">
           <van-field colon :border="false" required v-model="cofficentForm.downloadUrl" clearable name="downloadUrl"
             :label="$t('apkManage.add.downloadLink')" :placeholder="$t('apkManage.add.downloadLinkPlace')" :rules="[
-              {
-                required: true,
-                message: $t('apkManage.add.downloadLinkPlace'),
-              },
-            ]" />
+      {
+        required: true,
+        message: $t('apkManage.add.downloadLinkPlace'),
+      },
+    ]" />
         </div>
         <div class="kBordBott">
           <van-field colon :border="false" required v-model="cofficentForm.versionInfo" clearable name="versionInfo"
             :label="$t('apkManage.add.versionIntroduction')" :placeholder="$t('apkManage.add.versionIntroductionPlace')"
             :rules="[
-              {
-                required: true,
-                message: $t('apkManage.add.versionIntroductionPlace'),
-              },
-            ]" />
+      {
+        required: true,
+        message: $t('apkManage.add.versionIntroductionPlace'),
+      },
+    ]" />
         </div>
       </div>
       <div style="margin: 16px">
@@ -231,7 +231,27 @@ export default {
       {
         name: "SI320en",
         id: "SI320en",
-      }
+      },
+      {
+        name: "SBM10ch",
+        id: "SBM10ch",
+      },
+      {
+        name: "SBM10en",
+        id: "SBM10en",
+      },
+      {
+        name: "EF210ch",
+        id: "EF210ch",
+      },
+      {
+        name: "EF210en",
+        id: "EF210en",
+      },
+      {
+        name: "lua",
+        id: "lua",
+      },
     ]);
     const busiPopFieldName = reactive({
       text: "name",

Dosya farkı çok büyük olduğundan ihmal edildi
+ 1168 - 0
src/views/bindBankCard/index.vue


+ 3 - 3
src/views/device/alarmClean/index.vue

@@ -98,13 +98,13 @@ export default {
                 cleanFunction: newValue ? '1' : '0',
             };
             showConfirmDialog({
-                title: t('alramClean.tips'),
-                message: t('alramClean.content'),
+                title: t('alarmClean.tips'),
+                message: t('alarmClean.content'),
             }).then(async () => {
                 const { data } = await changeCleanFunction(params);
                 if (data.code) {
                     // checked.value = newValue;
-                    showToast(t('alramClean.successfully'));
+                    showToast(t('alarmClean.successfully'));
                     setTimeout(() => {
                         router.go(-1);
                     }, 1500);

+ 209 - 60
src/views/device/alarmClock.vue

@@ -1,52 +1,46 @@
 <template>
-  <!-- 设备定时开关列表 -->
-  <div class="pageClock flex-col">
-    <s-header :name="$t('device.timeSwitch')" :noback="false"></s-header>
-    <div class="bd1 flex-col">
-      <div class="section5 flex-col">
-        <div class="layer1 flex-row">
-          <div class="ImageText1 flex-col">
-            <div class="layer1 flex-row justify-between" @click="addAlarmClock">
-              <div class="bd2"></div>
-              <div class="TextGroup1 flex-col">
-                <span class="word2">{{ $t('device.addAlarmClock') }}</span>
-              </div>
-            </div>
-          </div>
-        </div>
-        <img class="img2" referrerpolicy="no-referrer"
-          src="../../assets/line.png" />
+  <div class="device-schedule">
+    <s-header :name="$t('device.timeSwitch')" :noback="false" />
+
+    <!-- 主内容区 -->
+    <div class="schedule-container">
+      <!-- 添加按钮 -->
+      <div class="add-button" @click="addAlarmClock">
+        <van-icon name="plus" class="add-icon" />
+        <span>{{ $t('device.addAlarmClock') }}</span>
       </div>
-      <div v-for="(item, index) in list" :key="index">
-        <div class="section6 l-flex-between kBordBott">
-          <div class="TextGroup2 flex-col">
-            <div class="bd3 flex-col justify-between">
-              <span class="word3">{{ item.hour.slice(0, 5) }}</span> <span class="info2">{{ showWeek(item.week) }}</span>
-            </div>
-          </div>
-          <div class="TextGroup3 flex-col">
-            <div class="main2 flex-col justify-between">
-              <span class="word4">{{ item.name }}</span>
-              <span class="txt3">{{ showTypeText(item.type) }}</span>
+
+      <!-- 分隔线 -->
+      <van-divider class="custom-divider" />
+
+      <!-- 定时项列表 -->
+      <div class="schedule-list">
+        <div v-for="(item, index) in list" :key="index" class="schedule-item">
+          <!-- 左侧时间信息 -->
+          <div class="time-info">
+            <div class="time-display">
+              <van-icon name="clock" class="time-icon" />
+              <span class="time">{{ item.hour.slice(0, 5) }}</span>
             </div>
+            <span class="weekdays">{{ showWeek(item.week) }}</span>
           </div>
-          <div class="ImageText2 flex-col">
-            <div class="group3 flex-row justify-between" @click="deleteAlarm(item.id)">
-              <div class="group4 flex-col"></div>
-              <div class="TextGroup4 flex-col">
-                <span class="info3">{{ $t('device.delete') }}</span>
-              </div>
-            </div>
+
+          <!-- 中部描述信息 -->
+          <div class="schedule-detail">
+            <span class="schedule-name">{{ item.name }}</span>
+            <van-tag class="type-tag" color="#2c87c8">
+              {{ showTypeText(item.type) }}
+            </van-tag>
           </div>
-          <div class="bd4 flex-col justify-between">
-            <div class="outer1 flex-row justify-between" @click="setAlarm(item)">
-              <div class="main3 flex-col"></div>
-              <span class="word5">{{ $t('device.modify') }}</span>
+
+          <!-- 右侧操作区 -->
+          <div class="action-group">
+            <van-switch :model-value="item.status" :active-value="'1'" :inactive-value="'0'" size="20px"
+              @change="updateStatus(item, value)" />
+            <div class="action-buttons">
+              <van-button icon="edit" size="small" class="edit-btn" @click="setAlarm(item)" />
+              <van-button icon="delete" size="small" class="delete-btn" @click="deleteAlarm(item.id)" />
             </div>
-            <span :class="{
-              'word6': item.status === '1',
-              'word6 close': item.status !== '1'
-            }">{{ item.status === '1' ? $t('device.opened') : $t('device.closed') }}</span>
           </div>
         </div>
       </div>
@@ -56,9 +50,9 @@
 <script>
 import { onMounted, ref } from 'vue';
 import sHeader from "@/components/SimpleHeader";
-import { getAlaramClockList, deleteAlaramClock } from '@/service/device'
-import { showFailToast, showSuccessToast } from 'vant';
-import { getLoginUser, styleUrl } from '@/common/js/utils';
+import { getAlaramClockList, getAlaramClockByDevice, deleteAlaramClock, updateAlaramClockStatus } from '@/service/device'
+import { showConfirmDialog, showFailToast, showSuccessToast } from 'vant';
+import { getLoginUser } from '@/common/js/utils';
 import { useRoute, useRouter } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 
@@ -68,19 +62,26 @@ export default {
     const user = getLoginUser();
     const router = useRouter();
     const route = useRoute();
+    const deviceId = ref(null);
     const list = ref([]);
     // 初始化页面获取列表
     onMounted(async () => {
-      // 加载样式
-      styleUrl('alarmClock');
+      deviceId.value = route.query.deviceId;
       getAlaramClockListFun();
     });
 
     // 获取设备列表数据
     const getAlaramClockListFun = async () => {
-      const { data } = await getAlaramClockList({ adminId: user.id });
-      if (data.code) {
-        list.value = data.data;
+      if (deviceId.value) {
+        const { data } = await getAlaramClockByDevice({ equipmentId: deviceId.value, adminId: user.id });
+        if (data.code) {
+          list.value = data.data;
+        }
+      } else {
+        const { data } = await getAlaramClockList({ adminId: user.id });
+        if (data.code) {
+          list.value = data.data;
+        }
       }
     }
 
@@ -97,7 +98,6 @@ export default {
     }
 
     const showWeek = (e) => {
-      // if (e === '1,2,3,4,5,6,7,') { return t('device.everyDay') }
       if (e.indexOf('1') > -1 && e.indexOf('2') > -1 && e.indexOf('3') > -1 && e.indexOf('4') > -1 && e.indexOf('5') > -1 && e.indexOf('6') > -1 && e.indexOf('7') > -1) {
         return t('device.everyDay')
       }
@@ -121,23 +121,172 @@ export default {
     }
 
     const deleteAlarm = async (id) => {
-      const { data } = await deleteAlaramClock({ id: id });
-      if (data.code) {
-        showSuccessToast(t('device.deletionSucceeded'));
-        getAlaramClockListFun();
-      } else { showFailToast(data.message); }
+      showConfirmDialog({
+        title: t('device.operationConfirmation'),
+        message: t('device.pleaseConfirmAgainWhetherToOperate'),
+      }).then(async () => {
+        const { data } = await deleteAlaramClock({ id: id });
+        if (data.code) {
+          showSuccessToast(t('device.deletionSucceeded'));
+          setTimeout(() => {
+            getAlaramClockListFun();
+          }, 1000);
+        } else { showFailToast(data.message); }
+      })
     }
 
     const setAlarm = async (item) => {
       router.push({ path: 'alarmClockSet', query: { alarmId: item.id } });
     }
 
+    // 修改状态
+    const updateStatus = async (item) => {
+      showConfirmDialog({
+        title: t('device.operationConfirmation'),
+        message: t('device.pleaseConfirmAgainWhetherToOperate'),
+      }).then(async () => {
+        if (item.status == '1') { item.status = '0'; } else { item.status = '1'; }
+        const { data } = await updateAlaramClockStatus({ id: item.id, status: item.status });
+        console.log("data", data);
+        if (data.code) {
+          showSuccessToast(t("device.modificationSucceeded"));
+          setTimeout(() => {
+            getAlaramClockListFun();
+          }, 1000);
+        } else {
+          showFailToast(data.message);
+        }
+      })
+    }
 
-    return { list, addAlarmClock, showTypeText, showWeek, deleteAlarm, setAlarm };
+    return { list, addAlarmClock, showTypeText, showWeek, deleteAlarm, setAlarm, updateStatus };
   },
   components: { sHeader },
 };
 </script>
 <style lang="less" scoped>
-@import "../../common/style/common";
-</style>
+.device-schedule {
+  --schedule-bg: #ffffff;
+  --border-color: #ebedf0;
+  --active-color: #2c87c8;
+  --text-primary: #323233;
+  --text-secondary: #969799;
+
+  background: #f7f8fa;
+  min-height: 100vh;
+
+  .schedule-container {
+    padding: 16px;
+  }
+
+  .add-button {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 44px;
+    background: var(--schedule-bg);
+    border-radius: 8px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+    color: var(--active-color);
+    font-size: 15px;
+
+    .add-icon {
+      margin-right: 8px;
+      font-size: 18px;
+    }
+  }
+
+  .custom-divider {
+    margin: 10px 0;
+    border-color: var(--border-color);
+  }
+
+  .schedule-list {
+    background: var(--schedule-bg);
+    border-radius: 8px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+
+    .schedule-item {
+      display: flex;
+      align-items: center;
+      padding: 16px;
+      border-bottom: 1px solid var(--border-color);
+
+      &:last-child {
+        border-bottom: none;
+      }
+
+      .time-info {
+        flex: 0 0 25%;
+
+        .time-display {
+          display: flex;
+          align-items: center;
+          margin-bottom: 8px;
+
+          .time-icon {
+            color: var(--text-secondary);
+            font-size: 16px;
+            margin-right: 6px;
+          }
+
+          .time {
+            font-size: 18px;
+            font-weight: 500;
+            color: var(--text-primary);
+          }
+        }
+
+        .weekdays {
+          font-size: 12px;
+          color: var(--text-secondary);
+        }
+      }
+
+      .schedule-detail {
+        flex: 1;
+        margin: 0 12px;
+
+        .schedule-name {
+          display: block;
+          font-size: 14px;
+          color: var(--text-primary);
+          margin-bottom: 10px;
+        }
+
+        .type-tag {
+          font-size: 12px;
+        }
+      }
+
+      .action-group {
+        flex: 0 0 80px;
+        text-align: right;
+
+        .action-buttons {
+          margin-top: 12px;
+
+          .van-button {
+            margin-left: 8px;
+            width: 28px;
+            height: 28px;
+
+            &::before {
+              border-radius: 4px;
+            }
+          }
+
+          .edit-btn {
+            color: var(--active-color);
+            border-color: var(--active-color);
+          }
+
+          .delete-btn {
+            color: #ee0a24;
+            border-color: #ee0a24;
+          }
+        }
+      }
+    }
+  }
+}</style>

+ 203 - 45
src/views/device/alarmClockSet/index.vue

@@ -1,54 +1,90 @@
 <template>
   <!-- 设置闹钟 -->
-  <div class="alarmClockSetPage flex-col">
-    <s-header :name="$t('device.setAlarm')" :noback="false"></s-header>
-    <div class="alarmClockSetBox flex-col">
-      <div style="width: 100%; height: 18px"></div>
-      <van-field class="equipmentField" is-link readonly :label="$t('device.equipmentName')"
-        :placeholder="$t('device.selectDevice')" v-model="equipmentIdsText" @click="equipmentShow = true" />
-      <van-field v-model="hour" is-link readonly :label="$t('device.selectTime')" :placeholder="$t('device.selectTime')"
-        @click="currentTimeShow = true" class="field" />
-      <div class="repeatTimeBox">
-        <span class="txt6">{{
-          $t("device.selectTheNumberOfAlarmClockRepetitions")
-        }}</span>
-        <div class="o-pl-15 o-ptb-10">
-          <van-checkbox @click="checkedAllClk" v-model="checkedAll">{{ $t("alarmClockSet.checkedAll") }}</van-checkbox>
+  <div class="alarm-config-container">
+    <s-header :name="$t('device.setAlarm')" :noback="false" />
+
+    <!-- 主表单区域 -->
+    <div class="config-card">
+      <!-- 设备选择 -->
+      <van-field v-model="equipmentIdsText" is-link readonly center :label="$t('device.equipmentName')"
+        :placeholder="$t('device.selectDevice')" class="form-field" @click="equipmentShow = true">
+        <template #left-icon>
+          <van-icon name="cluster-o" class="field-icon" />
+        </template>
+      </van-field>
+
+      <!-- 时间选择 -->
+      <van-field v-model="hour" is-link readonly center :label="$t('device.selectTime')"
+        :placeholder="$t('device.selectTime')" class="form-field" @click="currentTimeShow = true">
+        <template #left-icon>
+          <van-icon name="clock-o" class="field-icon" />
+        </template>
+      </van-field>
+      <!-- 闹钟类型 -->
+      <van-field v-model="alarmClockTypeText" is-link readonly center :label="$t('device.alarmTypeLabel')"
+        :placeholder="$t('device.alarmTypePlaceholder')" class="form-field" @click="alarmClockTypeShow = true">
+        <template #left-icon>
+          <van-icon name="flag-o" class="field-icon" />
+        </template>
+      </van-field>
+
+      <!-- 重复周期 -->
+      <div class="repeat-section">
+        <h3 class="section-title">
+          <van-icon name="replay" class="title-icon" />
+          {{ $t("device.selectTheNumberOfAlarmClockRepetitions") }}
+        </h3>
+        <div class="quick-select">
+          <van-checkbox v-model="checkedAll" shape="square" @click="checkedAllClk">
+            {{ $t("alarmClockSet.checkedAll") }}
+          </van-checkbox>
         </div>
-        <div class="l-flex-between dayCon">
-          <div @click="selectDayClk(item.value)" class="dayName" :class="{ active: selectList.includes(item.value) }"
-            v-for="(item, index) in weekDayList" :key="index">
+        <div class="day-grid">
+          <div v-for="(item, index) in weekDayList" :key="index" class="day-item"
+            :class="{ active: selectList.includes(item.value) }" @click="selectDayClk(item.value)">
             {{ item.name }}
           </div>
         </div>
       </div>
-      <van-field v-model="alarmClockTypeText" is-link readonly :label="$t('device.alarmTypeLabel')"
-        :placeholder="$t('device.alarmTypePlaceholder')" @click="alarmClockTypeShow = true" class="field" />
-      <van-field v-model="alarmClockName" name="alarmClockName" :label="$t('device.alarmNameLabel')"
-        :placeholder="$t('device.alarmNamePlaceholder')" />
-      <div class="ImageText1">
-        <div class="mod4 justify-between">
-          <div class="TextGroup1">
-            <span class="info4">{{ $t("device.effectiveImmediately") }}</span>
-          </div>
-          <div class="">
-            <van-switch v-model="checked" size="20px" />
-          </div>
-        </div>
+
+
+      <!-- 闹钟名称 -->
+      <van-field v-model="alarmClockName" center :label="$t('device.alarmNameLabel')"
+        :placeholder="$t('device.alarmNamePlaceholder')" class="form-field">
+        <template #left-icon>
+          <van-icon name="edit" class="field-icon" />
+        </template>
+      </van-field>
+
+      <!-- 立即生效 -->
+      <div class="switch-section">
+        <span class="switch-label">
+          <van-icon name="certificate" class="switch-icon" />
+          {{ $t("device.effectiveImmediately") }}
+        </span>
+        <van-switch v-model="checked" size="18px" />
       </div>
-      <van-row justify="space-around" style="padding: 5em">
-        <van-button span="5" round type="primary" style="height: 2em; padding: 0 2em" @click="submitSet">
-          {{ $t("device.submitSettings") }}</van-button>
-      </van-row>
     </div>
-    <van-popup v-model:show="alarmClockTypeShow" round position="bottom">
+
+    <!-- 提交按钮 -->
+    <div class="action-bar">
+      <van-button round type="primary" class="submit-btn" @click="submitSet">
+        <van-icon name="passed" class="btn-icon" />
+        {{ $t("device.submitSettings") }}
+      </van-button>
+    </div>
+
+    <!-- 弹出层(保持原有逻辑,优化样式) -->
+    <van-popup v-model:show="alarmClockTypeShow" round position="bottom" class="custom-popup">
       <van-cascader v-model="alarmClockType" :title="$t('device.alarmTypePlaceholder')" :options="alarmClockTypeOptions"
-        @close="alarmClockTypeShow = false" @finish="alarmClockTypeFinish" />
+        active-color="#2c87c8" @close="alarmClockTypeShow = false" @finish="alarmClockTypeFinish" />
     </van-popup>
-    <van-popup v-model:show="currentTimeShow" round position="bottom">
+
+    <van-popup v-model:show="currentTimeShow" round position="bottom" class="custom-popup">
       <van-time-picker v-model="currentTime" :title="$t('device.clickToSelectTheTime')" @confirm="onConfirm"
         @cancel="currentTimeShow = false" />
     </van-popup>
+
     <van-popup v-model:show="equipmentShow" position="bottom">
       <div class="van-picker__toolbar">
         <button type="button" class="van-picker__cancel" style="margin: 0 0.5em" @click="equipmentShow = false">
@@ -67,7 +103,7 @@
             <van-cell v-for="(item, index) in equipmentList" clickable :key="index" :title="item.label"
               @click="equipementCheckItem(item.value)">
               <template #right-icon>
-                <van-checkbox :name="item.value" @click.stop/>
+                <van-checkbox :name="item.value" @click.stop />
               </template>
             </van-cell>
           </van-cell-group>
@@ -80,7 +116,7 @@
 import { showSuccessToast, showFailToast, showToast } from "vant";
 import { onMounted, ref, watch } from "vue";
 import sHeader from "@/components/SimpleHeader";
-import { getLoginUser, styleUrl } from "@/common/js/utils";
+import { getLoginUser } from "@/common/js/utils";
 import {
   getListEquipment,
   addAlaramClock,
@@ -170,8 +206,6 @@ export default {
     const equipmentList = ref([]);
     // 初始化页面获取列表
     onMounted(async () => {
-      // 加载样式
-      styleUrl('alarmClock');
       if (route.query.deviceId) {
         equipmentIds.value.push(route.query.deviceId);
       }
@@ -325,10 +359,13 @@ export default {
       const { data } = route.query.deviceId
         ? await addAlaramClock(params)
         : await alaramClockUpdate(params);
-      console.log("data", data);
       if (data.code) {
-        showSuccessToast(t("device.successfullyAddedAlarmClock"));
-        router.back();
+        route.query.deviceId
+          ? showSuccessToast(t("device.successfullyAddedAlarmClock"))
+          : showSuccessToast(t("device.modificationSucceeded"));
+        setTimeout(() => {
+          router.back();
+        }, 1000);
       } else {
         showFailToast(data.message);
       }
@@ -362,5 +399,126 @@ export default {
 };
 </script>
 <style lang="less" scoped>
-@import "../../../common/style/common";
+.alarm-config-container {
+  --card-bg: #ffffff;
+  --border-color: #ebedf0;
+  --primary-color: #2c87c8;
+  --text-primary: #323233;
+  --text-secondary: #969799;
+
+  background: #f7f8fa;
+  min-height: 100vh;
+
+  .config-card {
+    margin: 16px;
+    padding: 16px;
+    background: var(--card-bg);
+    border-radius: 12px;
+    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
+
+    .form-field {
+      margin: 8px 0;
+      padding: 12px 16px;
+      background: #f8f9fa;
+      border-radius: 8px;
+
+      :deep(.van-field__label) {
+        width: 6em;
+        color: var(--text-primary);
+      }
+
+      .field-icon {
+        font-size: 18px;
+        margin-right: 12px;
+        color: var(--primary-color);
+      }
+    }
+  }
+
+  .repeat-section {
+    margin: 20px 0;
+
+    .section-title {
+      display: flex;
+      align-items: center;
+      font-size: 15px;
+      color: var(--text-primary);
+      margin: 0 0 16px 0;
+
+      .title-icon {
+        margin-right: 8px;
+        color: var(--primary-color);
+      }
+    }
+
+    .quick-select {
+      margin-bottom: 12px;
+
+      :deep(.van-checkbox) {
+        --van-checkbox-size: 18px;
+      }
+    }
+
+    .day-grid {
+      display: grid;
+      grid-template-columns: repeat(4, 1fr);
+      gap: 10px;
+
+      .day-item {
+        padding: 10px;
+        text-align: center;
+        border-radius: 6px;
+        background: #f8f9fa;
+        color: var(--text-secondary);
+        transition: all 0.2s;
+
+        &.active {
+          background: var(--primary-color);
+          color: white;
+          font-weight: 500;
+        }
+      }
+    }
+  }
+
+  .switch-section {
+    display: flex;
+    align-items: center;
+    gap: 30px; // 控制文字和按钮间距
+    padding: 13px 15px;
+    background: #f8f9fa;
+    border-radius: 8px;
+    margin-bottom: 10px;
+
+
+    .switch-label {
+      display: flex;
+      align-items: center;
+      color: var(--text-primary);
+
+      .switch-icon {
+        font-size: 20px;
+        margin-right: 15px;
+        color: var(--primary-color);
+      }
+    }
+  }
+
+  .action-bar {
+    padding: 0 16px 32px;
+
+    .submit-btn {
+      width: 100%;
+      height: 44px;
+      font-size: 16px;
+      letter-spacing: 1px;
+
+      .btn-icon {
+        font-size: 16px;
+        margin-right: 2px;
+        vertical-align: -2px;
+      }
+    }
+  }
+}
 </style>

+ 428 - 182
src/views/device/deviceOper.vue

@@ -1,267 +1,320 @@
 <template>
-  <!-- 设备常见操作弹窗 -->
-  <van-dialog class-name="operDialog" width="350px" v-model:show="show" :showConfirmButton="false"
-    :showCancelButton="false" :closeOnClickOverlay="true">
-    <slot name="title">
-      <div class="van-dialog__header" style="padding-bottom: 1em;">{{ $t("device.commonOperations") }}</div>
-      <div class="txt1" style="padding: 0.2em 1em">
-        {{ $t("device.equipmentName") }}: {{ device.name != null ? device.name : $t("device.equipmentNameTips") }}
+  <!-- 操作弹窗 -->
+  <van-dialog class="operation-dialog" :width="isMobile ? '90%' : '560px'" v-model:show="show"
+    :show-confirm-button="false" :show-cancel-button="false" :close-on-click-overlay="true">
+    <!-- 头部 -->
+    <div class="dialog-header">
+      <h3 class="dialog-title">{{ $t("device.commonOperations") }}</h3>
+      <van-icon name="cross" class="close-icon" @click="show = false" />
+    </div>
+
+    <!-- 设备信息 -->
+    <div class="device-info">
+      <div class="info-item">
+        <span class="info-label">{{ $t("device.equipmentName") }}:</span>
+        <span class="info-value">{{ device.name || $t("device.equipmentNameTips") }}</span>
       </div>
-      <div class="txt1" style="padding: 0.2em 1em">
-        {{ $t("device.equipmentNo") }}: {{ device.clientId.slice(-6) }}
+      <div class="info-item">
+        <span class="info-label">{{ $t("device.equipmentNo") }}:</span>
+        <span class="info-value">{{ device.clientId.slice(-6) }}</span>
       </div>
-    </slot>
-    <van-icon name="cross" class="close" @click="show = false" />
-    <div class="group4 flex-col"></div>
-    <div class="operBox">
+    </div>
+
+    <!-- 操作列表 -->
+    <div class="operation-grid">
       <!-- 重启炉头 -->
-      <div v-if="controlList.includes('C1')" class="operItem" @click="restartFurnace()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/restart.png" />
+      <div v-if="controlList.includes('C1')" class="operation-item" @click="restartFurnace()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/restart.png" alt="restart" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">
+            {{ device.machineType === '0' || !device.machineType ?
+    $t("device.restartFurnaceHead") : $t("device.restart") }}
+          </span>
         </div>
-        <div v-if="device.machineType === '0' || device.machineType === null" class="operText">{{
-    $t("device.restartFurnaceHead") }}</div>
-        <div v-else class="operText">{{ $t("device.restart") }}</div>
       </div>
-      <!-- 睡眠 -->
-      <div v-if="controlList.includes('C2')" class="operItem" @click="sleepEquipmentFun()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/sleep.png" />
+
+      <!-- 睡眠控制 -->
+      <div v-if="controlList.includes('C2')" class="operation-item" @click="sleepEquipmentFun()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/sleep.png" alt="sleep" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ sleepTitle }}</span>
         </div>
-        <div class="operText">{{ sleepTitle }}</div>
       </div>
+
       <!-- 开启炉头/设备 -->
-      <div v-if="controlList.includes('C3') && device.machineType != '2'" class="operItem" @click="openOffFurnace(1)">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/onOff.png" />
+      <div v-if="controlList.includes('C3') && device.machineType != '2'" class="operation-item"
+        @click="openOffFurnace(1)">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/onOff.png" alt="onOff" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">
+            {{ device.machineType === '0' || !device.machineType ?
+    $t("device.openFurnHead") : $t("device.openDevice") }}
+          </span>
         </div>
-        <div v-if="device.machineType === '0' || device.machineType === null" class="operText">{{
-    $t("device.openFurnHead") }}</div>
-        <div v-else class="operText">{{ $t("device.openDevice") }}</div>
       </div>
+
       <!-- 关闭炉头/设备 -->
-      <div v-if="controlList.includes('C4')" class="operItem" @click="openOffFurnace(0)">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/onOff.png" />
+      <div v-if="controlList.includes('C4')" class="operation-item" @click="openOffFurnace(0)">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/onOff.png" alt="onOff" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">
+            {{ device.machineType === '0' || !device.machineType ?
+    $t("device.closeFurnHead") : $t("device.closeDevice") }}
+          </span>
         </div>
-        <div v-if="device.machineType === '0' || device.machineType === null" class="operText">{{
-    $t("device.closeFurnHead") }}</div>
-        <div v-else class="operText">{{ $t("device.closeDevice") }}</div>
       </div>
+
       <!-- 雪糕机制冷模式 -->
-      <div v-if="device.machineType == '2' && controlList.includes('C24')" class="operItem"
+      <div v-if="device.machineType == '2' && controlList.includes('C24')" class="operation-item"
         @click="updateWorkingMode(0)">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/refrigeration.png" />
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/refrigeration.png" alt="refrigeration" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.refrigeration") }}</span>
         </div>
-        <div class="operText">{{ $t("device.refrigeration") }}</div>
       </div>
+
       <!-- 雪糕机搅拌模式 -->
-      <div v-if="device.machineType == '2' && controlList.includes('C25')" class="operItem"
+      <div v-if="device.machineType == '2' && controlList.includes('C25')" class="operation-item"
         @click="updateWorkingMode(1)">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/stir.png" />
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/stir.png" alt="stir" />
+        </div>
+        <div class="text-wrapper">
+          <div class="operation-text">{{ $t("device.stir") }}</div>
         </div>
-        <div class="operText">{{ $t("device.stir") }}</div>
       </div>
+
       <!-- 雪糕机保鲜模式 -->
-      <div v-if="device.machineType == '2' && controlList.includes('C26')" class="operItem"
+      <div v-if="device.machineType == '2' && controlList.includes('C26')" class="operation-item"
         @click="updateWorkingMode(2)">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/keepFresh.png" />
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/keepFresh.png" alt="keepFresh" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.keepFresh") }}</span>
         </div>
-        <div class="operText">{{ $t("device.keepFresh") }}</div>
       </div>
+
       <!-- 雪糕机解冻模式 -->
-      <div v-if="device.machineType == '2' && controlList.includes('C27')" class="operItem"
+      <div v-if="device.machineType == '2' && controlList.includes('C27')" class="operation-item"
         @click="updateWorkingMode(3)">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/thaw.png" />
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/thaw.png" alt="thaw" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.thaw") }}</span>
         </div>
-        <div class="operText">{{ $t("device.thaw") }}</div>
       </div>
-      <!--     <div class="operItem" @click="openDoorFun()">
-              <div class="operIcon">
-                <img
-                  class="operImg"
-                  src="../../assets/device/operIcon/openDoor.png"
-                />
-              </div>
-              <div class="operText">{{ $t("device.remoteDoorOpening") }}</div>
-            </div> -->
+
       <!-- 远程开门 -->
-      <div v-if="controlList.includes('C5')" class="operItem" @click="openDoorFun()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/openDoor.png" />
+      <div v-if="controlList.includes('C5')" class="operation-item" @click="openDoorFun()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/openDoor.png" alt="openDoor" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.remoteDoorOpening") }}</span>
         </div>
-        <div class="operText">{{ $t("device.remoteDoorOpening") }}</div>
       </div>
+
       <!-- 远程做糖 -->
-      <div v-if="controlList.includes('C6')" class="operItem" @click="doSugar()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/doSugar.png" />
+      <div v-if="controlList.includes('C6')" class="operation-item" @click="doSugar()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/doSugar.png" alt="doSugar" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.remoteProduction") }}</span>
         </div>
-        <div v-if="device.machineType === '0' || device.machineType === null" class="operText">{{
-    $t("device.remoteSugarMaking") }}</div>
-        <div v-else class="operText">{{ $t("device.remoteProduction") }}</div>
       </div>
+
       <!-- 定时开关 -->
-      <div v-if="controlList.includes('C7') && device.equimentType != 'SI320'" class="operItem" @click="alarmClock()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/alarmClock.png" />
+      <div v-if="controlList.includes('C7') && device.equimentType != 'SI320'" class="operation-item"
+        @click="alarmClock()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/alarmClock.png" alt="alarmClock" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.timeSwitch") }}</span>
         </div>
-        <div class="operText">{{ $t("device.timeSwitch") }}</div>
       </div>
+
       <!-- 音量调节 -->
-      <div v-if="controlList.includes('C8')" class="operItem" @click="modulation()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/modulation.png" />
+      <div v-if="controlList.includes('C8')" class="operation-item" @click="modulation()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/modulation.png" alt="modulation" />
         </div>
-        <div class="operText">{{ $t("device.modulation") }}</div>
-      </div>
-      <!-- <div v-if="user.ifForeign == '0'" class="operItem" @click="recharge()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/recharge.png" />
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.modulation") }}</span>
         </div>
-        <div class="operText">{{ $t("device.equipmentRecharge") }}</div>
-      </div> -->
+      </div>
+
+      <!-- 参数调整 -->
       <div v-if="device.equimentType != 'SI320' && device.machineType != '2' && controlList.includes('C9')"
-        class="operItem" @click="paramSetPush()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/paramsSet.png" />
+        class="operation-item" @click="paramSetPush()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/paramsSet.png" alt="paramsSet" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.parameterSetting") }}</span>
+        </div>
+      </div>
+      <!-- 设置分销 -->
+      <div v-if="user.ifForeign == '0' && controlList.includes('C10')" class="operation-item"
+        @click="saveProportionPush()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/saveProportion.png" alt="saveProportion" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.addDistributor") }}</span>
         </div>
-        <div class="operText">{{ $t("device.parameterSetting") }}</div>
       </div>
-      <div v-if="user.ifForeign == '0' && controlList.includes('C10')" class="operItem" @click="saveProportionPush()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/saveProportion.png" />
+      <!-- 系统脱机 -->
+      <div v-if="controlList.includes('C19')" class="operation-item" @click="tuojiEquipmentFun()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/tuoji.png" alt="tuoji" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.sysOffline") }}</span>
         </div>
-        <div class="operText">{{ $t("device.addDistributor") }}</div>
       </div>
-      <div v-if="controlList.includes('C19')" class="operItem" @click="tuojiEquipmentFun()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/tuoji.png" />
+      <!-- 修改价格 -->
+      <div v-if="controlList.includes('C11')" class="operation-item" @click="modifyPriceClk()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/editPrice.png" alt="editPrice" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.modifyPrice") }}</span>
         </div>
-        <div class="operText">{{ $t("device.sysOffline") }}</div>
       </div>
-      <div v-if="controlList.includes('C11')" class="operItem" @click="modifyPriceClk()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/editPrice.png" />
+      <!-- 支付方式 -->
+      <div v-if="controlList.includes('C28') && device.machineType == '0' && user.ifForeign == '1'"
+        class="operation-item" @click="paymentClk()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/payment.png" alt="payment" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("remote.C28") }}</span>
         </div>
-        <div class="operText">{{ $t("device.modifyPrice") }}</div>
       </div>
       <!-- 物料监控 -->
-      <div v-if="device.equimentType != 'SI320' && controlList.includes('C12')" class="operItem"
+      <div v-if="device.equimentType != 'SI320' && controlList.includes('C12')" class="operation-item"
         @click="materialMonitorClk()">
-        <div class="operIcon">
-          <img v-if="materialIcon === '0'" class="operImg" src="../../assets/device/operIcon/materialMonitor.png" />
-          <img v-else class="operImg" src="../../assets/device/operIcon/materialMonitorOff.png" />
-          <!-- <img class="operImg" src="../../assets/device/operIcon/materialMonitor.png" /> -->
+        <div class="icon-wrapper">
+          <img class="operation-icon" v-if="materialIcon === '0'" src="../../assets/device/operIcon/materialMonitor.png"
+            alt="materialMonitor" />
+          <img class="operation-icon" v-else src="../../assets/device/operIcon/materialMonitorOff.png"
+            alt="materialMonitorOff" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ materialTitle }}</span>
         </div>
-        <!-- <div class="operText">{{ $t("device.materialMonitor") }}</div> -->
-        <div class="operText">{{ materialTitle }}</div>
       </div>
       <!-- 屏蔽/展示商品 -->
-      <div v-if="device.equimentType != 'SI320' && controlList.includes('C13')" class="operItem"
+      <div v-if="device.equimentType != 'SI320' && controlList.includes('C13')" class="operation-item"
         @click="showGoodsClk()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/showGoods.png" />
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/showGoods.png" alt="showGoods" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.showGoods") }}</span>
         </div>
-        <div class="operText">{{ $t("device.showGoods") }}</div>
       </div>
       <!-- DIY花型 -->
       <div v-if="(device.equimentType == 'MG320' || device.equimentType == 'MG330') && controlList.includes('C15')"
-        class="operItem" @click="diyFlowerClk()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/diyFlower.png" />
+        class="operation-item" @click="diyFlowerClk()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/diyFlower.png" alt="diyFlower" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.diyFlower") }}</span>
         </div>
-        <div class="operText">{{ $t("device.diyFlower") }}</div>
       </div>
       <!-- 修改机器密码 -->
-      <div v-if="controlList.includes('C14')" class="operItem" @click="changePasswordClk()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/password.png" />
+      <div v-if="controlList.includes('C14')" class="operation-item" @click="changePasswordClk()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/password.png" alt="password" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.changePassword") }}</span>
         </div>
-        <div class="operText">{{ $t("device.changePassword") }}</div>
       </div>
       <!-- 删除设备 -->
-      <div v-if="controlList.includes('C21')" class="operItem" @click="deleteDevice()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/deletedevice.png" />
+      <div v-if="controlList.includes('C21')" class="operation-item" @click="deleteDevice()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/deletedevice.png" alt="deletedevice" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.deleteDevice") }}</span>
         </div>
-        <div class="operText">{{ $t("device.deleteDevice") }}</div>
       </div>
       <!-- 日志功能 -->
-      <div v-if="controlList.includes('C20')" class="operItem" @click="viewLogs()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/viewLogs.png" />
+      <div v-if="controlList.includes('C20')" class="operation-item" @click="viewLogs()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/viewLogs.png" alt="viewLogs">
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.viewLogs") }}</span>
         </div>
-        <div class="operText">{{ $t("device.viewLogs") }}</div>
       </div>
       <!-- 定制logo -->
-      <div v-if="controlList.includes('C22')" class="operItem" @click="customLogo()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/customLogo.png" />
+      <div v-if="controlList.includes('C22')" class="operation-item" @click="customLogo()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/customLogo.png" alt="customLogo">
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.customLogo.customLogo") }}</span>
         </div>
-        <div class="operText">{{ $t("device.customLogo.customLogo") }}</div>
       </div>
       <!-- 远程重启触摸屏 -->
-      <div v-if="controlList.includes('C16')" class="operItem" @click="restartAndroid()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/restartAndroid.png" />
+      <div v-if="controlList.includes('C16')" class="operation-item" @click="restartAndroid()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/restartAndroid.png" alt="restartAndroid" />
         </div>
-        <div class="operText">{{ $t("device.restartAndroid") }}</div>
-      </div>
-      <!-- 查看定位 -->
-      <!-- <div class="operItem" @click="viewPosiClk()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/location.png" />
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.restartAndroid") }}</span>
         </div>
-        <div class="operText">{{ $t("device.viewPositioning") }}</div>
-      </div> -->
+      </div>
       <!-- 设备清洗提醒 -->
-      <div class="operItem"
+      <div class="operation-item"
         v-if="(device.machineType === '0' || device.machineType === null) && controlList.includes('C17')"
-        @click="alramCleanClk()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/alarmClean.png" />
+        @click="alarmCleanClk()">
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/alarmClean.png" alt="alarmClean" />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.alarmClean") }}</span>
         </div>
-        <div class="operText">{{ $t("device.alramClean") }}</div>
       </div>
       <!-- 远程退币 -->
-      <div class="operItem"
+      <div class="operation-item"
         v-if="(device.machineType === '0' || device.machineType === null) && (user.ifForeign == 1 || user.type == 0) && controlList.includes('C18')"
         @click="returnCoinClk()">
-        <div class="operIcon">
-          <img class="operImg" src="../../assets/device/operIcon/coin.png" />
+        <div class="icon-wrapper">
+          <img class="operation-icon" src="../../assets/device/operIcon/coin.png" alt="coin" />
         </div>
-        <div class="operText">{{ $t("device.returnCoin") }}</div>
-      </div>
-
-    </div>
-  </van-dialog>
-  <van-dialog v-model:show="operCheckShow" :title="$t('device.operationConfirmation')" :showConfirmButton="false"
-    :showCancelButton="false">
-    <div class="operCheckBox">
-      <div class="block5 flex-col"></div>
-      <span class="word10">{{
-    $t("device.pleaseConfirmAgainWhetherToOperate")
-  }}</span>
-      <div class="block6 flex-row justify-between">
-        <div class="mod7 flex-col" @click="operCheckClear()">
-          <span class="info5">{{ $t("device.IllThinkAboutItAgain") }}</span>
-        </div>
-        <div class="mod8 flex-col" @click="operCheck()">
-          <span class="info6">{{ $t("device.confirm") }}</span>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("device.returnCoin") }}</span>
         </div>
       </div>
     </div>
   </van-dialog>
+  <van-dialog close-on-click-overlay v-model:show="operCheckShow" :title="$t('device.operationConfirmation')"
+    :message="$t('device.pleaseConfirmAgainWhetherToOperate')" show-cancel-button @confirm="operCheck()">
+  </van-dialog>
 </template>
 
 
 <script>
-import { onMounted, ref } from "vue";
+import { onMounted, ref, onBeforeUnmount } from "vue";
 import {
   setFurnace,
   sleepEquipment,
@@ -277,11 +330,18 @@ import {
 import { showFailToast, showSuccessToast } from "vant";
 import { useRouter } from "vue-router";
 import { useI18n } from "vue-i18n";
-import { getLoginUser, styleUrl } from "@/common/js/utils";
+import { getLoginUser } from "@/common/js/utils";
 
 export default {
   emits: ['operfinish'],
+  components: {
+  },
   setup(props, { emit }) {
+    const isMobile = ref(false);
+    // 检测屏幕尺寸
+    const checkMobile = () => {
+      isMobile.value = window.innerWidth < 768
+    }
     // 点击修改价格
     const modifyPriceClk = () => {
       router.push({
@@ -289,6 +349,13 @@ export default {
         query: { deviceId: device.value.id, name: device.value.name },
       });
     };
+    // 点击支付方式
+    const paymentClk = () => {
+      router.push({
+        path: "payment",
+        query: { deviceId: device.value.id, name: device.value.name, payment: device.value.paymentType },
+      });
+    };
     // 点击屏蔽/展示商品
     const showGoodsClk = () => {
       router.push({
@@ -340,9 +407,12 @@ export default {
     const controlList = ref([]);
     // 初始化页面获取列表
     onMounted(async () => {
-      // 加载样式
-      styleUrl('deviceOper');
+      checkMobile()
+      window.addEventListener('resize', checkMobile)
     });
+    onBeforeUnmount(() => {
+      window.removeEventListener('resize', checkMobile)
+    })
     // 当前弹窗父组件触发
     const showOper = (e, value) => {
       controlList.value = value;
@@ -500,14 +570,9 @@ export default {
       }
       // 睡眠
       if (operType.value === 2) {
-        let eqeStatus = 1;
-        // isSleep=true,机器属于休眠状态,按钮是关闭休眠
-        if (device.value.isSleep) {
-          eqeStatus = 0;
-        }
         const { data } = await sleepEquipment({
           equipmentId: device.value.id,
-          eqeStatus,
+          eqeStatus: device.value.isSleep ? '0' : '1',
         });
         if (data.code) {
           showSuccessToast(t("device.sleepSuccessfully"));
@@ -655,7 +720,6 @@ export default {
       viewLogs,
       deleteDevice,
       restartAndroid,
-      // viewPosiClk,
       changePasswordClk,
       sleepIcon,
       materialIcon,
@@ -664,11 +728,193 @@ export default {
       alarmCleanClk,
       returnCoinClk,
       controlList,
+      isMobile,
+      paymentClk,
     };
-  },
-  components: {},
+  }
 };
 </script>
 <style lang="less" scoped>
 @import "../../common/style/common";
+.operation-dialog {
+  border-radius: 12px;
+  overflow: hidden;
+
+  .dialog-header {
+    padding: 16px 24px;
+    background: #f8f9fa;
+    position: relative;
+
+    .dialog-title {
+      margin: 0;
+      font-size: 18px;
+      color: #1a1a1a;
+      font-weight: 500;
+    }
+
+    .close-icon {
+      position: absolute;
+      right: 16px;
+      top: 50%;
+      transform: translateY(-50%);
+      font-size: 20px;
+      color: #666;
+      padding: 8px;
+      border-radius: 50%;
+      transition: background 0.2s;
+
+      &:active {
+        background: #e8e8e8;
+      }
+    }
+  }
+
+  .device-info {
+    padding: 12px 24px;
+    border-bottom: 1px solid #eee;
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      margin: 8px 0;
+      font-size: 14px;
+
+      .info-label {
+        color: #666;
+        margin-right: 8px;
+        flex-shrink: 0;
+      }
+
+      .info-value {
+        color: #333;
+        font-weight: 500;
+        .text-ellipsis();
+      }
+    }
+  }
+
+  .operation-grid {
+    display: grid;
+    grid-template-columns: repeat(4, 1fr);
+    gap: 12px;
+    padding: 10px;
+    max-height: 60vh;
+    overflow-y: auto;
+    overflow-x: hidden;
+
+    @media (max-width: 480px) {
+      grid-template-columns: repeat(3, 1fr);
+      /* 移动端2列 */
+    }
+
+    .operation-item {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      padding: 8px;
+      position: relative;
+
+      .icon-wrapper {
+        width: 35px;
+        height: 35px;
+        margin-bottom: 6px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+      }
+
+      .operation-icon {
+        max-width: 100%;
+        max-height: 100%;
+        object-fit: contain;
+      }
+
+      .text-wrapper {
+        width: 100%;
+        min-height: 36px;
+        /* 固定文字容器高度 */
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        text-align: center;
+        position: relative;
+      }
+
+      .operation-text {
+        font-size: 10px;
+        line-height: 1.4;
+        color: #333;
+        display: -webkit-box;
+        -webkit-line-clamp: 2;
+        /* 最多显示两行 */
+        -webkit-box-orient: vertical;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        padding: 0 4px;
+        max-width: 100%;
+
+        /* 备用方案 */
+        @supports not (-webkit-line-clamp: 2) {
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+      }
+
+      /* 悬浮提示 */
+      &:hover .text-tooltip {
+        visibility: visible;
+        opacity: 1;
+      }
+
+      .text-tooltip {
+        position: absolute;
+        bottom: 100%;
+        left: 50%;
+        transform: translateX(-50%);
+        background: rgba(0, 0, 0, 0.8);
+        color: white;
+        padding: 6px 12px;
+        border-radius: 4px;
+        font-size: 12px;
+        white-space: nowrap;
+        visibility: hidden;
+        opacity: 0;
+        transition: opacity 0.2s;
+        z-index: 100;
+
+        &::after {
+          content: '';
+          position: absolute;
+          top: 100%;
+          left: 50%;
+          margin-left: -4px;
+          border-width: 4px;
+          border-style: solid;
+          border-color: rgba(0, 0, 0, 0.8) transparent transparent;
+        }
+      }
+    }
+  }
+}
+
+// 文字截断混入
+.text-ellipsis() {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+/* 移动端适配 */
+@media (max-width: 480px) {
+  .operation-item {
+    .text-wrapper {
+      min-height: 32px;
+    }
+
+    .operation-text {
+      font-size: 10px;
+    }
+  }
+}
 </style>

+ 1 - 1
src/views/device/doSugar.vue

@@ -1,7 +1,7 @@
 <template>
   <!-- 远程做糖 -->
   <div class="sugarPage flex-col">
-    <s-header :name="$t('device.remoteSugarMaking')" :noback="false"></s-header>
+    <s-header :name="$t('device.remoteProduction')" :noback="false"></s-header>
     <div class="box1 flex-col">
       <div class="block2 flex-row justify-between">
         <div class="block3 flex-col"></div>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 785 - 247
src/views/device/index.vue


+ 221 - 0
src/views/device/payment/index.vue

@@ -0,0 +1,221 @@
+<template>
+    <div class="payment-settings">
+        <s-header :name="$t('remote.C28')" :noback="false" />
+
+        <!-- 设备名称标题 -->
+        <div class="device-header">
+            <div class="vertical-indicator"></div>
+            <h3 class="device-name">{{ $t('device.equipmentName') }}:{{ deviceName }}</h3>
+        </div>
+
+        <!-- 支付方式列表 -->
+        <div class="settings-card">
+            <!-- Nayax/Z1 -->
+            <div class="payment-item">
+                <div class="payment-info">
+                    <van-icon name="card" class="payment-icon" />
+                    <div class="payment-detail">
+                        <h3 class="payment-title">Nayax</h3>
+                    </div>
+                </div>
+                <van-switch v-model="activeZ1" size="22px" />
+            </div>
+
+            <!-- WMDB/Z2 -->
+            <div class="payment-item">
+                <div class="payment-info">
+                    <van-icon name="card" class="payment-icon" />
+                    <div class="payment-detail">
+                        <h3 class="payment-title">WMDB</h3>
+                    </div>
+                </div>
+                <van-switch v-model="activeZ2" size="22px" />
+            </div>
+
+            <!-- Mixed/Z3 -->
+            <div class="payment-item">
+                <div class="payment-info">
+                    <van-icon name="card" class="payment-icon" />
+                    <div class="payment-detail">
+                        <h3 class="payment-title">Mixed</h3>
+                    </div>
+                </div>
+                <van-switch v-model="activeZ3" size="22px" />
+            </div>
+        </div>
+
+        <!-- 提交按钮 -->
+        <div class="submit-footer">
+            <van-button round type="primary" class="submit-btn" @click="handleSubmit">
+                <van-icon name="success" class="btn-icon" />
+                {{ $t('device.modify')}}
+            </van-button>
+        </div>
+    </div>
+</template>
+
+<script>
+import sHeader from "@/components/SimpleHeader";
+import { showConfirmDialog } from "vant";
+import { useRoute } from 'vue-router';
+import { ref } from "vue";
+import { useI18n } from 'vue-i18n';
+import { onMounted } from "vue";
+
+
+export default {
+    components: { sHeader },
+    setup() {
+        const { t } = useI18n();
+        const route = useRoute();
+        const deviceName = ref(route.query.name);
+        const activeZ1 = ref(false);
+        const activeZ2 = ref(false);
+        const activeZ3 = ref(false);
+
+        onMounted(() => {
+            console.log(route.query.payment)
+            if (route.query.payment) {
+                const payment = route.query.payment.split(',')
+                if (payment.includes('Z1')) activeZ1.value = true
+                if (payment.includes('Z2')) activeZ2.value = true
+                if (payment.includes('Z3')) activeZ3.value = true
+            }
+        });
+
+        const handleSubmit = () => {
+            showConfirmDialog({
+                title: t('device.operationConfirmation'),
+                message: t('device.pleaseConfirmAgainWhetherToOperate'),
+            }).then(() => {
+                // on confirm
+                const activePayments = [];
+                if (activeZ1.value) activePayments.push("Z1");
+                if (activeZ2.value) activePayments.push("Z2");
+                if (activeZ3.value) activePayments.push("Z3");
+                const result = activePayments.join(',')
+                console.log(result)
+            }).catch(() => {
+                // on cancel
+            });
+        }
+
+
+        return {
+            deviceName,
+            activeZ1,
+            activeZ2,
+            activeZ3,
+            handleSubmit
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.payment-settings {
+    --payment-bg: #ffffff;
+    --border-color: #ebedf0;
+    --active-color: #2c87c8;
+    --text-primary: #323233;
+    --text-secondary: #969799;
+
+    background: #f7f8fa;
+    min-height: 100vh;
+
+
+    .device-header {
+        display: flex;
+        align-items: center;
+        padding: 12px 15px;
+        background: #fff;
+        margin: 12px 16px;
+        border-radius: 8px;
+        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+
+        .vertical-indicator {
+            width: 4px;
+            height: 15px;
+            background: var(--active-color, #2c87c8);
+            border-radius: 2px;
+            margin-right: 10px;
+        }
+
+        .device-name {
+            margin: 0;
+            font-size: 15px;
+            color: #404d74;
+            font-weight: 550;
+
+            // 长名称处理
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+            max-width: 70vw;
+        }
+    }
+
+    .settings-card {
+        margin: 16px;
+        padding: 8px 16px;
+        background: var(--payment-bg);
+        border-radius: 12px;
+        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
+    }
+
+    .payment-item {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 16px 0;
+        border-bottom: 1px solid var(--border-color);
+
+        &:last-child {
+            border-bottom: none;
+        }
+
+        .payment-info {
+            display: flex;
+            align-items: center;
+            flex: 1;
+        }
+
+        .payment-icon {
+            font-size: 22px;
+            color: var(--active-color);
+            margin-right: 12px;
+        }
+
+        .payment-detail {
+            flex: 1;
+
+            .payment-title {
+                margin: 0;
+                font-size: 16px;
+                color: var(--text-primary);
+            }
+
+            .payment-desc {
+                margin: 4px 0 0;
+                font-size: 12px;
+                color: var(--text-secondary);
+            }
+        }
+    }
+
+    .submit-footer {
+        padding: 24px 16px;
+
+        .submit-btn {
+            width: 100%;
+            height: 44px;
+            font-size: 16px;
+
+            .btn-icon {
+                margin-right: 8px;
+                vertical-align: -2px;
+            }
+        }
+    }
+}
+</style>

+ 2 - 2
src/views/device/returnCoin/index.vue

@@ -98,13 +98,13 @@ export default {
                 adminId: user.id
             };
             showConfirmDialog({
-                title: t('alramClean.tips'),
+                title: t('alarmClean.tips'),
                 message: t('device.returnCoinPage.tipsContent'),
             }).then(async () => {
                 const { data } = await applyReturnCoin(params);
                 console.log("data>>>", data);
                 if (data.code) {
-                    showToast(t('alramClean.successfully'));
+                    showToast(t('alarmClean.successfully'));
                     setTimeout(() => {
                         router.go(-1);
                     }, 1500);

+ 3 - 0
src/views/orderCenter/index.vue

@@ -740,6 +740,9 @@ export default {
       if (searchParams.type == null || searchParams.type == '') {
         searchParams.type = user.ifForeign;
       }
+      if (user.type === 1) {
+        searchParams.userName = "";
+      }
       // 显示加载框
       const downloadOrder = showLoadingToast({
         forbidClick: true,

+ 319 - 74
src/views/purse/index.vue

@@ -2,63 +2,31 @@
     <div class="wallet-page">
         <!-- 导航栏 -->
         <s-header name="我的钱包" :noback="false" :isBorder="false"></s-header>
-
-        <!-- 新版余额卡片 -->
-        <!-- <div class="new-balance-card">
-            <div class="card-bg">
-                <div class="wave"></div>
-                <div class="deco-circle"></div>
-            </div>
-
-            <div class="balance-content">
-                <div class="balance-header">
-                    <van-icon name="balance-pay" color="rgba(255,255,255,0.9)" size="20" />
-                    <span class="balance-label">可用余额(元)</span>
-                </div>
-
-                <div class="balance-main">
-                    <span class="currency">¥</span>
-                    <span class="amount">8,888.00</span>
-                </div>
-
-                <div class="action-buttons">
-                    <van-button round class="recharge-btn" @click="handleRecharge">
-                        <van-icon name="cash-back-record" size="16" />
-                        <span>立即充值</span>
-                    </van-button>
-
-                    <van-button round plain class="withdraw-btn" @click="handleWithdraw">
-                        <van-icon name="cash-on-deliver" size="16" />
-                        <span>申请提现</span>
-                    </van-button>
-                </div>
-            </div>
-        </div> -->
+        <!-- 新增提示栏 -->
+        <van-notice-bar v-if="showNotice" left-icon="info" color="#ed6a0c" background="#fef6e6" scrollable>
+            温馨提示:今日收款金额 {{ formatAmount(receivableBalance) }} 元将于T+1日结算后可提现
+        </van-notice-bar>
 
         <!-- 余额概览 -->
         <div class="balance-section">
             <div class="section-title">
-                <van-icon name="balance-list" color="#4d6add" size="18" />
+                <van-icon name="balance-list" color="#2c87c8" size="18" />
                 <span>资金账户</span>
             </div>
 
             <div class="balance-cards">
                 <!-- 今日收款卡片 -->
-                <div class="balance-card today-card">
+                <div class="balance-card today-card" v-if="user.payPlatform === '0'">
                     <div class="card-header">
                         <van-icon name="cash-back-record" color="white" size="18" />
                         <div class="card-title">
                             <h3>今日收款余额(元)</h3>
                         </div>
                     </div>
-                    <div class="amount">8,888.00</div>
+                    <div class="amount">{{ formatAmount(receivableBalance) }}</div>
                     <van-button icon="cash-back-record" @click="handleRecharge">
                         立即充值
                     </van-button>
-                    <!-- <div class="hint-text">
-                        <van-icon name="info" size="12" />
-                        <span>T+1自动转入可提现余额</span>
-                    </div> -->
                 </div>
 
                 <!-- 可提现卡片 -->
@@ -69,7 +37,7 @@
                             <h3>可提现余额(元)</h3>
                         </div>
                     </div>
-                    <div class="amount">6,666.00</div>
+                    <div class="amount">{{ formatAmount(withdrawableBalance) }}</div>
                     <van-button icon="cash-on-deliver" @click="handleWithdraw">
                         立即提现
                     </van-button>
@@ -80,11 +48,11 @@
         <!-- 记录入口 -->
         <div class="record-section">
             <div class="section-title">
-                <van-icon name="records" color="#4d6add" size="18" />
+                <van-icon name="records" color="#2c87c8" size="18" />
                 <span>交易记录</span>
             </div>
             <div class="record-cards">
-                <div class="record-card" @click="goToAutoRecord">
+                <!-- <div class="record-card" @click="goToAutoRecord">
                     <div class="card-icon auto">
                         <van-icon name="passed" size="24" />
                     </div>
@@ -93,9 +61,9 @@
                         <p>查看系统自动结算记录</p>
                     </div>
                     <van-icon name="arrow" size="16" color="#ccc" />
-                </div>
+                </div> -->
 
-                <div class="record-card" @click="goToManualRecord">
+                <div class="record-card" @click="jumpTo('/withdrawList')">
                     <div class="card-icon manual">
                         <van-icon name="cash-on-deliver" size="24" />
                     </div>
@@ -111,28 +79,24 @@
         <!-- 银行卡管理 -->
         <div class="bank-section">
             <div class="section-title">
-                <van-icon name="credit-pay" color="#4d6add" size="18" />
+                <van-icon name="credit-pay" color="#2c87c8" size="18" />
                 <span>银行卡管理</span>
             </div>
 
-            <div class="bank-cards">
+            <div class="bank-cards" @click="jumpTo('/settlement')">
                 <!-- 已绑卡状态 -->
                 <div class="bank-card" v-if="hasBankCard">
                     <div class="card-header">
                         <van-icon name="card" size="20" />
-                        <span>储蓄卡</span>
-                    </div>
-                    <div class="card-number">****​ ​****​ ​****​ 1234</div>
-                    <div class="card-footer">
-                        <span>中国工商银行</span>
-                        <van-icon name="ellipsis" size="16" />
+                        <span>已绑定</span>
                     </div>
+                    <div class="card-number">{{ bankCardNo }}</div>
                     <div class="auto-settle-hint" v-if="autoSettle">
-                        <van-icon name="checked" color="#4d6add" size="18" />
+                        <van-icon name="checked" color="#2c87c8" size="18" />
                         <span>本卡已启用自动结算</span>
                     </div>
                     <div class="auto-settle-hint" v-if="!autoSettle">
-                        <van-icon name="circle" color="#4d6add" size="18" />
+                        <van-icon name="circle" color="#2c87c8" size="18" />
                         <span>本卡已关闭自动结算</span>
                     </div>
                 </div>
@@ -142,7 +106,7 @@
                     <div class="empty-content">
                         <p class="empty-title">尚未绑定银行卡</p>
                         <p class="empty-desc">绑定后可享受快捷支付服务</p>
-                        <van-button type="primary" round size="small" @click="handleBindCard" class="bind-btn">
+                        <van-button type="primary" round size="small" class="bind-btn">
                             <van-icon name="plus" size="16" />
                             立即绑卡
                         </van-button>
@@ -151,38 +115,262 @@
             </div>
         </div>
         <div class="bottom-spacer"></div>
+        <!--提现弹窗-->
+        <van-popup v-model:show="showWithdrawPopup" position="bottom" round :style="{ height: '40%' }">
+            <div class="withdraw-popup">
+                <h3 class="popup-title">提现金额</h3>
+
+                <div class="amount-input">
+                    <span class="currency-symbol">¥</span>
+                    <van-field v-model="withdrawAmount" type="number" placeholder="请输入提现金额"
+                        :formatter="formatterAmount" />
+                </div>
+
+                <div class="balance-hint">
+                    可提现余额 {{ formatAmount(withdrawableBalance) }} 元
+                </div>
+
+                <van-button type="primary" block round class="confirm-btn" @click="confirmWithdraw">
+                    确认提现
+                </van-button>
+            </div>
+        </van-popup>
     </div>
+
 </template>
 
 <script>
 import sHeader from "../../components/SimpleHeader";
+import { getBalance, withdraw } from "../../service/purse/index"
+import { onMounted, ref } from "vue";
+import { getOneJoinPayMch } from '../../service/joinpayMch';
+import { getHuifuId, getMerchantBusiness, addWithdraw } from "@/service/huifuMch";
+import { getLoginUser } from "../../common/js/utils";
+import { useRouter } from "vue-router";
+import { showConfirmDialog, showSuccessToast, showToast } from "vant";
 
 export default {
     components: { sHeader },
     setup() {
 
-
+        const user = getLoginUser();
+        const router = useRouter();
+        const receivableBalance = ref(0.00); // 今日收款余额
+        const withdrawableBalance = ref(0.00); // 可提现余额
+        const autoSettle = ref(false);
+        const hasBankCard = ref(false);
+        const bankCardInfo = ref(null);
+        const bankCardNo = ref('');
+        // 通知栏显示控制
+        const showNotice = ref(false);
+        // 提现弹窗数据
+        const showWithdrawPopup = ref(false);
+        const withdrawAmount = ref('');
+        const withdrawaParams = ref({
+            adminId: user.id,
+            amount: 0,
+            payPlatform: user.payPlatform,
+            companyType: user.companyType,
+        })
         const handleRecharge = () => {
-            console.log('handleRecharge');
+            showToast({ message: '暂未开放' });
+        };
+
+        // 新增金额格式化方法
+        const formatterAmount = (value) => {
+            // 只允许输入数字和小数点
+            value = value.replace(/[^\d.]/g, '');
+
+            // 处理多个小数点的情况
+            const pointIndex = value.indexOf('.');
+            if (pointIndex > -1) {
+                value = value.slice(0, pointIndex + 3); // 限制小数点后两位
+            }
+
+            return value;
+        };
+
+        // 新增确认提现方法
+        const confirmWithdraw = async () => {
+            const amount = Number(withdrawAmount.value);
+
+            if (!amount || amount <= 0) {
+                showToast('请输入有效的提现金额');
+                return;
+            }
+
+            if (amount > withdrawableBalance.value) {
+                showToast('提现金额不可超过可用余额');
+                return;
+            }
+            withdrawaParams.value.amount = amount;
+            console.log('withdrawaParams', withdrawaParams.value);
+            showConfirmDialog({
+                message: '确定要提现 ' + amount + ' 元吗?',
+            }).then(async () => {
+                const { data } = await withdraw(withdrawaParams.value);
+                if (data.code === "00000") {
+                    showSuccessToast('申请成功');
+                    setTimeout(async() => {
+                        await queryBalance();
+                    }, 1500);
+                }
+            });
+            showWithdrawPopup.value = false;
         };
 
+        // 点击提现
         const handleWithdraw = () => {
-            console.log('handleWithdraw');
+            if (!hasBankCard.value) {
+                showConfirmDialog({
+                    title: '未绑定银行卡',
+                    message: '提现需要先绑定银行卡,是否立即绑定?',
+                    confirmButtonColor: '#2c87c8',
+                }).then(() => {
+                    router.push('/settlement');
+                });
+                return;
+            }
+            if (bankCardInfo.value.settMode === 1 || bankCardInfo.value.settType === 1) {
+                showConfirmDialog({
+                    title: '未开启手动提现',
+                    message: '当前银行卡已开启自动结算,是否切换成手动提现?',
+                    confirmButtonColor: '#2c87c8',
+                }).then(() => {
+                    router.push('/settlement');
+                });
+                return;
+            }
+
+            showWithdrawPopup.value = true;
         };
 
         const goToAutoRecord = () => {
-            console.log('goToAutoRecord');
+            showToast({ message: '暂未开放' });
         };
 
         const goToManualRecord = () => {
-            console.log('goToManualRecord');
+            showToast({ message: '暂未开放' });
         }
+        onMounted(async () => {
+            await getBankCard();
+            await queryBalance();
+            if (user.payPlatform === '0' && (bankCardInfo.value && (bankCardInfo.value.settMode === 2 || bankCardInfo.value.settType === 2)) ) {
+                showNotice.value = true;
+            }
+
+            // 查询汇付是否开启取现功能
+            if (user.payPlatform === '1' && bankCardInfo.value.huifuId != null && bankCardInfo.value.tokenNo == null) {
+                const { data } = await getMerchantBusiness({ adminId: user.id });
+                if (data.code === "00000") {
+                    if (data.data === null || data.data === "") {
+                        await addWithdraw({ adminId: user.id });
+                    }
+                }
+            }
+        });
+
+        // 查询余额
+        const queryBalance = async () => {
+            try {
+                const { data } = await getBalance({ adminId: user.id });
+                if (data.code === "00000") {
+                    if (data.data.receivableBalance != null) {
+                        receivableBalance.value = data.data.receivableBalance;
+                    }
+                    if (data.data.withdrawableBalance != null) {
+                        withdrawableBalance.value = data.data.withdrawableBalance;
+                    }
+                }
+            } catch (error) {
+                console.log('error', error);
+            }
+        };
+
+        // 格式化金额
+        const formatAmount = (amount) => {
+            return new Intl.NumberFormat('en-US', {
+                minimumFractionDigits: 2,
+                maximumFractionDigits: 2
+            }).format(Number(amount))
+        };
+
+        // 获取绑定银行卡
+        const getBankCard = async () => {
+            if (user.payPlatform && user.payPlatform == "1") {
+                // 汇付
+                const { data } = await getHuifuId({ adminId: user.id });
+                if (data.code === "00000" && data.data) {
+                    bankCardInfo.value = data.data;
+                    if (bankCardInfo.value.cardNo != null) {
+                        bankCardNo.value = formatBankCard(bankCardInfo.value.cardNo);
+                        hasBankCard.value = true;
+                    }
+                    if (data.data.settType === 1) {
+                        autoSettle.value = true;
+                    }
+                }
+            } else {
+                // 汇聚
+                const { data } = await getOneJoinPayMch({ adminId: user.id });
+                if (data.code === "00000" && data.data) {
+                    bankCardInfo.value = data.data;
+                    if (bankCardInfo.value.bankAccountNo != null) {
+                        bankCardNo.value = formatBankCard(bankCardInfo.value.bankAccountNo);
+                        hasBankCard.value = true;
+                    }
+                    if (data.data.settMode === 1) {
+                        autoSettle.value = true;
+                    }
+                }
+
+            }
+        };
+
+        // 格式化银行卡号
+        const formatBankCard = (cardNumber) => {
+            if (!cardNumber) return '未获取卡号';
+            const cleaned = cardNumber.toString().replace(/\D/g, '');
+
+            // 动态分组逻辑
+            const lastFour = cleaned.slice(-4);
+            const starCount = Math.max(cleaned.length - 4, 0);
+            const starGroups = Array(Math.ceil(starCount / 4)).fill('****').join(' ');
+
+            return `${starGroups} ${lastFour}`.trim();
+        };
+
+        // 跳转绑卡页面
+        const jumpTo = (value) => {
+            router.push({ path: value });
+        };
 
         return {
             handleRecharge,
-            handleWithdraw,
             goToAutoRecord,
-            goToManualRecord
+            goToManualRecord,
+            receivableBalance,
+            withdrawableBalance,
+            formatAmount,
+            bankCardInfo,
+            hasBankCard,
+            autoSettle,
+            formatBankCard,
+            jumpTo,
+
+            // 提现
+            handleWithdraw,
+            showWithdrawPopup,
+            withdrawAmount,
+            formatterAmount,
+            confirmWithdraw,
+
+            // 通知栏
+            showNotice,
+
+            // 数据
+            bankCardNo,
+            user,
         };
     }
 };
@@ -200,7 +388,7 @@ export default {
     gap: 4px;
     padding: 10px 10px;
     font-size: 18px;
-    color: #4d6add;
+    color: #2c87c8;
     font-weight: 700;
 }
 
@@ -272,7 +460,7 @@ export default {
 .card-header {
     display: flex;
     align-items: center;
-    gap: 12px;
+    gap: 10px;
     margin-bottom: 10px;
     position: relative;
     z-index: 1;
@@ -280,7 +468,7 @@ export default {
 
 .card-header .van-icon {
     background: rgba(255, 255, 255, 0.15);
-    padding: 8px;
+    padding: 5px;
     border-radius: 10px;
 }
 
@@ -309,7 +497,7 @@ export default {
     color: white !important;
     border-radius: 20px;
     transition: all 0.3s ease;
-    width: auto
+    width: auto;
 }
 
 /* 仅影响卡片内的按钮悬停状态 */
@@ -409,7 +597,7 @@ export default {
 
     &.auto {
         background: rgba(77, 106, 221, 0.1);
-        color: #4d6add;
+        color: #2c87c8;
     }
 
     &.manual {
@@ -448,7 +636,6 @@ export default {
     border-radius: 12px;
     padding: 10px 5px;
     margin: 0 10px;
-    // box-shadow: 0 2px 8px rgba(77, 106, 221, 0.05);
     box-shadow: 0 4px 12px rgba(77, 106, 221, 0.08);
     position: relative;
     overflow: hidden;
@@ -460,7 +647,7 @@ export default {
         top: 0;
         bottom: 0;
         width: 4px;
-        background: #4d6add;
+        background: #2c87c8;
     }
 
     &.backup::before {
@@ -489,7 +676,7 @@ export default {
     font-size: 18px;
     color: #333;
     letter-spacing: 2px;
-    margin: 16px 0;
+    margin: 16px 10px;
 }
 
 .card-footer {
@@ -497,6 +684,7 @@ export default {
     align-items: center;
     justify-content: space-between;
     color: #999;
+    padding: 0 10px;
     font-size: 12px;
 }
 
@@ -515,6 +703,7 @@ export default {
     gap: 8px;
     color: #666;
     font-size: 13px;
+    padding: 10px 5px;
 }
 
 /* 未绑卡状态样式 */
@@ -548,7 +737,7 @@ export default {
 }
 
 .bind-btn {
-    background: #4d6add;
+    background: #2c87c8;
     padding: 8px 24px;
     box-shadow: 0 3px 8px rgba(77, 106, 221, 0.2);
 }
@@ -560,8 +749,64 @@ export default {
 
 /* 占位元素样式 */
 .bottom-spacer {
-  height: 50px;
-  height: calc(60px + env(safe-area-inset-bottom));
-  pointer-events: none; /* 防止遮挡点击 */
+    height: 50px;
+    height: calc(60px + env(safe-area-inset-bottom));
+    pointer-events: none;
+    /* 防止遮挡点击 */
+}
+
+/**
+ * 提现弹窗样式
+ */
+.withdraw-popup {
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+
+    .popup-title {
+        text-align: center;
+        font-size: 18px;
+        color: #333;
+        margin-bottom: 20px;
+    }
+
+    .amount-input {
+        display: flex;
+        align-items: center;
+        margin: 15px 0;
+        border-bottom: 1px solid #eee;
+
+        .currency-symbol {
+            font-size: 24px;
+            color: #333;
+            margin-right: 8px;
+        }
+
+        :deep(.van-field) {
+            padding: 10px 0;
+            font-size: 22px;
+
+            input {
+                font-size: 22px;
+                font-weight: 500;
+            }
+        }
+    }
+
+    .balance-hint {
+        font-size: 12px;
+        color: #999;
+        margin-bottom: auto;
+    }
+
+    .confirm-btn {
+        margin-top: 20px;
+        background: #2c87c8;
+        border: none;
+
+        &:active {
+            opacity: 0.9;
+        }
+    }
 }
 </style>

+ 740 - 0
src/views/purse/withdrawList.vue

@@ -0,0 +1,740 @@
+<template>
+    <div class="withdraw-record-page">
+        <!-- 导航栏 -->
+        <s-header name="提现记录" :noback="false" :isBorder="false"></s-header>
+        <div class="content-container">
+            <!-- 统计卡片 -->
+            <div class="stats-card">
+                <div class="stats-content">
+                    <div class="stats-icon-box">
+                        <van-icon name="bar-chart-o" class="stats-icon" />
+                    </div>
+                    <div class="stats-text">
+                        <div class="stats-title">提现记录</div>
+                        <div class="stats-info">
+                            <span class="stats-number">{{ total }}</span>
+                            <span class="stats-unit">{{ $t('device.makeRecord.total') }}</span>
+                        </div>
+                    </div>
+                    <!-- 右侧操作按钮 -->
+                    <div class="action-buttons">
+                        <van-icon name="filter-o" class="action-icon" @click="showFilter = true" />
+                        <van-icon name="down" class="action-icon" @click="showExport = true" />
+                    </div>
+                </div>
+            </div>
+
+            <!-- 筛选弹窗 -->
+            <van-popup v-model:show="showFilter" position="right" class="filter-popup">
+                <div class="popup-header">
+                    <h3>{{ $t('device.makeRecord.condition') }}</h3>
+                    <van-icon name="cross" @click="showFilter = false" />
+                </div>
+
+                <div class="filter-content">
+                    <!-- 提现单号输入 -->
+                    <div class="filter-item">
+                        <label>提现单号</label>
+                        <van-field v-model="filter.orderNo" placeholder="请输入提现单号" clearable />
+                    </div>
+
+                    <!-- 提现状态单选 -->
+                    <div class="filter-item">
+                        <label>提现状态</label>
+                        <van-radio-group v-model="filter.status">
+                            <van-cell-group>
+                                <van-cell v-for="status in statusOptions" :key="status.value" clickable
+                                    @click="filter.status = status.value">
+                                    <template #title>
+                                        <span class="status-label">{{ status.label }}</span>
+                                    </template>
+                                    <template #right-icon>
+                                        <van-radio :name="status.value" />
+                                    </template>
+                                </van-cell>
+                            </van-cell-group>
+                        </van-radio-group>
+                    </div>
+
+                    <!-- 时间范围 -->
+                    <div class="filter-item">
+                        <label>提现时间</label>
+                        <div class="date-picker">
+                            <van-field v-model="filter.startTime" :placeholder="$t('device.makeRecord.startTime')"
+                                @click="showStartPicker = true" />
+                            <van-field v-model="filter.endTime" :placeholder="$t('device.makeRecord.endTime')"
+                                @click="showEndPicker = true" />
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 底部操作 -->
+                <div class="popup-footer">
+                    <van-button type="default" @click="handleReset">重置</van-button>
+                    <van-button type="primary" @click="handleConfirmFilter">筛选</van-button>
+                </div>
+            </van-popup>
+
+            <!-- 时间选择器 -->
+            <van-popup v-model:show="showStartPicker" position="bottom">
+                <van-date-picker :columns-type="columnsType" v-model="startDate" @confirm="handleStartConfirm"
+                    @cancel="showStartPicker = false" />
+            </van-popup>
+            <van-popup v-model:show="showEndPicker" position="bottom">
+                <van-date-picker :columns-type="columnsType" v-model="endDate" @confirm="handleEndConfirm"
+                    @cancel="showEndPicker = false" />
+            </van-popup>
+
+            <!-- 导出弹窗 -->
+            <van-dialog v-model:show="showExport" :title="$t('device.makeRecord.export')"
+                :message="$t('device.makeRecord.exportTips')" show-cancel-button @confirm="handleExport">
+            </van-dialog>
+
+            <!-- 记录列表 -->
+            <van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="loadRecords">
+                <div class="record-list">
+                    <div v-for="item in records" :key="item.id" class="record-card" :class="[`status-${item.status}`]">
+                        <div class="card-header">
+                            <div class="status-amount">
+                                <div class="status-badge">
+                                    <van-icon name="cash-back-record" class="status-icon" />
+                                    <span class="status-text">{{ statusText(item.status) }}</span>
+                                    <div class="amount">¥{{ formatAmount(item.amount) }}</div>
+                                </div>
+                            </div>
+                            <van-icon v-if="item.status === 0" name="replay" class="refresh-icon" @click.stop="refreshStatus(item.orderNo)" />
+                        </div>
+
+                        <div class="card-content">
+                            <div class="info-item">
+                                <van-icon name="description" class="info-icon" />
+                                <span class="info-text">单号:{{ item.orderNo }}</span>
+                            </div>
+
+                            <div class="info-item">
+                                <van-icon name="clock" class="info-icon" />
+                                <span class="info-text">申请时间:{{ showDateTime(item.createDate) }}</span>
+                            </div>
+
+                            <div class="info-item" v-if="item.status === 1">
+                                <van-icon name="clock" class="info-icon" />
+                                <span class="info-text">到账时间:{{ showDateTime(item.arrivalDate) || '--' }}</span>
+                            </div>
+                        </div>
+
+                        <div v-if="item.status === 2" class="error-tip">
+                            <van-icon name="warning" />
+                            <span>{{ item.resultMsg || '系统处理异常' }}</span>
+                        </div>
+                    </div>
+                </div>
+            </van-list>
+        </div>
+    </div>
+</template>
+
+<script>
+import { $M_ExportFile, getLoginUser } from "../../common/js/utils";
+import sHeader from "../../components/SimpleHeader";
+import { ref, reactive } from 'vue';
+import { withdrawRecord, exportWithdrawRecord, withdrawStatus } from "../../service/purse/index";
+import { showFailToast } from "vant";
+import dateUtil from "../../utils/dateUtil";
+
+
+export default {
+    components: { sHeader },
+    setup() {
+        const user = getLoginUser();
+        const filter = reactive({
+            adminId: user.type > 1 ? user.id : '', // 用户账户id
+            status: '', // 提现状态 0:处理中 1:提现成功 2:提现失败
+            payPlatform: user.type > 1 ? user.payPlatform : '', // 支付平台
+            orderNo: '', // 提现单号
+            current: 0, // 页数
+            size: 10, // 页大小
+            startTime: "", // 开始时间
+            endTime: "", // 结束时间
+        });
+        const records = ref([]);
+        const loading = ref(false);
+        const finished = ref(false);
+        const total = ref(0);
+
+        const showFilter = ref(false);
+        const showExport = ref(false);
+
+        // 时间选择
+        const columnsType = ref(["year", "month", "day"]);
+        const showStartPicker = ref(false);
+        const showEndPicker = ref(false);
+        const startDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]);
+        const endDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]);
+        // 时间选择
+        const handleStartConfirm = ({ selectedValues }) => {
+            console.log(selectedValues.join('/'));
+            filter.startTime = selectedValues.join('/');
+            showStartPicker.value = false;
+        }
+
+        // 时间选择
+        const handleEndConfirm = ({ selectedValues }) => {
+            console.log(selectedValues.join('/'));
+            filter.endTime = selectedValues.join('/');
+            showEndPicker.value = false;
+        }
+        // 状态选项
+        const statusOptions = [
+            { label: '全部状态', value: '' },
+            { label: '处理中', value: 0 },
+            { label: '提现成功', value: 1 },
+            { label: '提现失败', value: 2 }
+        ];
+
+        // 加载记录
+        const loadRecords = async () => {
+            if (!finished.value) {
+                filter.current = filter.current + 1;
+                await getWithdrawRecords();
+            }
+        };
+
+        // 获取提现记录
+        const getWithdrawRecords = async () => {
+            finished.value = false;
+            const { data } = await withdrawRecord(filter);
+            if (data.code) {
+                records.value = records.value.concat(
+                    data.data.records
+                );
+                total.value = data.data.total;
+                if (records.value.length === data.data.total) {
+                    finished.value = true;
+                }
+                loading.value = false;
+            } else {
+                showFailToast(data.message);
+            }
+        };
+
+        // 状态标签类型
+        const statusTagType = (status) => {
+            console.log(status);
+            const statusMap = {
+                0: 'warning',
+                1: 'success',
+                2: 'danger'
+            };
+            return statusMap[status];
+        };
+
+        // 重置
+        const handleReset = () => {
+            filter.status = "";
+            filter.startTime = "";
+            filter.endTime = "";
+            filter.orderNo = "";
+        }
+
+        // 确认
+        const handleConfirmFilter = async () => {
+            showFilter.value = false;
+            filter.current = 1;
+            records.value = [];
+            await getWithdrawRecords();
+        }
+        // 导出记录
+        const handleExport = async () => {
+            const { headers, data } = await exportWithdrawRecord(Object.assign({}, filter));
+            $M_ExportFile(data, headers);
+        };
+
+        // 查询提现状态
+        const refreshStatus = async (orderNo) => {
+            const { data } = await withdrawStatus({ adminId: user.id, orderNo: orderNo });
+            if (data.code === '00000') {
+                setTimeout(async () => {
+                    filter.current = 1;
+                    records.value = [];
+                    await getWithdrawRecords();
+                }, 500);
+            }
+        };
+
+        const showDateTime = (date) => {
+            if (!date) {
+                return "";
+            }
+            const currentDate = new Date(dateUtil.formateDate(new Date(date), "yyyy/MM/dd hh:mm:ss"));
+            return dateUtil.timeZoneDate(currentDate);
+        };
+
+        const statusText = (status) => {
+            switch (status) {
+                case 0:
+                    return '处理中';
+                case 1:
+                    return '提现成功';
+                case 2:
+                    return '提现失败';
+            }
+        };
+
+
+        // 格式化金额
+        const formatAmount = (amount) => {
+            return new Intl.NumberFormat('en-US', {
+                minimumFractionDigits: 2,
+                maximumFractionDigits: 2
+            }).format(Number(amount))
+        };
+
+        return {
+            filter,
+            records,
+            loading,
+            finished,
+            statusOptions,
+            statusTagType,
+            loadRecords,
+            statusText,
+            formatAmount,
+            showDateTime,
+            total,
+
+            showFilter,
+            showExport,
+            showStartPicker,
+            showEndPicker,
+            startDate,
+            endDate,
+            columnsType,
+
+            refreshStatus,
+            handleStartConfirm,
+            handleEndConfirm,
+            handleExport,
+            handleReset,
+            handleConfirmFilter,
+        };
+    },
+};
+</script>
+
+<style lang="less" scoped>
+.withdraw-record-page {
+    --primary-color: #2c87c8;
+    --success-color: #38b48d;
+    --warning-color: #ff9500;
+    --error-color: #ff4d4f;
+    --text-primary: #1a1a1a;
+    --text-secondary: #666;
+    --background-light: #f8f9ff;
+
+    background: #f8f9ff;
+    overflow-y: auto;
+    // min-height: 100vh;
+}
+
+.filter-bar {
+    padding: 12px 16px;
+    background: white;
+    display: flex;
+    gap: 12px;
+    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
+
+    .van-search {
+        flex: 1;
+        padding: 0;
+
+        :deep(.van-field__left-icon) {
+            margin-right: 8px;
+        }
+    }
+
+    .filter-buttons {
+        display: flex;
+        gap: 8px;
+
+        .van-button {
+            border-radius: 16px;
+            padding: 0 12px;
+            border: 1px solid #eee;
+
+            &::before {
+                display: none;
+            }
+        }
+    }
+}
+
+.stats-card {
+    background: #ffffff;
+    border-radius: 12px;
+    padding: 18px;
+    margin: 16px 15px;
+    position: relative;
+    overflow: hidden;
+
+    &::before {
+        content: "";
+        position: absolute;
+        top: -20px;
+        right: -20px;
+        width: 80px;
+        height: 80px;
+        background: #f0f3ff;
+        border-radius: 50%;
+    }
+
+    .stats-content {
+        display: flex;
+        align-items: center;
+        position: relative;
+        z-index: 1;
+    }
+
+    .stats-icon-box {
+        width: 36px; // 容器尺寸缩小
+        height: 36px; // 容器尺寸缩小
+        background: linear-gradient(135deg, #4e6bdd 0%, #6b8eff 100%);
+        border-radius: 8px; // 圆角缩小
+        margin-right: 12px; // 右边距缩小
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        .stats-icon {
+            font-size: 18px;
+            color: white;
+        }
+    }
+
+    .stats-text {
+        .stats-title {
+            color: #666;
+            font-size: 12px;
+            margin-bottom: 4px;
+        }
+
+        .stats-info {
+            display: flex;
+            align-items: baseline;
+
+            .stats-number {
+                color: #4e6bdd;
+                font-size: 22px;
+                font-weight: 600;
+                margin-right: 6px;
+            }
+
+            .stats-unit {
+                color: #999;
+                font-size: 12px;
+            }
+        }
+    }
+
+    .action-buttons {
+        display: flex;
+        gap: 16px; // 增大按钮间距
+        margin-left: auto; // 确保右对齐
+
+        .action-icon {
+            font-size: 24px; // 增大图标尺寸
+            color: #ffffff; // 白色图标
+            padding: 8px; // 增大点击区域
+            background: #4e6bdd; // 主题色背景
+            border-radius: 8px; // 圆角匹配整体风格
+            box-shadow: 0 2px 6px rgba(78, 107, 221, 0.3); // 添加投影
+            transition: all 0.2s ease;
+
+            // 悬停效果
+            &:active {
+                transform: scale(0.95);
+                background: #3b5ab3;
+                box-shadow: 0 1px 3px rgba(78, 107, 221, 0.2);
+            }
+
+        }
+
+        // 单独设置导出按钮颜色
+        .van-icon-down {
+            background: #66bb6a; // 绿色表示导出操作
+
+            &:active {
+                background: #4caf50;
+            }
+        }
+    }
+}
+
+.filter-popup {
+    width: 75%;
+    height: 100%;
+
+    .popup-header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 16px;
+        border-bottom: 1px solid #eee;
+
+        h3 {
+            margin: 0;
+            font-size: 18px;
+        }
+
+        .van-icon {
+            font-size: 20px;
+            color: #999;
+        }
+    }
+
+    .filter-content {
+        padding: 16px;
+
+        .filter-item {
+            margin-bottom: 20px;
+
+            label {
+                font-size: 14px;
+                color: #606266;
+                margin-bottom: 8px;
+                display: block;
+            }
+
+            // 设备编号输入框样式
+            .van-field {
+                background: #f5f7fa;
+                border-radius: 4px;
+                padding: 10px 12px;
+
+                &::placeholder {
+                    color: #c0c4cc;
+                }
+            }
+
+            .van-radio-group {
+                width: 100%;
+            }
+
+            .van-cell {
+
+                // 选中状态样式
+                &--selected {
+                    background-color: #f0f3ff;
+
+                    .status-label {
+                        color: #4e6bdd;
+                    }
+                }
+            }
+
+            .van-radio__icon--checked .van-icon {
+                background-color: #4e6bdd;
+                border-color: #4e6bdd;
+            }
+
+            .date-picker {
+                display: grid;
+                grid-template-columns: 1fr 1fr;
+                gap: 8px;
+            }
+        }
+    }
+
+    .popup-footer {
+        position: fixed;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        display: flex;
+        gap: 12px;
+        padding: 16px;
+        background: #fff;
+        border-top: 1px solid #eee;
+
+        .van-button {
+            flex: 1;
+        }
+    }
+}
+
+.record-list {
+    padding: 0 16px 20px;
+
+    .record-card {
+        background: white;
+        border-radius: 12px;
+        padding: 16px;
+        margin-bottom: 12px;
+        box-shadow: 0 2px 12px rgba(25, 43, 114, 0.08);
+        position: relative;
+        overflow: hidden;
+
+        // 状态色条
+        &::before {
+            content: "";
+            position: absolute;
+            left: 0;
+            top: 0;
+            bottom: 0;
+            width: 4px;
+            background: var(--status-color);
+        }
+
+        .card-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: flex-start;
+            margin-bottom: 12px;
+
+            .status-amount {
+                display: flex;
+                align-items: center;
+                gap: 12px;
+
+                .status-badge {
+                    display: flex;
+                    align-items: center;
+                    gap: 6px;
+                    background: rgba(var(--status-rgb), 0.1);
+                    padding: 6px 10px;
+                    border-radius: 20px;
+
+                    .status-icon {
+                        font-size: 16px;
+                        color: var(--status-color);
+                    }
+
+                    .status-text {
+                        font-size: 13px;
+                        font-weight: 500;
+                        color: var(--status-color);
+                    }
+                }
+
+                .amount {
+                    font-size: 20px;
+                    font-weight: 600;
+                    color: #000000;
+                    letter-spacing: 0.5px;
+                }
+            }
+
+            .refresh-icon {
+                font-size: 18px;
+                color: #2c87c8;
+                padding: 6px;
+                border-radius: 50%;
+                transition: all 0.3s ease;
+                cursor: pointer;
+
+                &:hover {
+                    background: rgba(77, 106, 221, 0.1);
+                    transform: rotate(360deg);
+                }
+            }
+        }
+
+        .card-content {
+            .info-item {
+                display: flex;
+                align-items: center;
+                gap: 8px;
+                padding: 8px 0;
+                border-bottom: 1px solid #f5f5f5;
+
+                &:last-child {
+                    border-bottom: none;
+                }
+
+                .info-icon {
+                    font-size: 14px;
+                    color: #999;
+                    flex-shrink: 0;
+                }
+
+                .info-text {
+                    font-size: 13px;
+                    color: #666;
+                    word-break: break-all;
+                }
+            }
+        }
+
+        .error-tip {
+            margin-top: 12px;
+            padding: 10px;
+            background: #fff2f0;
+            border-radius: 6px;
+            display: flex;
+            align-items: center;
+            gap: 6px;
+            font-size: 12px;
+            color: var(--status-color);
+
+            .van-icon {
+                font-size: 14px;
+                flex-shrink: 0;
+            }
+        }
+
+        // 状态颜色定义
+        &.status-0 {
+            // 处理中
+            --status-color: #ff9500;
+            --status-rgb: 255, 149, 0;
+        }
+
+        &.status-1 {
+            // 成功
+            --status-color: #38b48d;
+            --status-rgb: 56, 180, 141;
+        }
+
+        &.status-2 {
+            // 失败
+            --status-color: #ff4d4f;
+            --status-rgb: 255, 77, 79;
+        }
+    }
+
+    @media (max-width: 375px) {
+        .record-card {
+            padding: 12px;
+
+            .card-header {
+                .status-amount {
+                    flex-direction: column;
+                    align-items: flex-start;
+                    gap: 8px;
+
+                    .amount {
+                        font-size: 18px;
+                    }
+                }
+            }
+
+            .card-content {
+                .info-text {
+                    font-size: 12px;
+                }
+            }
+        }
+    }
+
+}
+
+.export-footer {
+    position: fixed;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+
+    .van-button {
+        box-shadow: 0 4px 12px rgba(77, 106, 221, 0.2);
+    }
+}
+</style>

+ 2 - 1
src/views/role/add.vue

@@ -181,7 +181,8 @@ export default {
         if (user.ifForeign === "0") {
 
           // 国内账号
-          delete delete remoteMenus['C18'];
+          delete remoteMenus['C18'];
+          delete remoteMenus['C28'];
         }
       }
 

+ 61 - 139
src/views/settlement/index.vue

@@ -51,6 +51,16 @@
               </van-radio-group>
             </div>
           </div>
+          <!-- 结算方式 -->
+          <div class="van-cell van-field requiredLeft">
+            <div class="van-cell__title van-field__label"><span>结算方式</span></div>
+            <div class="van-cell__value van-field__value radioBox">
+              <van-radio-group v-model="settMode" direction="horizontal" @change="fieldUpdate">
+                <van-radio :name="1" icon-size="18px">自动结算</van-radio>
+                <van-radio :name="2" icon-size="18px">手动提现</van-radio>
+              </van-radio-group>
+            </div>
+          </div>
           <div v-if="altMerchantType == 12" class="requiredLeft">
             <!-- 商户名称 -->
             <div class="cell-input">
@@ -385,13 +395,18 @@
 <script>
 import { onMounted, reactive, toRefs, ref } from "vue";
 import sHeader from "../../components/SimpleHeader";
-import { showFailToast, showSuccessToast, showToast, showLoadingToast } from "vant";
+import { showFailToast, showSuccessToast, showLoadingToast } from "vant";
 import { areaList } from "@vant/area-data";
 import {
   getOneJoinPayMch, updateJoinPayMchCheck, altMchSign,
-  sentImage, updateApproveStatus, saveJoinPayMch
+  sentImage, updateApproveStatus,
+  saveJoinPayMch
 } from '../../service/joinpayMch';
-import { newUploadPic, getHuifuMchCheck, newSaveHuifuMch, updateMerchant, openAccount, sendSms } from "@/service/huifuMch";
+import {
+  getHuifuMchCheck,
+  newSaveHuifuMch, updateMerchant,
+  openAccount
+} from "@/service/huifuMch";
 import { getLoginUser, styleUrl, getLocal, setLocal } from "../../common/js/utils";
 import dateUtil from "../../utils/dateUtil";
 import { useI18n } from "vue-i18n";
@@ -501,7 +516,14 @@ export default {
       }
     }
 
-    let addParams = reactive({
+    const beginDate = ref();
+    const endDate = ref();
+    const beginDateLicense = ref();
+    const endDateLicense = ref();
+    const registeredAddress = ref();
+    const bankAddress = ref();
+
+    const addParams = reactive({
       adminId: user.id, // 当前登录账户的id Long 必填
       altMchName: '', // 分账方名称; string 必填
       altMchNo: '', // 分账方账号; string	必填
@@ -548,7 +570,7 @@ export default {
       loginName: '', // 分账方登录名,即邮箱;	string
     });
     // 汇付字段
-    let huifuParams = reactive({
+    const huifuParams = reactive({
       id: null,
       adminId: user.id, // 当前登录账户的id
       type: '0', // 类型 String 必填 企业:type='1'; 个人:type='0'
@@ -585,6 +607,7 @@ export default {
       certBeginDate: '', // 有效期开始日期
       certEndDate: '', // 有效期截止日期
       sms: '', // 验证码
+      settType: 1, // 结算方式 * 1 由汇聚自动结算 * 2 由商户平台手工结算(结算接口);	integer(int32)	默认填1
     });
     let cardPositiveList = ref([]);
     let cardNegativeList = ref([]);
@@ -615,6 +638,7 @@ export default {
     // 日期选择
     // 身份证有效开始日期
     const onConfirmBeginDate = ({ selectedValues }) => {
+      beginDate.value = selectedValues.join("-");
       addParams.beginDate = selectedValues.join("-");
       huifuParams.certBeginDate = selectedValues.join("");
       showBeginDate.value = false;
@@ -622,6 +646,7 @@ export default {
     };
     // 身份证有效截止日期
     const onConfirmEndDate = ({ selectedValues }) => {
+      endDate.value = selectedValues.join("-");
       addParams.endDate = selectedValues.join("-");
       huifuParams.certEndDate = selectedValues.join("");
       showEndDate.value = false;
@@ -629,6 +654,7 @@ export default {
     };
     // 营业执照有效开始日期
     const onConfirmEndDateLicense = ({ selectedValues }) => {
+      endDateLicense.value = selectedValues.join("-");
       addParams.endDateLicense = selectedValues.join("-");
       huifuParams.licenseEndDate = selectedValues.join("");
       showEndDateLicense.value = false;
@@ -636,6 +662,7 @@ export default {
     };
     // 营业执照有效截止日期
     const onConfirmBeginDateLicense = ({ selectedValues }) => {
+      beginDateLicense.value = selectedValues.join("-");
       addParams.beginDateLicense = selectedValues.join("-");
       huifuParams.licenseBeginDate = selectedValues.join("");
       showBeginDateLicense.value = false;
@@ -644,7 +671,7 @@ export default {
     // 地址选择
     const onConfirmBankAddress = ({ selectedOptions }) => {
       showBankAddress.value = false;
-      addParams.bankAddress = (selectedOptions[0]?.text != selectedOptions[1]?.text ? selectedOptions[0]?.text : '')
+      bankAddress.value = (selectedOptions[0]?.text != selectedOptions[1]?.text ? selectedOptions[0]?.text : '')
         + selectedOptions[1]?.text;
       huifuParams.cardProvId = selectedOptions[0]?.value || '';
       huifuParams.cardAreaId = selectedOptions[1]?.value || '';
@@ -652,7 +679,7 @@ export default {
     };
     const onConfirmReAddress = ({ selectedOptions }) => {
       showReAddress.value = false;
-      addParams.registeredAddress = (selectedOptions[0]?.text != selectedOptions[1]?.text ? selectedOptions[0]?.text : '')
+      registeredAddress.value = (selectedOptions[0]?.text != selectedOptions[1]?.text ? selectedOptions[0]?.text : '')
         + selectedOptions[1]?.text + selectedOptions[2]?.text;
       huifuParams.regProvId = selectedOptions[0]?.value || '';
       huifuParams.regAreaId = selectedOptions[1]?.value || '';
@@ -667,7 +694,6 @@ export default {
       verCodeTime.time = getLocal('registerVerCodeTime');
       if (huifuMchID.value == null) {
         huifuPicUpStatus.value = 1;
-        console.log(huifuPicUpStatus.value);
       }
       if (verCodeTime.time && verCodeTime.time !== '') {
         verCodeTime.time = parseInt(verCodeTime.time);
@@ -677,6 +703,7 @@ export default {
       } else {
         verCodeTime.time = 0;
       }
+      console.log(addParams.beginDate);
     });
     // 获取汇聚账号回显
     const getOneJoinPayMchFun = async () => {
@@ -720,7 +747,7 @@ export default {
           addParams.licenseExpiry = dateUtil.formateDate(new Date(data.data.licenseExpiry), "yyyy-MM-dd");
         }
 
-        addParams.settMode = data.data.settMode ? data.data.settMode.toString() : '';
+        addParams.settMode = data.data.settMode ? data.data.settMode : 1;
         addParams.settDateType = data.data.settDateType ? data.data.settDateType.toString() : '';
         addParams.riskDay = data.data.riskDay;
         addParams.manageScope = data.data.manageScope;
@@ -758,12 +785,17 @@ export default {
           addParams.manageAddr = areaList.province_list[data.data.provId] + areaList.city_list[data.data.areaId] + areaList.county_list[data.data.districtId];
           huifuMchNO.value = data.data.huifuId;
           addParams.validityType = data.data.certValidityType;
-          addParams.beginDate = dateUtil.formatDate(data.data.certBeginDate);
-          addParams.endDate = dateUtil.formatDate(data.data.certEndDate);
+          if (data.data.certBeginDate != null && data.data.certBeginDate != "") {
+            beginDate.value = dateUtil.formatDate(data.data.certBeginDate);
+          }
+          if (data.data.certEndDate != null && data.data.certEndDate != "") {
+            endDate.value = dateUtil.formatDate(data.data.certEndDate);
+          }
           huifuParams.cardProvId = data.data.cardProvId;
           huifuParams.cardAreaId = data.data.cardAreaId;
           huifuParams.detailAddr = data.data.detailAddr;
-          addParams.bankAddress = areaList.province_list[data.data.cardProvId] == areaList.city_list[data.data.cardAreaId] ? areaList.province_list[data.data.cardProvId] :
+          huifuParams.settType = data.data.settType;
+          bankAddress.value = areaList.province_list[data.data.cardProvId] == areaList.city_list[data.data.cardAreaId] ? areaList.province_list[data.data.cardProvId] :
             (areaList.province_list[data.data.cardProvId] + areaList.city_list[data.data.cardAreaId]);
           if (data.data.cardFrontPic != null && data.data.legalCertBackPic != null && data.data.legalCertFrontPic) {
             huifuPicUpStatus.value = 1;
@@ -772,7 +804,7 @@ export default {
             addParams.altMerchantType = "12";
             addParams.regNameValue = data.data.regName;
             addParams.shortNameValue = data.data.shortName;
-            addParams.registeredAddress = areaList.province_list[data.data.regProvId] == areaList.city_list[data.data.regAreaId] ? (areaList.city_list[data.data.regAreaId] + areaList.county_list[data.data.regDistrictId]) :
+            registeredAddress.value = areaList.province_list[data.data.regProvId] == areaList.city_list[data.data.regAreaId] ? (areaList.city_list[data.data.regAreaId] + areaList.county_list[data.data.regDistrictId]) :
               (areaList.province_list[data.data.regProvId] + areaList.city_list[data.data.regAreaId] + areaList.county_list[data.data.regDistrictId]);
             huifuParams.regProvId = data.data.regProvId;
             huifuParams.regAreaId = data.data.regAreaId;
@@ -786,8 +818,12 @@ export default {
               addParams.bankChannelNo = data.data.branchCode;
             }
             addParams.validityType1 = data.data.licenseValidityType;
-            addParams.beginDateLicense = dateUtil.formatDate(data.data.licenseBeginDate);
-            addParams.endDateLicense = dateUtil.formatDate(data.data.licenseEndDate);
+            if (data.data.licenseBeginDate != null && data.data.licenseBeginDate != "") {
+              beginDateLicense.value = dateUtil.formatDate(data.data.licenseBeginDate);
+            }
+            if (data.data.licenseEndDate != null && data.data.licenseEndDate != "") {
+              endDateLicense.value = dateUtil.formatDate(data.data.licenseEndDate);
+            }
             if (data.data.licensePic != null && data.data.certBackPic != null && data.data.certFrontPic != null && data.data.regAcctPic != null) {
               huifuPicUpStatus.value = 1;
             }
@@ -824,22 +860,6 @@ export default {
         });
       }
     };
-    // 发送验证码
-    const sendCode = async () => {
-      const { data } = await sendSms({
-        adminId: user.id,
-      });
-      if (data.code === '00000') {
-        showToast({
-          duration: 2000,
-          message: t('huifuMch.successSend') + '\n' + maskPhoneNumber(data.data.phone)
-        });
-        verCodeTime.time = 60;
-        verCodeTimeInterval();
-      } else {
-        showFailToast(data.message);
-      }
-    }
     // 格式手机号码
     const maskPhoneNumber = (value) => {
       const prefix = value.slice(0, 3);
@@ -895,6 +915,7 @@ export default {
           huifuParams.certAddress = addParams.certAddressValue
         }
       }
+      huifuParams.settType = params.settMode;
       try {
         const { data } = await saveJoinPayMch(addParams);
         if (data.code === "00000") {
@@ -1035,112 +1056,7 @@ export default {
 
     // 文件上传
     const afterRead = async (file) => {
-      file.status = 'uploading';
-      file.message = '上传中...';
-      const params = {
-        adminId: user.id,
-        base64Str: null,
-        fileType: null,
-      };
-      // 人像面
-      if (cardNegativeList.value.length > 0 && uploadCertFront.value === 0) {
-        params.base64Str = cardNegativeList.value[0].content;
-        if (addParams.bankAccountType === '1') {
-          params.fileType = "F40";
-        } else {
-          params.fileType = "F02";
-        }
-        try {
-          const { data } = await newUploadPic(params);
-          if (data.code == "00000") {
-            file.status = 'done';
-            uploadCertFront.value = 1;
-          } else {
-            file.status = 'failed';
-            file.message = '上传失败';
-          }
-        } catch {
-          file.status = 'failed';
-          file.message = '上传失败';
-        }
-      }
-      // 国徽面
-      if (cardPositiveList.value.length > 0 && uploadCertBack.value === 0) {
-        params.base64Str = cardPositiveList.value[0].content;
-        if (addParams.bankAccountType === '1') {
-          params.fileType = "F41";
-        } else {
-          params.fileType = "F03";
-        }
-        try {
-          const { data } = await newUploadPic(params);
-          if (data.code == "00000") {
-            file.status = 'done';
-            uploadCertBack.value = 1;
-          } else {
-            file.status = 'failed';
-            file.message = '上传失败';
-          }
-        } catch {
-          file.status = 'failed';
-          file.message = '上传失败';
-        }
-      }
-      // 结算卡
-      if (statementCard.value.length > 0 && uploadCard.value === 0) {
-        params.base64Str = statementCard.value[0].content;
-        params.fileType = "F13";
-        try {
-          console.log(params.fileType);
-          const { data } = await newUploadPic(params);
-          if (data.code == "00000") {
-            file.status = 'done';
-            uploadCard.value = 1;
-          } else {
-            file.status = 'failed';
-            file.message = '上传失败';
-          }
-        } catch {
-          file.status = 'failed';
-          file.message = '上传失败';
-        }
-      }
-      // 营业执照
-      if (tradeLicenceList.value.length > 0 && tradeLicenceStatus.value === 0) {
-        params.base64Str = tradeLicenceList.value[0].content;
-        params.fileType = "F07";
-        try {
-          const { data } = await newUploadPic(params);
-          if (data.code == "00000") {
-            file.status = 'done';
-            tradeLicenceStatus.value = 1;
-          } else {
-            file.status = 'failed';
-            file.message = '上传失败';
-          }
-        } catch {
-          file.status = 'failed';
-          file.message = '上传失败';
-        }
-      }
-      // 开户许可证
-      if (openAccountLicenceList.value.length > 0 && accountLicenceStatus.value === 0) {
-        params.base64Str = openAccountLicenceList.value[0].content;
-        params.fileType = "F08";
-        try {
-          const { data } = await newUploadPic(params);
-          if (data.code == "00000") {
-            file.status = 'done';
-            accountLicenceStatus.value = 1;
-          } else {
-            file.status = 'failed';
-            file.message = '上传失败';
-          }
-        } catch {
-          file.status = 'failed';
-          file.message = '上传失败';
-        }
-      }
+      console.log(file);
     }
     // 删除时改变上传状态
     const deleteCertFront = () => {
@@ -1212,7 +1128,6 @@ export default {
       onConfirmEndDateLicense,
       onConfirmBeginDateLicense,
       huifuMchNO,
-      sendCode,
       maskPhoneNumber,
       verCodeTimeInterval,
       verCodeTime,
@@ -1224,7 +1139,14 @@ export default {
       showPopover,
       regNameVisible,
       shortNameVisible,
-      popoverVisible
+      popoverVisible,
+
+      beginDate,
+      endDate,
+      beginDateLicense,
+      endDateLicense,
+      bankAddress,
+      registeredAddress,
     };
   },
 };

+ 0 - 9
src/views/taskMessage/joinpayMchCheck/info/index.less

@@ -1,9 +0,0 @@
-.joinpayMchCheckPage {
-  width: 100%;
-
-  .joinpayMchCheckBox {
-    width: 100%;
-    height: calc(100% - 44px);
-    overflow: auto;
-  }
-}

+ 0 - 389
src/views/taskMessage/joinpayMchCheck/info/index.vue

@@ -1,389 +0,0 @@
-<template>
-  <!-- 提现账号 -->
-  <div class="joinpayMchCheckPage flex-col">
-    <s-header :name="$t('taskMessage.joinpayMchCheck.withAccoDetail')" :noback="false"></s-header>
-    <div v-if="detailType == 0 && infoData" class="joinpayMchCheckBox flex-col">
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.merchantName') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.altMchName }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.merchantType') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.altMerchantType === 10 ? $t('taskMessage.joinpayMchCheck.personal') : '' }}
-            {{ infoData.altMerchantType === 11 ? $t('taskMessage.joinpayMchCheck.indivBusines') : '' }}
-            {{ infoData.altMerchantType === 12 ? $t('taskMessage.joinpayMchCheck.enterprise') : '' }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.contactName') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.busiContactName }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.indiOrPersName') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.legalPerson }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.indiOrPersPhone') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.phoneNo }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.indiOrPersPhoneIdCard') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.idCardNo }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.idCardValid') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.idCardExpiry }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.accountType') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.bankAccountType === '1' ? $t('taskMessage.joinpayMchCheck.debitCard') : '' }}
-            {{ infoData.bankAccountType === '4' ? $t('taskMessage.joinpayMchCheck.corporateAccount') : '' }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.bankAccountName') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.bankAccountName }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.bankAccount') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.bankAccountNo }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.interBankNo') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.bankChannelNo }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.settlMethod') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.settMode === '1' ? $t('taskMessage.joinpayMchCheck.autoSettByConvergence') : '' }}
-            {{ infoData.settMode === '2' ? $t('taskMessage.joinpayMchCheck.manuSettByMercPlatform') : '' }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.settlCycle') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.riskDay }}{{ $t('taskMessage.joinpayMchCheck.day') }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.businessNature') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.manageScope }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.businessAddress') }}:</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.manageAddr }}
-          </div>
-        </div>
-      </div>
-      <div v-if="isOper" class="itemRow" style="display: flex; justify-content: center; padding: 0.5rem;">
-        <van-button span="5" round type="primary"
-          style="height: 2em; padding: 0 2em; margin: 0 1em; background: rgb(255 0 0 / 20%); color: #ff0000; border-color: #ff0000;"
-          @click="changeStatusFun('3')">
-          {{ $t('taskMessage.refuse') }}
-        </van-button>
-        <van-button span="5" round type="primary"
-          style="height: 2em; padding: 0 2em; margin: 0 1em; background: rgb(25 137 250 / 20%); color: #1989fa;"
-          @click="changeStatusFun('1')">
-          {{ $t('taskMessage.agree') }}
-        </van-button>
-      </div>
-    </div>
-    <div v-if="detailType == 1 && infoData" class="joinpayMchCheckBox flex-col">
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.merchantID') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.adminId }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.merchantType') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.type == 0 ? $t('taskMessage.joinpayMchCheck.personal') :
-              $t('taskMessage.joinpayMchCheck.enterprise') }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.merchantName') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.regName }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.shortName') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.shortName }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.contactName') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.name }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.phone') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.phone }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.email') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.email }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.certNo') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.certNo }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.cardName') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.cardName }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.bankAccount') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.cardNo }}
-          </div>
-        </div>
-      </div>
-      <div class="van-cell van-field">
-        <div class="van-cell__title van-field__label">
-          <label for="van-field-3-input">{{ $t('taskMessage.joinpayMchCheck.mp') }}</label>
-        </div>
-        <div class="van-cell__value van-field__value">
-          <div class="van-field__body">
-            {{ infoData.mp }}
-          </div>
-        </div>
-      </div>
-      <div v-if="isOper && (infoData.status == '1' || infoData.status == '4')" class="itemRow"
-        style="display: flex; justify-content: center; padding: 0.5rem;">
-        <van-button span="5" round type="primary"
-          style="height: 2em; padding: 0 2em; margin: 0 1em; background: rgb(255 0 0 / 20%); color: #ff0000; border-color: #ff0000;"
-          @click="changeStatusFun('3')">
-          {{ $t('taskMessage.refuse') }}
-        </van-button>
-        <van-button span="5" round type="primary"
-          style="height: 2em; padding: 0 2em; margin: 0 1em; background: rgb(25 137 250 / 20%); color: #1989fa; border-color: #1989fa;"
-          @click="changeStatusFun('1')">
-          {{ $t('taskMessage.agree') }}
-        </van-button>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import { getLoginUser } from "@/common/js/utils";
-import { showFailToast, showSuccessToast } from "vant";
-import { onMounted, ref } from 'vue';
-import { useRoute, useRouter } from "vue-router";
-import sHeader from "@/components/SimpleHeader";
-import { gettJoinpayMchCheckInfo, changetJoinpayMchCheckStatus, auditAddMerchant, auditUpdateMerchant } from "@/service/taskMessage";
-import { useI18n } from "vue-i18n";
-
-export default {
-  components: { sHeader },
-  setup() {
-    // 引入语言
-    const { t } = useI18n();
-    // 获取用户信息
-    const user = getLoginUser();
-    const route = useRoute();
-    const router = useRouter();
-    let infoId = '';
-    let infoType = '';
-    let infoData = ref(null);
-    // 是汇聚还是杉德 0 汇聚 1杉德
-    const detailType = ref(0);
-    // 是否有操作的权限
-    const isOper = ref(true);
-    // 初始化页面获取列表
-    onMounted(async () => {
-      infoId = route.query.infoId;
-      infoType = route.query.infoType;
-      // 根据路由参数赋值
-      detailType.value = infoType || '';
-      getInfoData();
-      // 如果是type大于1,那么不能有操作的权限
-      if (user.type > 1) {
-        isOper.value = false;
-      }
-    });
-    const getInfoData = async () => {
-      const { data } = await gettJoinpayMchCheckInfo({ id: infoId, type: infoType });
-      if (data.code === '00000') {
-        infoData.value = data.data;
-      } else { showFailToast(data.message); }
-      console.log('getInfoData', infoData);
-      console.log(infoData.value.status);
-    }
-    const changeStatusFun = async (status) => {
-      if (detailType.value == 0) {
-        const { data } = await changetJoinpayMchCheckStatus({ type: infoType, id: infoId, status: status, });
-        if (data.code === '00000') {
-          showSuccessToast(data.message);
-          router.push({ path: '/taskJoinPayMchCheck' })
-        } else { showFailToast(data.message); }
-      } else {
-        // 商户入驻
-        if (infoData.value.status == '1') {
-          const { data } = await auditAddMerchant({ id: infoId, status: status, });
-          if (data.code === '00000') {
-            showSuccessToast(t('taskMessage.joinpayMchCheck.successful'));
-            setTimeout(() => {
-              router.go(-1);
-            }, 1500);
-          } else { showFailToast(data.message); }
-        } else if (infoData.value.status == '4') {
-          // 商户修改
-          const { data } = await auditUpdateMerchant({ id: infoId, status: status, });
-          if (data.code === '00000') {
-            showSuccessToast(t('taskMessage.joinpayMchCheck.successful'));
-            setTimeout(() => {
-              router.go(-1);
-            }, 1500);
-          } else { showFailToast(data.message); }
-        }
-      }
-    }
-    return {
-      infoData,
-      changeStatusFun,
-      detailType,
-      isOper,
-    };
-  },
-};
-</script>
-
-<style lang="less" scoped>
-@import "../../../../common/style/common.less";
-@import "./index.less";
-</style>

+ 8 - 24
src/views/user.vue

@@ -70,13 +70,6 @@
               <van-icon name="edit" class="editIcon" @click="editClk(2)" />
             </div>
           </div>
-          <!-- 上级账号 -->
-          <div v-if="isInland && user.type == '2'">
-            <div v-if="haveRelation" class="userInfo l-flex-between">
-              <span class="userInfoLeft">{{ $t("user.superiorAccount") }}: </span>
-              <span>{{ relationAdminName }}</span>
-            </div>
-          </div>
           <!-- 手机号码 -->
           <div v-if="user.type != '0'">
             <div v-if="!phoneNumberShow" class="userInfo l-flex-between">
@@ -198,12 +191,18 @@
           </div>
 
           <!-- 提现帐号 -->
-          <div v-if="isInland && (user.type == 2 || user.type == 3)" class="taskListRow l-flex-RC"
+          <!-- <div v-if="isInland && (user.type == 2 || user.type == 3)" class="taskListRow l-flex-RC"
             @click="pushPageList('/settlement')">
             <div class="taskIcon joinPayMchIcon"></div>
             <div class="taskRight">
               <div class="taskTitle">{{ $t("user.settlementAccount") }}</div>
             </div>
+          </div> -->
+          <div v-if="isInland && (user.type == 2 || user.type == 3)" class="taskListRow l-flex-RC" @click="pushPageList('/purse')">
+            <div class="taskIcon joinPayMchIcon"></div>
+            <div class="taskRight">
+              <div class="taskTitle">钱包</div>
+            </div>
           </div>
           <!-- 绑定微信 -->
           <div v-if="isInWeChat" class="taskListRow l-flex-RC" @click="pushPageList('/bindWechat')">
@@ -248,14 +247,6 @@
         </div>
       </div>
     </div>
-    <!-- 退出登录弹窗 -->
-    <kDialog :dialogTitle="$t('user.logOutTips')" :cancelBtnTxt="$t('user.cancelLog')"
-      :confirmBtnTxt="$t('user.confirmLog')" ref="kDialogRef" :dialogContent="$t('user.logOutContent')"
-      @confirmclk="confirmClk">
-    </kDialog>
-    <!-- 地区弹窗 -->
-    <!-- <kCascader @getareaname="getAreaName" :selectId="accountDetail.areaId" @areapopfinish="areaPopFinish"
-      ref="kCascaderRef"></kCascader> -->
     <!-- 时区弹窗 -->
     <kTimezone @gettimezone="getTimezone" :selectId="accountDetail.timezone" @timezonepopfinish="timezonePopFinish"
       ref="kTimezoneRef"></kTimezone>
@@ -278,15 +269,11 @@
 </template>
 
 <script>
-// 导入地区弹窗
-// import kCascader from "@/components/commom/kCascader/index.vue";
 // 导入时区弹窗
 import kTimezone from "@/components/commom/kTimezone/index.vue";
 // 导入接口
 import { getAdmin } from "@/service/merchantManage";
 import { updateAdmin } from "@/service/merchantManage";
-// 引入弹窗
-import kDialog from "@/components/commom/kDialog/index.vue";
 import { onMounted, reactive, ref } from "vue";
 import sHeader from "@/components/SimpleHeader";
 import {
@@ -305,7 +292,7 @@ import { countriesDataEn } from '@/common/js/countries-en';
 import { useCascaderAreaData } from '@vant/area-data';
 
 export default {
-  components: { sHeader, kDialog, kTimezone },
+  components: { sHeader, kTimezone },
   setup() {
     let languageName = ref(getLocal("curLang"));
     // 引入语言
@@ -537,8 +524,6 @@ export default {
         }
       });
     };
-    // 退出登录弹窗
-    const kDialogRef = ref(null);
     // 点击右侧按钮
     const confirmClk = () => {
       // 获取缓存的语言
@@ -948,7 +933,6 @@ export default {
       pushPageList,
       roleCheck,
       sys,
-      kDialogRef,
       confirmClk,
       mailboxShow,
       mailboxChg,

+ 19 - 5
vue.config.js

@@ -4,14 +4,28 @@ module.exports = {
   publicPath: "/sc",
   assetsDir: 'static',
   css: {
-    extract: false
+    // extract: false
+    extract:
+      process.env.NODE_ENV === "production"
+        ? {
+            filename: `css/[name].${version}.css`,
+            chunkFilename: `css/[name].${version}.css`,
+          }
+        : false,
   },
-  filenameHashing: false,
+  filenameHashing: true,
   configureWebpack: {
     output: {
-      filename: `js/[name].${version}.js`,
-      chunkFilename: `js/[name].${version}.js`
-    }
+      // 动态文件名配置
+      filename:
+        process.env.NODE_ENV === "production"
+          ? `js/[name].[contenthash:8].${version}.js`
+          : "js/[name].js",
+      chunkFilename:
+        process.env.NODE_ENV === "production"
+          ? `js/[name].[contenthash:8].${version}.js`
+          : "js/[name].js",
+    },
   },
   devServer: {
     open: true,