Selaa lähdekoodia

feat:"优化绑卡流程,增加乐摇摇东南亚支付配置功能"

soobin 1 kuukausi sitten
vanhempi
commit
6bf256bf65

+ 1 - 0
package.json

@@ -13,6 +13,7 @@
   "dependencies": {
     "@airwallex/payouts-web-sdk": "^1.3.0",
     "@amap/amap-jsapi-loader": "^1.0.1",
+    "@googlemaps/js-api-loader": "^1.16.8",
     "@tinymce/tinymce-vue": "^4.0.7",
     "@vant/area-data": "^1.5.0",
     "@vant/compat": "^1.0.0",

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


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

@@ -724,7 +724,8 @@
     "discountCannotBeGreaterThan": "Max 10% off",
     "deductionRollNoZero": "Amount > 0",
     "successfulProductionOfDiscountCode": "Applied",
-    "applDiscCode": "New Code"
+    "applDiscCode": "New Code",
+    "exportTips": "Batch export for datasets over 5,000 entries"
   },
   "distributionSet": {
     "distributionSettings": "Distribution",
@@ -1455,7 +1456,7 @@
     "emailCodePlaceholder": "Enter code",
     "emailCodeRequired": "Required",
     "invitationCode": "Invite Code",
-    "invitationCodePlaceholder": "Enter code",
+    "invitationCodePlaceholder": "Enter invite Code",
     "registerButton": "Register",
     "replaysInSeconds": "s resend",
     "emailRegistration": "Email Signup",
@@ -1860,6 +1861,7 @@
     "C28": "Edit Payment Method",
     "C29": "Tax Administration",
     "C30": "Jam Extraction",
-    "C31": "Maintenance Details"
+    "C31": "Maintenance Details",
+    "C32": "Payment Configuration"
   }
 }

+ 5 - 3
src/assets/language/es.json

@@ -724,7 +724,8 @@
         "discountCannotBeGreaterThan": "Máx. 10% descuento",
         "deductionRollNoZero": "Mín. 1€",
         "successfulProductionOfDiscountCode": "Códigos generados",
-        "applDiscCode": "Solicitar códigos"
+        "applDiscCode": "Solicitar códigos",
+        "exportTips": "Exportación por lotes para más de 5000 registros"
     },
     "distributionSet": {
         "distributionSettings": "Distribución",
@@ -1454,7 +1455,7 @@
         "emailCodePlaceholder": "Ej: ABCD12",
         "emailCodeRequired": "Requerido",
         "invitationCode": "Código invitación",
-        "invitationCodePlaceholder": "Ej: INV-2023",
+        "invitationCodePlaceholder": "Código invitación",
         "registerButton": "Registrar",
         "replaysInSeconds": "Reintentar en X seg.",
         "emailRegistration": "Registro por email",
@@ -1859,6 +1860,7 @@
         "C28": "Cambiar pago",
         "C29": "Gestión Tributaria",
         "C30": "Extracción de Mermelada",
-        "C31": "Detalles de Mantenimiento"
+        "C31": "Detalles de Mantenimiento",
+        "C32": "Configuración de pagos"
     }
 }

+ 5 - 3
src/assets/language/fr.json

@@ -724,7 +724,8 @@
         "discountCannotBeGreaterThan": "Remise ≤ 90%",
         "deductionRollNoZero": "Montant > 0",
         "successfulProductionOfDiscountCode": "Code généré",
-        "applDiscCode": "Générer code promo"
+        "applDiscCode": "Générer code promo",
+        "exportTips": "Export par lots au-delà de 5000 données"
     },
     "distributionSet": {
         "distributionSettings": "Param. distribution",
@@ -1485,7 +1486,7 @@
         "emailCodePlaceholder": "Code reçu par email",
         "emailCodeRequired": "Code requis",
         "invitationCode": "Code d'invitation",
-        "invitationCodePlaceholder": "Code facultatif",
+        "invitationCodePlaceholder": "Code d'invitation",
         "registerButton": "Valider",
         "replaysInSeconds": "s avant renvoi",
         "emailRegistration": "Inscription par email",
@@ -1890,6 +1891,7 @@
         "C28": "Modifier paiement",
         "C29": "Gestion Fiscale",
         "C30": "Extraction de Confiture",
-        "C31": "Détails de la maintenance"
+        "C31": "Détails de la maintenance",
+        "C32": "Configuration de paiement"
     }
 }

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

@@ -718,7 +718,8 @@
         "discountCannotBeGreaterThan": "割引は10を超えてはいけません",
         "deductionRollNoZero": "割り引き価格は0にできません",
         "successfulProductionOfDiscountCode": "ディスカウントコードの申請に成功",
-        "applDiscCode": "ディスカウントコードを申請"
+        "applDiscCode": "ディスカウントコードを申請",
+        "exportTips": "5000件以上のデータは一括エクスポート"
     },
     "distributionSet": {
         "distributionSettings": "分配設定",
@@ -1448,7 +1449,7 @@
         "emailCodePlaceholder": "メール認証コードを入力してください",
         "emailCodeRequired": "メール認証コードを入力してください",
         "invitationCode": "招待コードです",
-        "invitationCodePlaceholder": "招待コードの入力をお願いします",
+        "invitationCodePlaceholder": "招待コードす",
         "registerButton": "登録する",
         "replaysInSeconds": "数秒後に再送信できます",
         "emailRegistration": "メールでの登録",
@@ -1851,6 +1852,7 @@
         "C28": "支払い方法変更",
         "C29": "税務管理",
         "C30": "ジャム抽出",
-        "C31": "メンテナンス記録"
+        "C31": "メンテナンス記録",
+        "C32": "決済設定"
     }
 }

+ 5 - 3
src/assets/language/pt.json

@@ -724,7 +724,8 @@
         "discountCannotBeGreaterThan": "Desconto máx. 10%",
         "deductionRollNoZero": "Valor deve ser > 0",
         "successfulProductionOfDiscountCode": "Cupons gerados",
-        "applDiscCode": "Solicitar Cupons"
+        "applDiscCode": "Solicitar Cupons",
+        "exportTips": "Exportação em lote acima de 5000 registros"
     },
     "distributionSet": {
         "distributionSettings": "Configurações de Distribuição",
@@ -1454,7 +1455,7 @@
         "emailCodePlaceholder": "Ex: ABCD12",
         "emailCodeRequired": "Digite o código",
         "invitationCode": "Código de Convite",
-        "invitationCodePlaceholder": "Ex: CONVITE2023",
+        "invitationCodePlaceholder": "Código de Convite",
         "registerButton": "Cadastrar",
         "replaysInSeconds": " segundos",
         "emailRegistration": "Cadastro por E-mail",
@@ -1859,6 +1860,7 @@
         "C28": "Alterar pagamento",
         "C29": "Gestão Tributária",
         "C30": "Extração de Geleia",
-        "C31": "Registros de Manutenção"
+        "C31": "Registros de Manutenção",
+        "C32": "Configuração de pagamento"
     }
 }

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

@@ -724,7 +724,8 @@
         "discountCannotBeGreaterThan": "Макс. 10%",
         "deductionRollNoZero": "Сумма > 0",
         "successfulProductionOfDiscountCode": "Успешно",
-        "applDiscCode": "Создать купон"
+        "applDiscCode": "Создать купон",
+        "exportTips": "Пакетный экспорт для данных свыше 5000 записей"
     },
     "distributionSet": {
         "distributionSettings": "Дистрибуция",
@@ -1485,7 +1486,7 @@
         "emailCodePlaceholder": "Введите код",
         "emailCodeRequired": "Обязательное поле",
         "invitationCode": "Код приглашения",
-        "invitationCodePlaceholder": "Введите код",
+        "invitationCodePlaceholder": "Код приглашения",
         "registerButton": "Зарегистрироваться",
         "replaysInSeconds": "Повтор через {n} сек.",
         "emailRegistration": "Регистрация по email",
@@ -1890,6 +1891,7 @@
         "C28": "Изменить оплату",
         "C29": "Управление налогообложением",
         "C30": "Экстракция джема",
-        "C31": "Журнал обслуживания"
+        "C31": "Журнал обслуживания",
+        "C32": "Настройка платежей"
     }
 }

+ 5 - 3
src/assets/language/uk.json

@@ -724,7 +724,8 @@
         "discountCannotBeGreaterThan": "Знижка ≤10",
         "deductionRollNoZero": "Сума >0",
         "successfulProductionOfDiscountCode": "Успішно створено",
-        "applDiscCode": "Запит промокодів"
+        "applDiscCode": "Запит промокодів",
+        "exportTips": "Пакетне експортування при понад 5000 записів"
     },
     "distributionSet": {
         "distributionSettings": "Налаштування дистрибуції",
@@ -1455,7 +1456,7 @@
         "emailCodePlaceholder": "Введіть код",
         "emailCodeRequired": "Введіть код",
         "invitationCode": "Інвайт-код",
-        "invitationCodePlaceholder": "Введіть код запрошення",
+        "invitationCodePlaceholder": "Інвайт-код",
         "registerButton": "Зареєструватися",
         "replaysInSeconds": "Повторно через (сек)",
         "emailRegistration": "Через пошту",
@@ -1860,6 +1861,7 @@
         "C28": "Змінити оплату",
         "C29": "Управління оподаткуванням",
         "C30": "Витяг джему",
-        "C31": "Журнал обслуговування"
+        "C31": "Журнал обслуговування",
+        "C32": "Налаштування платежів"
     }
 }

+ 4 - 2
src/assets/language/zh.json

@@ -733,7 +733,8 @@
     "discountCannotBeGreaterThan": "折扣不能大于10",
     "deductionRollNoZero": "立减价格不能为0",
     "successfulProductionOfDiscountCode": "申请成功",
-    "applDiscCode": "申请优惠码"
+    "applDiscCode": "申请优惠码",
+    "exportTips": "5000条数据以上分批导出"
   },
   "distributionSet": {
     "distributionSettings": "分销设置",
@@ -1869,6 +1870,7 @@
     "C28": "修改支付方式",
     "C29": "税收管理",
     "C30": "果酱抽取",
-    "C31": "维护记录"
+    "C31": "维护记录",
+    "C32": "支付配置"
   }
 }

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

@@ -58,7 +58,10 @@ export const remoteMenus = {
   "C26": t("remote.C26"),
   "C27": t("remote.C27"),
   "C28": t("remote.C28"),
-  "C29": t("remote.C29")
+  "C29": t("remote.C29"),
+  "C30": t("remote.C30"),
+  "C31": t("remote.C31"),
+  "C32": t("remote.C32"),
 }
 // 判断值是否是数字 true:数值型的,false:非数值型
 export const $M_IsNaN = (num) => {

+ 17 - 3
src/router/index.js

@@ -218,9 +218,16 @@ const router = createRouter({
     },
     // 结算账号
     {
-      path: "/bindBankCard",
-      name: "bindBankCard",
-      component: () => import("@/views/bindBankCard/index"),
+      path: "/joinPayBind",
+      name: "joinPayBind",
+      component: () => import("@/views/bindBankCard/joinPayBind.vue"),
+      meta: { index: 1 },
+    },
+    // 结算账号
+    {
+      path: "/huifuBind",
+      name: "huifuBind",
+      component: () => import("@/views/bindBankCard/huifuBind.vue"),
       meta: { index: 1 },
     },
     // 公告编辑
@@ -547,6 +554,13 @@ const router = createRouter({
       component: () => import("@/views/device/maintenance/index"),
       meta: { index: 1 },
     },
+    // 支付配置
+    {
+      path: "/payInfo",
+      name: "payInfo",
+      component: () => import("@/views/device/payInfo/index"),
+      meta: { index: 1 },
+    },
     // 修改机器密码
     {
       path: "/devicePassword",

+ 147 - 68
src/service/device/index.js

@@ -1,322 +1,401 @@
-import axios from '../../utils/axios';
-import { stringToUrl } from '@/common/js/utils';
-
+import axios from "../../utils/axios";
+import { stringToUrl } from "@/common/js/utils";
 
 // 获取设备列表
 export function getDeviceList(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/findList?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/findList?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 获取设备详情
 export function getDeviceDetal(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/findById?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/findById?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 获取花型种类下拉列表
 export function getGoodsNumber(params) {
-    return axios.get(`/SZWL-SERVER/tGoodsData/getGoodsNumber?${stringToUrl(params)}`);
+  return axios.get(
+    `/SZWL-SERVER/tGoodsData/getGoodsNumber?${stringToUrl(params)}`
+  );
 }
 
 // 修改设备详情
 export function updateDevice(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/update`, params);
+  return axios.post(`/SZWL-SERVER/tEquipment/update`, params);
 }
 
 // 消除报警
 export function eliminate(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/eliminate?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/eliminate?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 重启炉头/开启关闭炉头
 export function setFurnace(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/onOff?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/onOff?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 雪糕机机器复位
 export function machineReset(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/machineReset?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/machineReset?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 睡眠
 export function sleepEquipment(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/sleep?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/sleep?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 远程开门
 export function openDoor(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/openDoor?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/openDoor?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 新版远程开门,包含内门外门
 export function Api_openDoor(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/openDoors`, { params })
+  return axios.get(`/SZWL-SERVER/tEquipment/openDoors`, { params });
 }
 
 // 系统脱机
 export function deviceTuoji(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/tuoji?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/tuoji?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 音量调解
 export function updateVolume(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/updateVolume?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/updateVolume?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 获取商品下拉列表
 export function selectProducts(params) {
-    return axios.get(`/SZWL-SERVER/tProduct/selectProducts?${stringToUrl(params)}`);
+  return axios.get(
+    `/SZWL-SERVER/tProduct/selectProducts?${stringToUrl(params)}`
+  );
 }
 
 // 远程做糖
 export function doSugar(params) {
-    return axios.post(`/SZWL-SERVER/tSugarDo/doSugar`, params);
+  return axios.post(`/SZWL-SERVER/tSugarDo/doSugar`, params);
 }
 
 // 远程制作
 export function remoteProduction(params) {
-    return axios.post(`/SZWL-SERVER/tSugarDo/remoteProduction`, params);
+  return axios.post(`/SZWL-SERVER/tSugarDo/remoteProduction`, params);
 }
 
 // 查询做糖状态
 export function selectSugarStatus(params) {
-    return axios.get(`/SZWL-SERVER/tSugarDo/selectSugarStatus?${stringToUrl(params)}`);
+  return axios.get(
+    `/SZWL-SERVER/tSugarDo/selectSugarStatus?${stringToUrl(params)}`
+  );
 }
 
 // 今日做糖列表
 export function selectSugarList(params) {
-    return axios.get(`/SZWL-SERVER/tSugarDo/selectSugarList?${stringToUrl(params)}`);
+  return axios.get(
+    `/SZWL-SERVER/tSugarDo/selectSugarList?${stringToUrl(params)}`
+  );
 }
 
 // 远程制作列表
 export function selectMakeList(params) {
-    return axios.post(`/SZWL-SERVER/tSugarDo/selectSugarRecord`, params);
+  return axios.post(`/SZWL-SERVER/tSugarDo/selectSugarRecord`, params);
 }
 
 // 导出制作列表
 export function exportMakeList(params) {
-    return axios.post(`/SZWL-SERVER/tSugarDo/exportSugarRecord`, params, { responseType: 'blob' });
+  return axios.post(`/SZWL-SERVER/tSugarDo/exportSugarRecord`, params, {
+    responseType: "blob",
+  });
 }
 
 // 查询定时开关列表
 export function getAlaramClockList(params) {
-    return axios.get(`/SZWL-SERVER/tAlarmClock/list?${stringToUrl(params)}`);
+  return axios.get(`/SZWL-SERVER/tAlarmClock/list?${stringToUrl(params)}`);
 }
 
 // 查询设备闹钟列表
 export function getAlaramClockByDevice(params) {
-    return axios.get(`/SZWL-SERVER/tAlarmClock/getList?${stringToUrl(params)}`);
+  return axios.get(`/SZWL-SERVER/tAlarmClock/getList?${stringToUrl(params)}`);
 }
 
 // 新增闹钟
 export function addAlaramClock(params) {
-    return axios.post(`/SZWL-SERVER/tAlarmClock/add?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tAlarmClock/add?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 删除闹钟
 export function deleteAlaramClock(params) {
-    return axios.post(`/SZWL-SERVER/tAlarmClock/delete?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tAlarmClock/delete?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 闹钟回显
 export function getAlaramClock(params) {
-    return axios.post(`/SZWL-SERVER/tAlarmClock/selectOne?${stringToUrl(params)}`, params);
+  return axios.post(
+    `/SZWL-SERVER/tAlarmClock/selectOne?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 修改闹钟
 export function alaramClockUpdate(params) {
-    return axios.post(`/SZWL-SERVER/tAlarmClock/updata`, params);
+  return axios.post(`/SZWL-SERVER/tAlarmClock/updata`, params);
 }
 
 // 修改闹钟状态
 export function updateAlaramClockStatus(params) {
-    return axios.post(`/SZWL-SERVER/tAlarmClock/updataStatus`, params);
+  return axios.post(`/SZWL-SERVER/tAlarmClock/updataStatus`, params);
 }
 
 // 获取旗下的机器
 export function getListEquipment(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/listEquipment?${stringToUrl(params)}`)
+  return axios.get(
+    `/SZWL-SERVER/tEquipment/listEquipment?${stringToUrl(params)}`
+  );
 }
 
 // 设备充值
 export function rechargeAjax(params) {
-    return axios.get(`/SZWL-SERVER/tOrder/equipmentPay?${stringToUrl(params)}`)
+  return axios.get(`/SZWL-SERVER/tOrder/equipmentPay?${stringToUrl(params)}`);
 }
 
 // 获取参数设置
 export function getParameters(params) {
-    return axios.post(`/SZWL-SERVER/tParameters/getParameters`, params)
+  return axios.post(`/SZWL-SERVER/tParameters/getParameters`, params);
 }
 
 // 修改参数设置
 export function updateParameters(params) {
-    return axios.post(`/SZWL-SERVER/tParameters/updateParameters`, params)
+  return axios.post(`/SZWL-SERVER/tParameters/updateParameters`, params);
 }
 
 // 修改湿度区间参数
 export function humidityParameters(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/humidityParameters`, params)
+  return axios.post(`/SZWL-SERVER/tEquipment/humidityParameters`, params);
 }
 
 // 启用物料监控
 export function enableMaterial(params) {
-    return axios.post(`/SZWL-SERVER/tParameters/enableMaterial`, params)
+  return axios.post(`/SZWL-SERVER/tParameters/enableMaterial`, params);
 }
 
 // 分销人回显
 export function getProportion(params) {
-    return axios.post(`/SZWL-SERVER/tProportion/getOne?${stringToUrl(params)}`)
+  return axios.post(`/SZWL-SERVER/tProportion/getOne?${stringToUrl(params)}`);
 }
 
 // 提交审批或修改
 export function saveProportion(params) {
-    return axios.post(`/SZWL-SERVER/tProportion/save`, params)
+  return axios.post(`/SZWL-SERVER/tProportion/save`, params);
 }
 
 // 单个/批量修改商品价格
 export function Api_getUpdaProdPrice(params) {
-    return axios.get(`/SZWL-SERVER/tProduct/updateProduct`, { params })
+  return axios.get(`/SZWL-SERVER/tProduct/updateProduct`, { params });
 }
 
 // 一键补料
 export function Api_getReplenishment(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/buliao`, { params })
+  return axios.get(`/SZWL-SERVER/tEquipment/buliao`, { params });
 }
 
 // 远程
 export function Api_getTApkInfo_updateApk(params) {
-    return axios.get(`/SZWL-SERVER/tApkInfo/updateApk`, { params })
+  return axios.get(`/SZWL-SERVER/tApkInfo/updateApk`, { params });
 }
 
 // 修改优惠码开关状态
 export function Api_getDiscCodeStatus(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/updateCouponStatus`, { params })
+  return axios.get(`/SZWL-SERVER/tEquipment/updateCouponStatus`, { params });
 }
 
 // 修改睡眠描述
 export function changeSleepDesc(params) {
-    return axios.get(`/SZWL-SERVER/tEquipmentDesc/updateSleepDesc`, { params })
+  return axios.get(`/SZWL-SERVER/tEquipmentDesc/updateSleepDesc`, { params });
 }
 
 // 删除设备
 export function delOneDevice(params) {
-    return axios.post(`/SZWL-SERVER/tEquipmentDeleted/delOneDevice`, params)
+  return axios.post(`/SZWL-SERVER/tEquipmentDeleted/delOneDevice`, params);
 }
 
 // 屏蔽/显示商品
 export function updateProductsShow(params) {
-    return axios.post(`/SZWL-SERVER/tProduct/updateProductsShow`, params)
+  return axios.post(`/SZWL-SERVER/tProduct/updateProductsShow`, params);
 }
 
 // 新屏蔽/显示商品
 export function newUpdateProductsShow(params) {
-    return axios.post(`/SZWL-SERVER/tProduct/newUpdateProductsShow`, params)
+  return axios.post(`/SZWL-SERVER/tProduct/newUpdateProductsShow`, params);
 }
 
 // 远程修改机器密码
 export function updateDevicePassword(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/updatePassword`, params)
+  return axios.post(`/SZWL-SERVER/tEquipment/updatePassword`, params);
 }
 
 // 修改Logo
 export function newCustomLogo(params) {
-    return axios.get(`/SZWL-SERVER/tLogo/newCustomLogo?${stringToUrl(params)}`, params)
+  return axios.get(
+    `/SZWL-SERVER/tLogo/newCustomLogo?${stringToUrl(params)}`,
+    params
+  );
 }
 // 日志下载
 export function downloadLog(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/downloadLog?${stringToUrl(params)}`, { responseType: 'blob', timeout: 12000 });
+  return axios.get(
+    `/SZWL-SERVER/tEquipment/downloadLog?${stringToUrl(params)}`,
+    { responseType: "blob", timeout: 12000 }
+  );
 }
 
 // 获取DIY花型列表信息
 export function selectDIYFlowers(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/selectDIYFlowers?${stringToUrl(params)}`);
+  return axios.get(
+    `/SZWL-SERVER/tEquipment/selectDIYFlowers?${stringToUrl(params)}`
+  );
 }
 
 // 修改DIY花型功能开关状态
 export function updateDIYFlowerStatus(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/updateDIYFlowerStatus?${stringToUrl(params)}`);
+  return axios.get(
+    `/SZWL-SERVER/tEquipment/updateDIYFlowerStatus?${stringToUrl(params)}`
+  );
 }
 
 // 修改DIY花型的形状或是否显示
 export function updateDIYProductShow(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/updateDIYProductShow`, params);
+  return axios.post(`/SZWL-SERVER/tEquipment/updateDIYProductShow`, params);
 }
 
 // 获取设备清洗提醒开关状态
 export function getAlarmClean(clientId) {
-    return axios.get(`/SZWL-SERVER/tAlarmClean/getAlarmClean/${clientId}`);
+  return axios.get(`/SZWL-SERVER/tAlarmClean/getAlarmClean/${clientId}`);
 }
 
 // 修改设备清洗提醒开关状态
 export function updateAlarmCleanStatus(params) {
-    return axios.post(`/SZWL-SERVER/tAlarmClean/updateAlarmCleanStatus`, params);
+  return axios.post(`/SZWL-SERVER/tAlarmClean/updateAlarmCleanStatus`, params);
 }
 
 // 日志上传
 export function uploadLog(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/uploadLog?${stringToUrl(params)}`);
+  return axios.get(`/SZWL-SERVER/tEquipment/uploadLog?${stringToUrl(params)}`);
 }
 
 // 新日志上传
 export function newUploadLog(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/newUploadLog?${stringToUrl(params)}`);
+  return axios.get(
+    `/SZWL-SERVER/tEquipment/newUploadLog?${stringToUrl(params)}`
+  );
 }
 
 // 查询日志
 export function queryLog(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/queryLog?${stringToUrl(params)}`);
+  return axios.get(`/SZWL-SERVER/tEquipment/queryLog?${stringToUrl(params)}`);
 }
 
 // 远程锁机
 export function updateLockStatus(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/updateLockStatus`, { params })
+  return axios.get(`/SZWL-SERVER/tEquipment/updateLockStatus`, { params });
 }
 
 // 重启触摸屏
 export function restartScreen(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/openScreen`, { params })
+  return axios.get(`/SZWL-SERVER/tEquipment/openScreen`, { params });
 }
 
 // 远程切换雪糕机工作模式
 export function changeWorkingMode(params) {
-    return axios.get(`/SZWL-SERVER/tEquipment/updateWorkingMode`, { params })
+  return axios.get(`/SZWL-SERVER/tEquipment/updateWorkingMode`, { params });
 }
 
 // 修改睡眠描述
 export function changeCleanFunction(params) {
-    return axios.get(`/SZWL-SERVER/tEquipmentDesc/updateCleanFunction`, { params })
+  return axios.get(`/SZWL-SERVER/tEquipmentDesc/updateCleanFunction`, {
+    params,
+  });
 }
 
 // 获取机器开关机状态
 export function getOnOffStatus(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/onOffStatus?${stringToUrl(params)}`, params)
+  return axios.post(
+    `/SZWL-SERVER/tEquipment/onOffStatus?${stringToUrl(params)}`,
+    params
+  );
 }
 
 // 获取当天远程退币申请记录
 export function getReturnCoinList(params) {
-    return axios.get(`/SZWL-SERVER/returnCoinRecord/list`, { params })
+  return axios.get(`/SZWL-SERVER/returnCoinRecord/list`, { params });
 }
 
 // 获取当天远程退币申请记录
 export function returnCoinList(params) {
-    return axios.post(`/SZWL-SERVER/returnCoinRecord/getList`, params)
+  return axios.post(`/SZWL-SERVER/returnCoinRecord/getList`, params);
 }
 
 // 提交远程退币申请
 export function applyReturnCoin(params) {
-    return axios.post(`/SZWL-SERVER/returnCoinRecord/applyReturn`, params)
+  return axios.post(`/SZWL-SERVER/returnCoinRecord/applyReturn`, params);
 }
 
 // 修改税费开关状态
 export function updateTaxStatus(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/updateTaxSwitch`, params)
+  return axios.post(`/SZWL-SERVER/tEquipment/updateTaxSwitch`, params);
 }
 
 // 修改税率
 export function updateTaxRate(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/updateTaxRate`, params)
+  return axios.post(`/SZWL-SERVER/tEquipment/updateTaxRate`, params);
 }
 
 // 果酱抽取
 export function smokeJam(params) {
-    return axios.post(`/SZWL-SERVER/tEquipment/smokeJam`, params)
-}
+  return axios.post(`/SZWL-SERVER/tEquipment/smokeJam`, params);
+}
+
+// 修改支付方式
+export function updatePayment(params) {
+  return axios.post(`/SZWL-SERVER/tEquipment/updatePayment`, params);
+}
+
+// 获取支付配置
+export function getPayConfig(params) {
+  return axios.get(`/SZWL-SERVER/openPayInfo/getPayConfig?${stringToUrl(params)}`);
+}
+
+// 推送支付配置
+export function pushPayInfo(params) {
+  return axios.post(`/SZWL-SERVER/openPayInfo/pushPayInfo`, params);
+}

+ 2 - 2
src/service/discountCode/index.js

@@ -4,11 +4,11 @@ import { stringToUrl } from '@/common/js/utils';
 
 // 获取优惠码列表
 export function getdiscountCodeList(params) {
-  return axios.get(`/SZWL-SERVER/tPromoCode/pagePromoCode?${stringToUrl(params)}`);
+  return axios.post(`/SZWL-SERVER/tPromoCode/list`, params);
 }
 // 导出优惠码
 export function discountCodeExport(params) {
-  return axios.get(`/SZWL-SERVER/tPromoCode/export?${stringToUrl(params)}`, { responseType: 'blob' })
+  return axios.post(`/SZWL-SERVER/tPromoCode/exportList`, params, { responseType: 'blob' })
 }
 // 添加优惠码
 export function addCode(params) {

+ 0 - 5
src/service/huifuMch/index.js

@@ -12,11 +12,6 @@ export function openAccount(params) {
     return axios.get(`/SZWL-SERVER/tHuifuMch/openAccount?${stringToUrl(params)}`);
 }
 
-// 商户入驻申请
-export function saveHuifuMch(params) {
-    return axios.post(`/SZWL-SERVER/tHuifuMch/addMerchant`, params);
-}
-
 // 获取审核信息
 export function getHuifuMchCheck(params) {
     return axios.get(`/SZWL-SERVER/tHuifuMch/getHuifuMchCheck?${stringToUrl(params)}`);

+ 30 - 5
src/service/purse/index.js

@@ -36,7 +36,7 @@ export function idCardRecognition(params) {
   return axios.post(`/SZWL-SERVER/purse/ocrImage`, params);
 }
 
-// 获取商户信息
+// 汇聚获取商户信息
 export function getJoinPayMch(params) {
   return axios.post(`/SZWL-SERVER/tJoinpayMch/getOne?${stringToUrl(params)}`, params);
 }
@@ -51,12 +51,12 @@ export function uploadPhotos(params) {
   return axios.post(`/SZWL-SERVER/tJoinpayMch/uploadPhotos`, params);
 }
 
-// 更新图片审核情况
+// 汇聚更新图片审核情况
 export function updateApproveStatus(params) {
   return axios.post(`/SZWL-SERVER/tJoinpayMch/updateApproveStatus`, params);
 }
 
-// 签约
+// 汇聚签约
 export function altMchSign(params) {
   return axios.get(`/SZWL-SERVER/tJoinpayMch/altMchSign?${stringToUrl(params)}`);
 }
@@ -66,12 +66,37 @@ export function getPhotos(params) {
   return axios.get(`/SZWL-SERVER/purse/userLicense?${stringToUrl(params)}`);
 }
 
-// 更新商户认证状态
+// 汇聚更新商户认证状态
 export function updateMchApproveStatus(params) {
   return axios.post(`/SZWL-SERVER/tJoinpayMch/updateMchApproveStatus`, params);
 }
 
-// 更新签约状态
+// 汇聚更新签约状态
 export function updateMchSignStatus(params) {
   return axios.post(`/SZWL-SERVER/tJoinpayMch/updateMchSignStatus`, params);
 }
+
+// 汇聚切换结算方式
+export function updateMchSettle(params) {
+  return axios.post(`/SZWL-SERVER/tJoinpayMch/updateMchSettle`, params);
+}
+
+// 汇付获取商户信息
+export function getHuifuMchCheck(params) {
+  return axios.get(`/SZWL-SERVER/tHuifuMch/getHuifuMchCheck?${stringToUrl(params)}`);
+}
+
+// 汇付入网
+export function createHuifuMch(params) {
+  return axios.post(`/SZWL-SERVER/tHuifuMch/createMch`, params);
+}
+
+// 汇付签约
+export function huifuMchSign(params) {
+  return axios.get(`/SZWL-SERVER/tHuifuMch/signCon?${stringToUrl(params)}`);
+}
+
+// 汇付切换结算方式
+export function updateSettlement(params) {
+  return axios.post(`/SZWL-SERVER/tHuifuMch/updateSettlement`, params);
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2157 - 0
src/views/bindBankCard/huifuBind.vue


+ 61 - 63
src/views/bindBankCard/index.vue

@@ -623,7 +623,7 @@
               required
               :rules="[{ required: true, message: '请输入银行账号' }]"
             />
-            <van-field label="结算方式" required>
+            <!-- <van-field label="结算方式" required>
               <template #input>
                 <div class="settlement-container">
                   <van-radio-group
@@ -637,14 +637,13 @@
                       >手动提现</van-radio
                     >
                   </van-radio-group>
-                  <!-- 新增提示语 -->
                   <div class="settlement-tip">
                     <van-icon name="info" color="#999" size="14px" />
                     <span>24小时内到账</span>
                   </div>
                 </div>
               </template>
-            </van-field>
+            </van-field> -->
           </template>
 
           <!-- 企业商户表单 -->
@@ -674,7 +673,7 @@
               required
               :rules="[{ required: true, message: '请输入联行号' }]"
             />
-            <van-field label="结算方式" required>
+            <!-- <van-field label="结算方式" required>
               <template #input>
                 <div class="settlement-container">
                   <van-radio-group
@@ -688,14 +687,13 @@
                       >手动提现</van-radio
                     >
                   </van-radio-group>
-                  <!-- 新增提示语 -->
                   <div class="settlement-tip">
                     <van-icon name="info" color="#999" size="14px" />
                     <span>自动结算和手工提现均为次日到账</span>
                   </div>
                 </div>
               </template>
-            </van-field>
+            </van-field> -->
           </template>
 
           <div class="confirm-buttons">
@@ -764,7 +762,7 @@ import {
   updateMchApproveStatus,
   updateMchSignStatus,
   altMchSign,
-  getPhotos,
+  // getPhotos,
 } from "../../service/purse/index.js";
 import { ref, computed, onMounted } from "vue";
 import dateUtil from "../../utils/dateUtil";
@@ -950,7 +948,7 @@ export default {
     const afterRead = async (file, type) => {
       try {
         const fileData = new FormData();
-        if (file.file.size > 1000 * 1024) {
+        if (file.file.size > 100 * 1024) {
           // 压缩文件
           const compressedFile = await createCompressedImage(file);
           fileData.append("file", compressedFile)
@@ -1032,7 +1030,7 @@ export default {
           ctx.drawImage(img, 0, 0, width, height);
 
           // 调整压缩质量(大图用0.7,中等图用0.8)
-          const quality = 0.95;
+          const quality = 0.8;
 
           
           canvas.toBlob(
@@ -1246,62 +1244,62 @@ export default {
     };
 
     // 获取图片
-    const getUserLicense = async () => {
-      try {
-        const { data } = await getPhotos({
-          adminId: user.id,
-        });
-        if (data.code === "00000") {
-          console.log("图片", data.data);
-          if (data.data.idCardFront) {
-            idCardFront.value = [
-              {
-                url: "data:image/jpeg;base64," + data.data.idCardFront,
-                isImage: true,
-              },
-            ];
-          }
-          if (data.data.idCardBack) {
-            idCardBack.value = [
-              {
-                url: "data:image/jpeg;base64," + data.data.idCardBack,
-                isImage: true,
-              },
-            ];
-          }
-          if (data.data.bankCard) {
-            bankCard.value = [
-              {
-                url: "data:image/jpeg;base64," + data.data.bankCard,
-                isImage: true,
-              },
-            ];
-          }
-          if (data.data.businessLicense) {
-            businessLicense.value = [
-              {
-                url: "data:image/jpeg;base64," + data.data.businessLicense,
-                isImage: true,
-              },
-            ];
-          }
-          if (data.data.accountLicense) {
-            accountLicense.value = [
-              {
-                url: "data:image/jpeg;base64," + data.data.accountLicense,
-                isImage: true,
-              },
-            ];
-          }
-        }
-      } catch (error) {
-        console.log(error);
-      }
-    };
+    // const getUserLicense = async () => {
+    //   try {
+    //     const { data } = await getPhotos({
+    //       adminId: user.id,
+    //     });
+    //     if (data.code === "00000") {
+    //       console.log("图片", data.data);
+    //       if (data.data.idCardFront) {
+    //         idCardFront.value = [
+    //           {
+    //             url: "data:image/jpeg;base64," + data.data.idCardFront,
+    //             isImage: true,
+    //           },
+    //         ];
+    //       }
+    //       if (data.data.idCardBack) {
+    //         idCardBack.value = [
+    //           {
+    //             url: "data:image/jpeg;base64," + data.data.idCardBack,
+    //             isImage: true,
+    //           },
+    //         ];
+    //       }
+    //       if (data.data.bankCard) {
+    //         bankCard.value = [
+    //           {
+    //             url: "data:image/jpeg;base64," + data.data.bankCard,
+    //             isImage: true,
+    //           },
+    //         ];
+    //       }
+    //       if (data.data.businessLicense) {
+    //         businessLicense.value = [
+    //           {
+    //             url: "data:image/jpeg;base64," + data.data.businessLicense,
+    //             isImage: true,
+    //           },
+    //         ];
+    //       }
+    //       if (data.data.accountLicense) {
+    //         accountLicense.value = [
+    //           {
+    //             url: "data:image/jpeg;base64," + data.data.accountLicense,
+    //             isImage: true,
+    //           },
+    //         ];
+    //       }
+    //     }
+    //   } catch (error) {
+    //     console.log(error);
+    //   }
+    // };
 
     onMounted(async () => {
       await getMchInfo();
-      await getUserLicense();
+      // await getUserLicense();
       if (currentStep.value === 3) {
         changeApproveStatus();
         changeMchApproveStatus();
@@ -1806,7 +1804,6 @@ export default {
   left: 0;
   right: 0;
   background: #ffffff;
-  padding: 12px 16px;
   box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.05);
   z-index: 100;
 }
@@ -1833,6 +1830,7 @@ export default {
 
 /* 按钮容器 */
 .action-buttons {
+  margin: 10px;
   display: flex;
   gap: 10px;
 

+ 36 - 4
src/views/device/deviceOper.vue

@@ -559,8 +559,10 @@
       <div
         class="operation-item"
         v-if="
-          (device.machineType === '0' || device.machineType === null) &&
-          user.type == 0 &&
+          (device.machineType === '0' ||
+            device.machineType === null ||
+            device.equimentType === 'P30') &&
+          (user.type < 2 || user.ifForeign === '1') &&
           controlList.includes('C18')
         "
         @click="returnCoinClk()"
@@ -616,7 +618,10 @@
       </div>
       <!-- 维护记录 -->
       <div
-        v-if="(user.type == 0 || user.id == 31 || user.id == 34) && controlList.includes('C31') "
+        v-if="
+          (device.machineType === '0' || device.machineType === '1') &&
+          controlList.includes('C31')
+        "
         class="operation-item"
         @click="maintenanceClk()"
       >
@@ -631,7 +636,22 @@
           <span class="operation-text">{{ $t("remote.C31") }}</span>
         </div>
       </div>
-      
+      <!-- 支付配置 -->
+      <div
+        class="operation-item"
+        @click="payInfoClk()"
+      >
+        <div class="icon-wrapper">
+          <img
+            class="operation-icon"
+            src="../../assets/device/operIcon/payInfo.png"
+            alt="payInfo"
+          />
+        </div>
+        <div class="text-wrapper">
+          <span class="operation-text">{{ $t("remote.C32") }}</span>
+        </div>
+      </div>
     </div>
   </van-dialog>
   <van-dialog
@@ -776,6 +796,17 @@ export default {
         },
       });
     };
+    // 点击支付配置
+    const payInfoClk = () => {
+      router.push({
+        path: "payInfo",
+        query: {
+          deviceId: device.value.id,
+          name: device.value.name,
+          clientId: device.value.clientId,
+        },
+      });
+    };
     const { t } = useI18n();
     const user = getLoginUser();
     const router = useRouter();
@@ -1173,6 +1204,7 @@ export default {
       taxClk,
       jamClk,
       maintenanceClk,
+      payInfoClk,
 
       changePasswordClk,
       sleepIcon,

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

@@ -803,7 +803,6 @@ export default {
 
     // 点击查看定位
     const viewPosiClk = (row) => {
-      // console.log("row 是 >>>", row);
       if (row.latitude) {
         router.push({
           path: "viewPosition",
@@ -811,6 +810,8 @@ export default {
             latitude: row.latitude,
             longitude: row.longitude,
             fullName: row.fullName,
+            name: row.name ? row.name : row.clientId.slice(-6),
+            status: row.eqeStatus
           },
         });
       } else {

+ 0 - 2
src/views/device/modifyPrice/index.vue

@@ -25,8 +25,6 @@
           </div>
           <van-button
             icon="edit"
-            plain
-            hairline
             @click="noticeClk"
             class="batch-btn"
           >

+ 4 - 3
src/views/device/modulation.vue

@@ -177,15 +177,16 @@ export default {
 
   .volume-slider {
     margin: 0 8px 40px;
+    width: auto;
 
     .slider-thumb {
-      width: 36px;
-      height: 36px;
+      width: 25px;
+      height: 25px;
       background: @primary-color;
       border-radius: 50%;
       color: white;
       font-size: 14px;
-      line-height: 36px;
+      line-height: 25px;
       text-align: center;
       box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
     }

+ 342 - 0
src/views/device/payInfo/index.vue

@@ -0,0 +1,342 @@
+<template>
+  <div class="merchant-config-page">
+    <!-- 顶部导航 -->
+    <s-header :name="$t('remote.C32')" :noback="false" />
+
+    <!-- 设备名称标题 -->
+    <div class="device-header">
+      <div class="vertical-indicator"></div>
+      <h3 class="device-name">
+        {{ $t("device.equipmentName") }}:{{ deviceName }}
+      </h3>
+    </div>
+
+    <!-- 商户信息表单 -->
+    <van-form @submit="handleSubmit">
+      <div class="settings-card">
+        <!-- Merchant ID -->
+        <div class="config-item">
+          <div class="config-info">
+            <van-icon name="user-circle-o" class="config-icon" />
+            <div class="config-detail">
+              <h3 class="config-title">merchant_id</h3>
+              <van-field
+                v-model="configData.merchantId"
+                class="config-input"
+                :border="false"
+                :rules="[
+                {
+                  required: true,
+                  message: 'merchant_id',
+                },
+              ]"
+              />
+            </div>
+          </div>
+        </div>
+
+        <!-- Secret Code -->
+        <div class="config-item">
+          <div class="config-info">
+            <van-icon name="lock" class="config-icon" />
+            <div class="config-detail">
+              <h3 class="config-title">secret_code</h3>
+              <van-field
+                v-model="configData.secretCode"
+                class="config-input"
+                type="password"
+                :border="false"
+                :rules="[
+                {
+                  required: true,
+                  message: 'secret_code',
+                },
+              ]"
+              />
+            </div>
+          </div>
+        </div>
+
+        <!-- Product Ability Code -->
+        <div class="config-item">
+          <div class="config-info">
+            <van-icon name="setting-o" class="config-icon" />
+            <div class="config-detail">
+              <h3 class="config-title">product_ability_code</h3>
+              <van-field
+                v-model="configData.productAbilityCode"
+                class="config-input"
+                :border="false"
+                :rules="[
+                {
+                  required: true,
+                  message: 'product_ability_code',
+                },
+              ]"
+              />
+            </div>
+          </div>
+        </div>
+
+        <!-- Area Code -->
+        <div class="config-item">
+          <div class="config-info">
+            <van-icon name="location-o" class="config-icon" />
+            <div class="config-detail">
+              <h3 class="config-title">area_code</h3>
+              <van-field
+                v-model="configData.areaCode"
+                class="config-input"
+                :border="false"
+                :rules="[
+                {
+                  required: true,
+                  message: 'area_code',
+                },
+              ]"
+              />
+            </div>
+          </div>
+        </div>
+      </div>
+      <!-- 提交按钮 -->
+      <div class="submit-footer">
+        <van-button round type="primary" class="submit-btn" native-type="submit">
+          <template #icon>
+            <van-icon name="success" class="btn-icon" />
+          </template>
+          {{ $t("device.modify") }}
+        </van-button>
+      </div>
+    </van-form>
+
+  </div>
+</template>
+
+<script>
+import sHeader from "@/components/SimpleHeader";
+import { showConfirmDialog, showSuccessToast, showFailToast } from "vant";
+import { useRoute, useRouter } from "vue-router";
+import { ref } from "vue";
+import { useI18n } from "vue-i18n";
+import { onMounted } from "vue";
+import { getPayConfig, pushPayInfo } from "@/service/device/index";
+
+export default {
+  components: { sHeader },
+  setup() {
+    const { t } = useI18n();
+    const route = useRoute();
+    const router = useRouter();
+    const deviceId = ref(route.query.clientId);
+    const deviceName = ref(route.query.name);
+
+    // 配置数据
+    const configData = ref({
+      clientId: deviceId.value,
+      merchantId: "",
+      secretCode: "",
+      productAbilityCode: "",
+      areaCode: "",
+    });
+
+    onMounted(() => {
+      if (deviceId.value) {
+        handleGetPayConfig();
+      }
+    });
+
+    const handleGetPayConfig = async () => {
+      const { data } = await getPayConfig({ clientId: deviceId.value });
+      if (data.data) {
+        configData.value.merchantId = data.data.merchantId;
+        configData.value.secretCode = data.data.secretCode;
+        configData.value.productAbilityCode = data.data.productAbilityCode;
+        configData.value.areaCode = data.data.areaCode;
+      }
+    };
+
+    const handleSubmit = () => {
+      showConfirmDialog({
+        title: t("device.operationConfirmation"),
+        message: t("device.pleaseConfirmAgainWhetherToOperate"),
+      })
+        .then(async () => {
+          // on confirm
+          const { data } = await pushPayInfo(configData.value);
+          if (data.code === "00000") {
+            showSuccessToast(t("device.modificationSucceeded"));
+            setTimeout(() => {
+              router.go(-1);
+            }, 2000);
+          } else {
+            showFailToast(data.message);
+          }
+        })
+        .catch(() => {
+          // on cancel
+        });
+    };
+
+    return {
+      deviceName,
+      handleSubmit,
+      configData,
+    };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+@theme-color: #4d6add;
+@light-bg: #f5f8ff;
+@card-bg: #ffffff;
+@text-dark: #333;
+@text-light: #666;
+@border-radius: 12px;
+@card-shadow: 0 4px 12px rgba(77, 106, 221, 0.15);
+@hover-shadow: 0 8px 20px rgba(77, 106, 221, 0.25);
+@transition: all 0.3s ease;
+
+.merchant-config-page {
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+  background-color: @light-bg;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
+    sans-serif;
+}
+
+.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, #4d6add);
+    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 {
+  background-color: @card-bg;
+  border-radius: @border-radius;
+  box-shadow: @card-shadow;
+  padding: 16px;
+  margin: 0 16px 24px;
+}
+
+.config-item {
+  margin-bottom: 24px;
+
+  &:last-child {
+    margin-bottom: 0;
+  }
+}
+
+.config-info {
+  display: flex;
+  align-items: center;
+}
+
+.config-icon {
+  font-size: 24px;
+  color: @theme-color;
+  margin-right: 16px;
+}
+
+.config-detail {
+  flex: 1;
+}
+
+.config-title {
+  font-size: 15px;
+  font-weight: 500;
+  color: @text-dark;
+  margin: 0 0 8px;
+}
+
+.config-input {
+  background-color: #f9fafc;
+  border-radius: 8px;
+  padding: 10px 16px;
+
+  :deep(.van-field__control) {
+    font-size: 15px;
+    color: @text-dark;
+  }
+
+  :deep(.van-field__placeholder) {
+    color: #a0a4ab;
+  }
+}
+
+.submit-footer {
+  padding: 0 16px 24px;
+  position: sticky;
+  bottom: 0;
+  background-color: @light-bg;
+}
+
+.submit-btn {
+  width: 100%;
+  height: 52px;
+  background-color: @theme-color;
+  border: none;
+  font-size: 17px;
+  font-weight: 500;
+  letter-spacing: 0.5px;
+  box-shadow: 0 6px 16px fade(@theme-color, 35%);
+
+  .btn-icon {
+    font-size: 22px;
+    margin-right: 8px;
+  }
+
+  &:active {
+    opacity: 0.92;
+    transform: translateY(1px);
+  }
+
+  &:disabled {
+    opacity: 0.7;
+    transform: none;
+  }
+}
+
+// 响应式调整
+@media (max-width: 360px) {
+  .device-header .device-name {
+    font-size: 16px;
+  }
+
+  .config-title {
+    font-size: 14px;
+  }
+
+  .submit-btn {
+    height: 48px;
+    font-size: 16px;
+  }
+}
+</style>

+ 160 - 145
src/views/device/payment/index.vue

@@ -1,73 +1,77 @@
 <template>
-    <div class="payment-settings">
-        <s-header :name="$t('remote.C28')" :noback="false" />
+  <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="device-header">
-            <div class="vertical-indicator"></div>
-            <h3 class="device-name">{{ $t('device.equipmentName') }}:{{ deviceName }}</h3>
+    <!-- 支付方式列表 -->
+    <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>
-
-        <!-- 支付方式列表 -->
-        <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>
+        <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>
-
-        <!-- 提交按钮 -->
-        <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>
+        <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 { showConfirmDialog, showSuccessToast, showFailToast } from "vant";
+import { useRoute, useRouter } from 'vue-router';
+import { ref, reactive } from "vue";
 import { useI18n } from 'vue-i18n';
 import { onMounted } from "vue";
-
+import { updatePayment } from "@/service/device/index";
 
 export default {
     components: { sHeader },
     setup() {
         const { t } = useI18n();
         const route = useRoute();
+        const router = useRouter();
+        const deviceId = ref(route.query.deviceId);
         const deviceName = ref(route.query.name);
         const activeZ1 = ref(false);
         const activeZ2 = ref(false);
@@ -87,14 +91,26 @@ export default {
             showConfirmDialog({
                 title: t('device.operationConfirmation'),
                 message: t('device.pleaseConfirmAgainWhetherToOperate'),
-            }).then(() => {
+            }).then(async() => {
                 // 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)
+                const params = reactive({
+                    id: deviceId.value,
+                    paymentType: result,
+                });
+                const { data } = await updatePayment(params);
+                if (data.code === "00000") {
+                    showSuccessToast(t('device.modificationSucceeded'));
+                    setTimeout(() => {
+                        router.go(-1);
+                    }, 2000);
+                } else {
+                    showFailToast(data.message);
+                }
             }).catch(() => {
                 // on cancel
             });
@@ -114,108 +130,107 @@ export default {
 
 <style lang="less" scoped>
 .payment-settings {
-    --payment-bg: #ffffff;
-    --border-color: #ebedf0;
-    --active-color: #4d6add;
-    --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, #4d6add);
-            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;
-        }
+  --payment-bg: #ffffff;
+  --border-color: #ebedf0;
+  --active-color: #4d6add;
+  --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, #4d6add);
+      border-radius: 2px;
+      margin-right: 10px;
     }
 
-    .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);
+    .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-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-info {
+      display: flex;
+      align-items: center;
+      flex: 1;
+    }
 
-        .payment-icon {
-            font-size: 22px;
-            color: var(--active-color);
-            margin-right: 12px;
-        }
+    .payment-icon {
+      font-size: 22px;
+      color: var(--active-color);
+      margin-right: 12px;
+    }
 
-        .payment-detail {
-            flex: 1;
+    .payment-detail {
+      flex: 1;
 
-            .payment-title {
-                margin: 0;
-                font-size: 16px;
-                color: var(--text-primary);
-            }
+      .payment-title {
+        margin: 0;
+        font-size: 16px;
+        color: var(--text-primary);
+      }
 
-            .payment-desc {
-                margin: 4px 0 0;
-                font-size: 12px;
-                color: var(--text-secondary);
-            }
-        }
+      .payment-desc {
+        margin: 4px 0 0;
+        font-size: 12px;
+        color: var(--text-secondary);
+      }
     }
+  }
 
-    .submit-footer {
-        padding: 24px 16px;
+  .submit-footer {
+    padding: 24px 16px;
 
-        .submit-btn {
-            width: 100%;
-            height: 44px;
-            font-size: 16px;
+    .submit-btn {
+      width: 100%;
+      height: 44px;
+      font-size: 16px;
 
-            .btn-icon {
-                margin-right: 8px;
-                vertical-align: -2px;
-            }
-        }
+      .btn-icon {
+        margin-right: 8px;
+        vertical-align: -2px;
+      }
     }
+  }
 }
-</style>
+</style>

+ 613 - 0
src/views/device/viewPosition/index1.vue

@@ -0,0 +1,613 @@
+<template>
+  <div class="view-position-container">
+    <s-header :name="$t('device.equipLocation')" :noback="false"></s-header>
+
+    <!-- 地图加载状态 -->
+    <div class="loading-overlay" v-if="loading">
+      <div class="spinner"></div>
+      <!-- <p>{{ $t("common.loadingMap") }}</p> -->
+      <p>地图加载中</p>
+    </div>
+
+    <!-- 错误提示 -->
+    <div class="error-message" v-if="error">
+      <p>{{ error }}</p>
+      <button class="retry-btn" @click="initMap">
+        <!-- {{ $t("common.retry") }} -->
+        重试
+      </button>
+    </div>
+
+    <!-- 地图容器 -->
+    <div class="map-wrapper">
+      <div ref="mapContainer" class="map"></div>
+    </div>
+
+    <!-- 位置信息卡片 -->
+    <div class="location-info-card">
+      <div class="card-header">
+        <div class="device-name">{{ deviceName || position.fullName }}</div>
+      </div>
+
+      <div class="info-item">
+        <!-- <span class="info-label">{{ $t("device.location") }}:</span> -->
+        <span class="info-label">位置:</span>
+
+        <span class="info-value">{{
+          position.address || position.fullName
+        }}</span>
+      </div>
+      <div class="info-item">
+        <!-- <span class="info-label">{{ $t("device.coordinates") }}:</span> -->
+        <span class="info-label">经纬度:</span>
+
+        <span class="info-value"
+          >{{ position.longitude }}, {{ position.latitude }}</span
+        >
+      </div>
+      <div class="info-item">
+        <span class="info-label">{{ $t("device.status") }}:</span>
+        <span v-if="position.status === '1'" class="status-badge online">在线</span>
+        <span v-else class="status-badge offline">离线</span>
+      </div>
+    </div>
+
+    <!-- 地图操作按钮 -->
+    <div class="map-controls">
+      <!-- 定位按钮 -->
+      <button
+        class="map-btn locate-btn"
+        @click="locateUser"
+        title="定位到我的位置"
+      >
+        <svg width="20" height="20" viewBox="0 0 24 24">
+          <path
+            d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"
+            fill="white"
+          />
+        </svg>
+      </button>
+
+      <!-- 放大按钮 -->
+      <button class="map-btn zoom-in-btn" @click="zoomIn" title="放大">
+        <svg width="20" height="20" viewBox="0 0 24 24">
+          <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" fill="white" />
+        </svg>
+      </button>
+
+      <!-- 缩小按钮 -->
+      <button class="map-btn zoom-out-btn" @click="zoomOut" title="缩小">
+        <svg width="20" height="20" viewBox="0 0 24 24">
+          <path d="M19 13H5v-2h14v2z" fill="white" />
+        </svg>
+      </button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { defineComponent, ref, reactive, onMounted, toRefs } from "vue";
+import { Loader } from "@googlemaps/js-api-loader";
+import { useRoute } from "vue-router";
+import sHeader from "@/components/SimpleHeader";
+
+export default defineComponent({
+  name: "GoogleMapView",
+  components: {
+    sHeader,
+  },
+  setup() {
+    const route = useRoute();
+    const position = reactive({
+      latitude: null,
+      longitude: null,
+      fullName: "",
+      address: "",
+      status: route.query.status || 0, // 默认为离线状态
+      ...route.query,
+    });
+
+    const state = reactive({
+      loading: true,
+      error: null,
+      deviceName: route.query.name,
+      map: null,
+      marker: null,
+      infoWindow: null,
+    });
+
+    const mapContainer = ref(null);
+
+    // 设备定位图标 (Base64 编码)
+    const deviceIconUrl =
+      "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCAzMCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE1IDBDNi43MTUgMCAwIDYuNzE1IDAgMTVjMCAxMCAxNSAyNSAxNSAyNXMxNS0xNSAxNS0yNWMwLTguMjg1LTYuNzE1LTE1LTE1LTE1eiIgZmlsbD0iIzQyODVGQiIvPgo8Y2lyY2xlIGN4PSIxNSIgY3k9IjE1IiByPSI2IiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMjAgMTVoLTNMMTAgMjh2LThoLTN2LThoMTV2OHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPg==";
+
+    // 初始化地图
+    const initMap = async () => {
+      try {
+        state.loading = true;
+        state.error = null;
+
+        // 确保位置参数有效
+        if (!position.latitude || !position.longitude) {
+          throw new Error("缺少位置信息参数");
+        }
+
+        const loader = new Loader({
+          apiKey: "AIzaSyAqxnF8_35P_vlxVGxKhfL2lxFup-qZF6g", // 替换为实际API密钥
+          version: "weekly",
+          libraries: ["places"],
+        });
+
+        // 使用 loader 代替直接使用 google 对象
+        const google = await loader.load();
+
+        // 确保地图容器已渲染
+        if (!mapContainer.value) {
+          throw new Error("地图容器未找到");
+        }
+
+        // 创建地图实例
+        state.map = new google.maps.Map(mapContainer.value, {
+          center: {
+            lat: parseFloat(position.latitude),
+            lng: parseFloat(position.longitude),
+          },
+          zoom: 15,
+          zoomControl: false,
+          mapTypeControl: false,
+          streetViewControl: false,
+          fullscreenControl: false,
+          styles: getMapStyle(),
+        });
+
+        // 创建设备图标对象
+        const deviceIcon = {
+          url: deviceIconUrl,
+          scaledSize: new google.maps.Size(30, 40),
+          origin: new google.maps.Point(0, 0),
+          anchor: new google.maps.Point(15, 40),
+        };
+
+        // 创建标记
+        state.marker = new google.maps.Marker({
+          position: {
+            lat: parseFloat(position.latitude),
+            lng: parseFloat(position.longitude),
+          },
+          map: state.map,
+          title: position.fullName,
+          icon: deviceIcon,
+          animation: google.maps.Animation.DROP,
+        });
+
+        // 创建信息窗口
+        state.infoWindow = new google.maps.InfoWindow({
+          content: `
+            <div class="map-infowindow">
+              <div><strong>${position.fullName}</strong></div>
+              <div style="margin-top:5px">设备: ${state.deviceName}</div>
+              <div style="margin-top:8px;color:#666;font-size:0.8rem">
+                <div>经度: ${position.longitude}</div>
+                <div>纬度: ${position.latitude}</div>
+              </div>
+            </div>
+          `,
+        });
+
+        // 添加点击事件
+        state.marker.addListener("click", () => {
+          state.infoWindow.open(state.map, state.marker);
+        });
+
+        // 添加加载完成事件
+        google.maps.event.addListenerOnce(state.map, "tilesloaded", () => {
+          state.loading = false;
+        });
+      } catch (err) {
+        console.error("地图加载失败:", err);
+        state.error = "地图加载失败: " + err.message;
+        state.loading = false;
+      }
+    };
+
+    // 获取用户位置
+    const locateUser = () => {
+      if (navigator.geolocation) {
+        navigator.geolocation.getCurrentPosition(
+          (position) => {
+            const userLocation = {
+              lat: position.coords.latitude,
+              lng: position.coords.longitude,
+            };
+
+            if (state.map) {
+              state.map.setCenter(userLocation);
+
+              // 添加用户位置标记
+              const userIcon = {
+                path: window.google.maps.SymbolPath.CIRCLE,
+                fillColor: "#34a853",
+                fillOpacity: 1,
+                strokeColor: "#ffffff",
+                strokeWeight: 2,
+                scale: 8,
+              };
+
+              new window.google.maps.Marker({
+                position: userLocation,
+                map: state.map,
+                icon: userIcon,
+                title: "您的位置",
+              });
+            }
+          },
+          (error) => {
+            console.error("获取位置失败:", error);
+            state.error = "无法获取您的位置: " + error.message;
+          },
+          {
+            enableHighAccuracy: true,
+            timeout: 5000,
+            maximumAge: 0,
+          }
+        );
+      } else {
+        state.error = "您的浏览器不支持地理位置功能";
+      }
+    };
+
+    // 地图缩放控制
+    const zoomIn = () => {
+      if (state.map) {
+        const currentZoom = state.map.getZoom();
+        state.map.setZoom(currentZoom + 1);
+      }
+    };
+
+    const zoomOut = () => {
+      if (state.map) {
+        const currentZoom = state.map.getZoom();
+        state.map.setZoom(currentZoom - 1);
+      }
+    };
+
+    // 地图样式配置
+    const getMapStyle = () => {
+      return [
+        {
+          featureType: "administrative",
+          elementType: "labels.text.fill",
+          stylers: [{ color: "#444444" }],
+        },
+        {
+          featureType: "landscape",
+          elementType: "all",
+          stylers: [{ color: "#f2f2f2" }],
+        },
+        {
+          featureType: "poi",
+          elementType: "all",
+          stylers: [{ visibility: "off" }],
+        },
+        {
+          featureType: "road",
+          elementType: "all",
+          stylers: [{ saturation: -100 }, { lightness: 45 }],
+        },
+        {
+          featureType: "road.highway",
+          elementType: "all",
+          stylers: [{ visibility: "simplified" }],
+        },
+        {
+          featureType: "road.arterial",
+          elementType: "labels.icon",
+          stylers: [{ visibility: "off" }],
+        },
+        {
+          featureType: "transit",
+          elementType: "all",
+          stylers: [{ visibility: "off" }],
+        },
+        {
+          featureType: "water",
+          elementType: "all",
+          stylers: [{ color: "#c4e6f3" }, { visibility: "on" }],
+        },
+      ];
+    };
+
+    // 组件挂载时初始化地图
+    onMounted(() => {
+      // 确保有位置数据
+      if (position.latitude && position.longitude) {
+        initMap();
+      } else {
+        state.error = "设备位置信息缺失";
+        state.loading = false;
+      }
+    });
+
+    return {
+      ...toRefs(state),
+      position,
+      mapContainer,
+      initMap,
+      locateUser,
+      zoomIn,
+      zoomOut,
+    };
+  },
+});
+</script>
+
+<style lang="less" scoped>
+.view-position-container {
+  position: relative;
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: #f5f7fa;
+  overflow: hidden;
+
+  .map-wrapper {
+    flex: 1;
+    position: relative;
+
+    .map {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  .loading-overlay {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: rgba(255, 255, 255, 0.9);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    z-index: 100;
+
+    .spinner {
+      width: 50px;
+      height: 50px;
+      border: 4px solid rgba(66, 133, 244, 0.2);
+      border-top: 4px solid #4285f4;
+      border-radius: 50%;
+      animation: spin 1s linear infinite;
+      margin-bottom: 15px;
+    }
+
+    p {
+      color: #4285f4;
+      font-weight: 500;
+    }
+  }
+
+  .error-message {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    background-color: #ffebee;
+    color: #c62828;
+    padding: 20px;
+    border-radius: 8px;
+    text-align: center;
+    z-index: 100;
+    max-width: 80%;
+
+    p {
+      margin-bottom: 15px;
+    }
+
+    .retry-btn {
+      background: #4285f4;
+      color: white;
+      border: none;
+      padding: 8px 20px;
+      border-radius: 4px;
+      font-weight: 500;
+      cursor: pointer;
+      transition: background 0.3s;
+
+      &:hover {
+        background: #3367d6;
+      }
+    }
+  }
+
+  .location-info-card {
+    position: absolute;
+    bottom: 20px;
+    left: 20px;
+    right: 20px;
+    background: rgba(255, 255, 255, 0.95);
+    border-radius: 12px;
+    padding: 15px;
+    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
+    backdrop-filter: blur(10px);
+    z-index: 50;
+    max-width: 500px;
+
+    .card-header {
+      display: flex;
+      align-items: center;
+      margin-bottom: 12px;
+      padding-bottom: 10px;
+      border-bottom: 1px solid #eee;
+    }
+
+    .device-name {
+      font-size: 1.1rem;
+      font-weight: 600;
+      color: #222;
+    }
+
+    .info-item {
+      display: flex;
+      align-items: center;
+      margin-bottom: 8px;
+      font-size: 0.9rem;
+
+      .info-label {
+        color: #666;
+        width: 70px;
+        flex-shrink: 0;
+      }
+
+      .info-value {
+        color: #333;
+        flex: 1;
+        font-weight: 500;
+      }
+
+      .status-badge {
+        padding: 2px 8px;
+        border-radius: 10px;
+        font-size: 14px;
+        font-weight: 500;
+
+        &.online {
+          background-color: rgba(52, 168, 83, 0.15);
+          color: #1d7e40;
+        }
+
+        &.offline {
+          background-color: rgba(71, 55, 55, 0.15);
+          color: #807575;
+        }
+      }
+    }
+  }
+
+  .map-controls {
+    position: absolute;
+    top: 50px;
+    right: 15px;
+    display: flex;
+    flex-direction: column;
+    z-index: 50;
+    gap: 10px;
+
+    .zoom-controls {
+      display: flex;
+      flex-direction: column;
+      gap: 10px;
+
+      .map-btn {
+        margin: 0;
+      }
+    }
+
+    .map-btn {
+      width: 42px;
+      height: 42px;
+      border-radius: 50%;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      cursor: pointer;
+      font-size: 1.1rem;
+      transition: all 0.3s ease;
+      border: none;
+      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+
+      &:hover {
+        transform: translateY(-2px);
+        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25);
+      }
+
+      i {
+        color: white; // 确保图标是白色
+        font-size: 16px;
+      }
+
+      // 定位按钮样式 - 蓝色
+      &.locate-btn {
+        background: #4285f4;
+        &:hover {
+          background: #3367d6;
+        }
+      }
+
+      // 放大按钮样式 - 绿色
+      &.zoom-in-btn {
+        background: #34a853;
+        &:hover {
+          background: #2c9048;
+        }
+      }
+
+      // 缩小按钮样式 - 红色
+      &.zoom-out-btn {
+        background: #ea4335;
+        &:hover {
+          background: #d33426;
+        }
+      }
+    }
+  }
+  @media (max-width: 768px) {
+    .location-info-card {
+      left: 10px;
+      right: 10px;
+      width: 35%;
+
+      .device-name {
+        font-size: 15px;
+      }
+
+      .info-item {
+        font-size: 0.85rem;
+      }
+    }
+
+    .map-controls {
+      top: 55px;
+      right: 10px;
+
+      .map-btn {
+        width: 38px;
+        height: 38px;
+        font-size: 1rem;
+      }
+    }
+  }
+}
+
+@keyframes spin {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
+
+:deep(.gm-style .gm-style-iw) {
+  padding: 12px !important;
+  max-width: 250px !important;
+  border-radius: 12px !important;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
+}
+
+:deep(.gm-style .gm-style-iw-c) {
+  border-radius: 12px !important;
+}
+
+:deep(.map-infowindow) {
+  font-size: 0.9rem;
+  color: #333;
+
+  strong {
+    color: #4285f4;
+  }
+}
+</style>

+ 15 - 20
src/views/discountCode/codeSearch.vue

@@ -4,7 +4,7 @@
     <van-popup v-model:show="sheetShow" round class="codeSearchPopup">
       <div class="content">
         <van-form @submit="onSubmit">
-          <van-field v-model="code" name="code" :label="$t('discountCode.discountCodeNoLabel')"
+          <van-field v-model="code" name="code" type="number" :label="$t('discountCode.discountCodeNoLabel')"
             :placeholder="$t('discountCode.discountCodeNoPlaceholder')" />
           <div class="van-cell van-field">
             <div class="van-cell__title van-field__label">
@@ -13,7 +13,7 @@
             <div class="van-cell__value van-field__value">
               <div class="van-field__body">
                 <input type="text" class="van-field__control" :placeholder="$t('discountCode.startTime')"
-                  style="text-align: center; width: 50%;" v-model="createStratDate" @click="createStratDateClick()" />
+                  style="text-align: center; width: 50%;" v-model="createStartDate" @click="createStratDateClick()" />
                 <span>{{ $t('discountCode.to') }}</span>
                 <input type="text" class="van-field__control" :placeholder="$t('discountCode.endTime')"
                   style="text-align: center; width: 50%;" v-model="createEndDate" @click="createEndDateClick()" />
@@ -27,7 +27,7 @@
             <div class="van-cell__value van-field__value">
               <div class="van-field__body">
                 <input type="text" class="van-field__control" :placeholder="$t('discountCode.startTime')"
-                  style="text-align: center; width: 50%;" v-model="useStratDate" @click="useStratDateClick()" />
+                  style="text-align: center; width: 50%;" v-model="useStartDate" @click="useStratDateClick()" />
                 <span>{{ $t('discountCode.to') }}</span>
                 <input type="text" class="van-field__control" :placeholder="$t('discountCode.endTime')"
                   style="text-align: center; width: 50%;" v-model="useEndDate" @click="useEndDateClick()" />
@@ -67,7 +67,6 @@
 
 <script>
 import { ref } from 'vue';
-import dateUtil from "@/utils/dateUtil";
 import { styleUrl } from "@/common/js/utils";
 
 export default {
@@ -94,38 +93,34 @@ export default {
     //加载样式
     styleUrl('discountCode');
     // 创建开始时间
-    const createStratDate = ref('');
+    const createStartDate = ref('');
     const createStratDateShow = ref(false);
     const createStratDateClick = () => { createStratDateShow.value = true; }
-    const createStratDateConFirm = ({ selectedValues }) => { createStratDate.value = selectedValues.join("-") + " 00:00:00"; createStratDateShow.value = false; }
-    // const createStratDateCancel = () => { createStratDate.value = dateUtil.formateDate(new Date(createStratDate.value), "yyyy-MM-dd hh:mm:ss"); createStratDateShow.value = false; }
+    const createStratDateConFirm = ({ selectedValues }) => { createStartDate.value = selectedValues.join("-"); createStratDateShow.value = false; }
     // 创建结束时间
     const createEndDate = ref('');
     const createEndDateShow = ref(false);
     const createEndDateClick = () => { createEndDateShow.value = true; }
-    const createEndDateConFirm = ({ selectedValues }) => { createEndDate.value = selectedValues.join("-") + " 23:59:59"; createEndDateShow.value = false; }
-    // const createEndDateCancel = () => { createEndDate.value = dateUtil.formateDate(new Date(createEndDate.value), "yyyy-MM-dd hh:mm:ss"); createEndDateShow.value = false; }
+    const createEndDateConFirm = ({ selectedValues }) => { createEndDate.value = selectedValues.join("-"); createEndDateShow.value = false; }
     // 使用起始时间
-    const useStratDate = ref('');
+    const useStartDate = ref('');
     const useStratDateShow = ref(false);
     const useStratDateClick = () => { useStratDateShow.value = true; }
-    const useStratDateConFirm = ({ selectedValues }) => { useStratDate.value = selectedValues.join("-") + " 00:00:00"; useStratDateShow.value = false; }
-    // const useStratDateCancel = () => { useStratDate.value = dateUtil.formateDate(new Date(useStratDate.value), "yyyy-MM-dd hh:mm:ss"); useStratDateShow.value = false; }
+    const useStratDateConFirm = ({ selectedValues }) => { useStartDate.value = selectedValues.join("-"); useStratDateShow.value = false; }
     // 使用结束时间
     const useEndDate = ref('');
     const useEndDateShow = ref(false);
     const useEndDateClick = () => { useEndDateShow.value = true; }
-    const useEndDateConFirm = ({ selectedValues }) => { useEndDate.value = selectedValues.join("-") + " 23:59:59"; useEndDateShow.value = false; }
-    // const useEndDateCancel = () => { useEndDate.value = dateUtil.formateDate(new Date(useEndDate.value), "yyyy-MM-dd hh:mm:ss"); useEndDateShow.value = false; }
+    const useEndDateConFirm = ({ selectedValues }) => { useEndDate.value = selectedValues.join("-"); useEndDateShow.value = false; }
 
     // 提交搜索表单触发搜索
     const onSubmit = () => {
       const searchParam = {};
       if (code.value !== '') { searchParam.code = code.value; }
-      if (createStratDate.value !== '') { searchParam.createStratDate = dateUtil.formateDate(new Date(createStratDate.value), "yyyy/MM/dd hh:mm:ss"); }
-      if (createEndDate.value !== '') { searchParam.createEndDate = dateUtil.formateDate(new Date(createEndDate.value), "yyyy/MM/dd hh:mm:ss"); }
-      if (useStratDate.value !== '') { searchParam.useStratDate = dateUtil.formateDate(new Date(useStratDate.value), "yyyy/MM/dd hh:mm:ss"); }
-      if (useEndDate.value !== '') { searchParam.useEndDate = dateUtil.formateDate(new Date(useEndDate.value), "yyyy/MM/dd hh:mm:ss"); }
+      if (createStartDate.value !== '') { searchParam.createStartDate = createStartDate.value; }
+      if (createEndDate.value !== '') { searchParam.createEndDate = createEndDate.value; }
+      if (useStartDate.value !== '') { searchParam.useStartDate = useStartDate.value; }
+      if (useEndDate.value !== '') { searchParam.useEndDate = useEndDate.value; }
       context.emit('search', searchParam);
       sheetShow.value = false;
     }
@@ -137,7 +132,7 @@ export default {
       maxDate,
       showSearch,
       code,
-      createStratDate,
+      createStartDate,
       createStratDateShow,
       createStratDateClick,
       createStratDateConFirm,
@@ -147,7 +142,7 @@ export default {
       createEndDateClick,
       createEndDateConFirm,
       // createEndDateCancel,
-      useStratDate,
+      useStartDate,
       useStratDateShow,
       useStratDateClick,
       useStratDateConFirm,

+ 28 - 25
src/views/discountCode/index.vue

@@ -21,11 +21,7 @@
 
       <div class="action-buttons">
         <template v-if="isDelete">
-          <van-button
-            size="small"
-            class="action-button"
-            @click="cancelClk"
-          >
+          <van-button size="small" class="action-button" @click="cancelClk">
             {{ $t("discountCode.cancel") }}
           </van-button>
           <van-button
@@ -76,7 +72,7 @@
             size="small"
             type="success"
             class="action-button"
-            @click="clickExport"
+            @click="showExport = true"
           >
             {{ $t("discountCode.export") }}
           </van-button>
@@ -241,8 +237,15 @@
     <!-- 搜索弹出框 -->
     <codeSearch ref="searchRef" @search="search($event)"></codeSearch>
 
-    <!-- 导出功能 -->
-    <codeExport ref="exportRef" @exportCode="exportCode($event)"></codeExport>
+    <!-- 导出弹窗 -->
+    <van-dialog
+      v-model:show="showExport"
+      :title="$t('device.makeRecord.export')"
+      :message="$t('device.makeRecord.exportTips')"
+      show-cancel-button
+      @confirm="handleExport"
+    >
+    </van-dialog>
   </div>
 </template>
 
@@ -257,7 +260,7 @@ import {
 import { showFailToast, showToast, showConfirmDialog } from "vant";
 import { getLoginUser, $M_ExportFile } from "@/common/js/utils";
 import codeSearch from "./codeSearch.vue";
-import codeExport from "./codeExport.vue";
+// import codeExport from "./codeExport.vue";
 import dateUtil from "@/utils/dateUtil";
 import { useRouter } from "vue-router";
 import { useI18n } from "vue-i18n";
@@ -269,6 +272,7 @@ export default {
     const searchRef = ref(null);
     const exportRef = ref(null);
     const user = getLoginUser();
+    const showExport = ref(false);
     const loading = ref(false); // 加载状态
     const error = ref(false); // 错误状态
     const finished = ref(false); // 结束翻页状态
@@ -296,11 +300,6 @@ export default {
       searchParams = Object.assign(searchParams, data);
       searchGetList();
     };
-    // 导出弹窗触发导出
-    const exportCode = (data) => {
-      searchParams = Object.assign(searchParams, data);
-      exportClick();
-    };
     // 查询列表
     const searchGetList = () => {
       discountCodeList.value = [];
@@ -330,7 +329,6 @@ export default {
         discountCodeList.value = discountCodeList.value.concat(
           data.data.records
         );
-        // console.log(discountCodeList.value);
         discountCodeTotal.value = data.data.total;
         if (discountCodeList.value.length === data.data.total) {
           finished.value = true;
@@ -366,14 +364,6 @@ export default {
         ? dateUtil.formateDate(new Date(date), "yyyy/MM/dd hh:mm:ss")
         : "";
     };
-    // 优惠码导出
-    const exportClick = async () => {
-      searchParams.size = 3000;
-      const { headers, data } = await discountCodeExport(
-        Object.assign({}, searchParams)
-      );
-      $M_ExportFile(data, headers);
-    };
     const payCode = () => {
       router.push({ path: "/payCode" });
     };
@@ -455,6 +445,18 @@ export default {
         });
     };
 
+    // 导出
+    const handleExport = async () => {
+      if (discountCodeTotal.value > 5000) {
+        showToast(t("discountCode.exportTips"));
+        return;
+      }
+      const { headers, data } = await discountCodeExport(
+        Object.assign({}, searchParams)
+      );
+      $M_ExportFile(data, headers);
+    };
+
     return {
       searchRef,
       exportRef,
@@ -472,6 +474,8 @@ export default {
       showDate,
       showDateTime,
       // exportClick,
+      showExport,
+      handleExport,
       payCode,
       isExpired,
       isDelete,
@@ -481,10 +485,9 @@ export default {
       cancelClk,
       user,
       clickExport,
-      exportCode,
     };
   },
-  components: { sHeader, codeSearch, codeExport },
+  components: { sHeader, codeSearch },
 };
 </script>
 

+ 1 - 1
src/views/discountCode/payCode.vue

@@ -71,7 +71,7 @@
 
           <van-field
             v-model="codeNum"
-            type="text"
+            type="number"
             maxlength="6"
             :placeholder="$t('discountCode.codeNumPlaceholder')"
           />

+ 90 - 28
src/views/purse/index.vue

@@ -2,19 +2,19 @@
   <div class="wallet-page">
     <!-- 导航栏 -->
     <s-header name="我的钱包" :noback="false" :isBorder="false"></s-header>
-    <!-- 新增提示栏 -->
-    <van-notice-bar
-      v-if="showNotice"
-      left-icon="info"
-      color="#ed6a0c"
-      background="#fef6e6"
-      scrollable
-    >
-      温馨提示:今日收款金额
-      {{ formatAmount(receivableBalance) }} 元将于T+1日结算后可提现
-    </van-notice-bar>
-
+    
     <div class="wallet-content">
+      <!-- 新增提示栏 -->
+      <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">
@@ -91,26 +91,29 @@
           <span>银行卡管理</span>
         </div>
 
-        <div class="bank-cards" @click="jumpTo('/settlement')">
+        <div class="bank-cards">
           <!-- 已绑卡状态 -->
           <div class="bank-card" v-if="hasBankCard">
-            <div class="card-header">
-              <van-icon name="card" size="20" />
-              <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" />
-              <span>本卡已启用自动结算</span>
+            <div @click="jumpTo(user.payPlatform === '1'? '/huifuBind': '/joinPayBind')">
+              <div class="card-header">
+                <van-icon name="card" size="20" />
+                <span>已绑定</span>
+              </div>
+              <div class="card-number">{{ bankCardNo }}</div>
             </div>
-            <div class="auto-settle-hint" v-if="!autoSettle">
-              <van-icon name="circle" color="#4d6add" size="18" />
-              <span>本卡已关闭自动结算</span>
+            <div class="auto-settle-hint">
+              <van-switch
+                :model-value="autoSettle"
+                size="20px"
+                @update:model-value="changeSettle"
+              />
+              <span v-if="autoSettle">已启用自动结算</span>
+              <span v-else>已关闭自动结算</span>
             </div>
           </div>
 
           <!-- 未绑卡状态 -->
-          <div class="bank-card empty-state" v-else>
+          <div class="bank-card empty-state" @click="jumpTo(user.payPlatform === '1'? '/huifuBind': '/joinPayBind')" v-else>
             <div class="empty-content">
               <p class="empty-title">尚未绑定银行卡</p>
               <p class="empty-desc">绑定后可享受快捷支付服务</p>
@@ -164,8 +167,13 @@
 
 <script>
 import sHeader from "../../components/SimpleHeader";
-import { getBalance, withdraw } from "../../service/purse/index";
-import { onMounted, ref } from "vue";
+import {
+  getBalance,
+  withdraw,
+  updateSettlement,
+  updateMchSettle,
+} from "../../service/purse/index";
+import { onMounted, ref, reactive } from "vue";
 import { getOneJoinPayMch } from "../../service/joinpayMch";
 import {
   getHuifuId,
@@ -174,11 +182,13 @@ import {
 } from "@/service/huifuMch";
 import { getLoginUser } from "../../common/js/utils";
 import { useRouter } from "vue-router";
-import { showConfirmDialog, showSuccessToast, showToast } from "vant";
+import { showConfirmDialog, showFailToast, showSuccessToast, showToast } from "vant";
+import { useI18n } from "vue-i18n";
 
 export default {
   components: { sHeader },
   setup() {
+    const { t } = useI18n();
     const user = getLoginUser();
     const router = useRouter();
     const receivableBalance = ref(0.0); // 今日收款余额
@@ -386,6 +396,57 @@ export default {
       router.push({ path: value });
     };
 
+    // 切换订单通知开关
+    const changeSettle = (value) => {
+      showConfirmDialog({
+        title: t("user.tips"),
+        message: autoSettle.value
+          ? "确定关闭自动结算吗?"
+          : "确定开启自动结算吗?",
+      })
+        .then(async () => {
+          if (user.payPlatform === "1") {
+            // 汇付
+            const params = reactive({
+              adminId: user.id,
+              settType: value ? 1 : 2,
+            });
+            const { data } = await updateSettlement(params);
+            if (data.code === "00000") {
+              showSuccessToast(
+                value ? t("user.openSuccess") : t("user.closeSuccess")
+              );
+              setTimeout(() => {
+                router.go(0);
+              }, 1500);
+            } else {
+              showFailToast(data.message);
+            }
+          }
+          if (user.payPlatform === "0") {
+            // 汇聚
+            const params = reactive({
+              adminId: user.id,
+              settMode: value ? 1 : 2,
+            });
+            const { data } = await updateMchSettle(params);
+            if (data.code === "00000") {
+              showSuccessToast(
+                value ? t("user.openSuccess") : t("user.closeSuccess")
+              );
+              setTimeout(() => {
+                router.go(0);
+              }, 1500);
+            } else {
+              showFailToast(data.message);
+            }
+          }
+        })
+        .catch((error) => {
+          console.error(error);
+        });
+    };
+
     return {
       handleRecharge,
       goToAutoRecord,
@@ -398,6 +459,7 @@ export default {
       autoSettle,
       formatBankCard,
       jumpTo,
+      changeSettle,
 
       // 提现
       handleWithdraw,

+ 3 - 3
src/views/user.vue

@@ -348,8 +348,8 @@
             </div>
           </div>
           <!-- 提现帐号 -->
-          <div
-            v-if="user.type == 0"
+          <!-- <div
+            v-if="user.type == 2"
             class="taskListRow l-flex-RC"
             @click="pushPageList('/bindBankCard')"
           >
@@ -357,7 +357,7 @@
             <div class="taskRight">
               <div class="taskTitle">绑定银行卡</div>
             </div>
-          </div>
+          </div> -->
           <!-- 提现帐号 -->
           <div
             v-if="isInland && (user.type == 2 || user.type == 3)"