Просмотр исходного кода

设置收款账号-公共组件,门店信息里加设置收款账号

zhuli 1 месяц назад
Родитель
Сommit
caea1e2bfe

+ 12 - 351
src/views/home/components/go-flow.vue

@@ -270,147 +270,11 @@
     </div>
   </div>
   <!-- 设置收款账号弹窗 -->
-  <el-dialog v-model="setPayAccountDialogVisible" title="设置收款账号" width="520px" destroy-on-close append-to-body>
-    <el-form
-      ref="setPayAccountFormRef"
-      :model="setPayAccountForm"
-      :rules="setPayAccountRules"
-      label-width="140px"
-      label-position="top"
-    >
-      <el-form-item label="账号类型" prop="accountType">
-        <el-radio-group v-model="setPayAccountForm.accountType">
-          <el-radio value="wechat"> 微信 </el-radio>
-          <el-radio value="alipay"> 支付宝 </el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="appid" prop="wechatAppid" v-if="setPayAccountForm.accountType === 'wechat'">
-        <el-input v-model="setPayAccountForm.wechatAppid" placeholder="请输入" clearable />
-      </el-form-item>
-      <el-form-item label="mchld" prop="wechatMchld" v-if="setPayAccountForm.accountType === 'wechat'">
-        <el-input v-model="setPayAccountForm.wechatMchld" placeholder="请输入" clearable />
-      </el-form-item>
-      <el-form-item label="小程序appid" prop="wechatMiniAppId" v-if="setPayAccountForm.accountType === 'wechat'">
-        <el-input v-model="setPayAccountForm.wechatMiniAppId" placeholder="请输入" clearable />
-      </el-form-item>
-      <el-form-item label="API证书序列号" prop="wechatApiCertSerialNo" v-if="setPayAccountForm.accountType === 'wechat'">
-        <el-input v-model="setPayAccountForm.wechatApiCertSerialNo" placeholder="请输入" clearable />
-      </el-form-item>
-      <el-form-item label="APIv3 Key" prop="wechatApiV3Key" v-if="setPayAccountForm.accountType === 'wechat'">
-        <el-input v-model="setPayAccountForm.wechatApiV3Key" placeholder="请输入" clearable />
-      </el-form-item>
-      <el-form-item label="支付公钥ID" prop="wechatPayPublicKeyId" v-if="setPayAccountForm.accountType === 'wechat'">
-        <el-input v-model="setPayAccountForm.wechatPayPublicKeyId" placeholder="请输入" clearable />
-      </el-form-item>
-      <el-form-item label="私钥证书" prop="wechatPrivateKeyFile" v-if="setPayAccountForm.accountType === 'wechat'">
-        <el-upload
-          v-model:file-list="setPayAccountForm.wechatPrivateKeyFile"
-          class="set-pay-key-upload"
-          drag
-          :auto-upload="false"
-          :limit="1"
-          accept=".pem"
-          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
-        >
-          <div class="set-pay-upload-box">
-            <el-icon :size="32" color="#6c8ff8">
-              <UploadFilled />
-            </el-icon>
-            <p>点击或拖拽文件至此处上传</p>
-            <span>支持.pem 格式文件,大小不超过2MB</span>
-          </div>
-        </el-upload>
-      </el-form-item>
-      <el-form-item label="公钥证书" prop="wechatPayPublicKeyFile" v-if="setPayAccountForm.accountType === 'wechat'">
-        <el-upload
-          v-model:file-list="setPayAccountForm.wechatPayPublicKeyFile"
-          class="set-pay-key-upload"
-          drag
-          :auto-upload="false"
-          :limit="1"
-          accept=".pem"
-          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
-        >
-          <div class="set-pay-upload-box">
-            <el-icon :size="32" color="#6c8ff8">
-              <UploadFilled />
-            </el-icon>
-            <p>点击或拖拽文件至此处上传</p>
-            <span>支持.pem 格式文件,大小不超过2MB</span>
-          </div>
-        </el-upload>
-      </el-form-item>
-
-      <!--支付宝--->
-      <el-form-item label="应用ID" prop="aliAppid" v-if="setPayAccountForm.accountType === 'alipay'">
-        <el-input v-model="setPayAccountForm.aliAppid" placeholder="请输入" clearable />
-      </el-form-item>
-      <el-form-item label="应用私钥" prop="aliPrivateId" v-if="setPayAccountForm.accountType === 'alipay'">
-        <el-input v-model="setPayAccountForm.aliPrivateId" placeholder="请输入" clearable />
-      </el-form-item>
-      <el-form-item label="应用公钥证书" prop="appPublicCertFile" v-if="setPayAccountForm.accountType === 'alipay'">
-        <el-upload
-          v-model:file-list="setPayAccountForm.appPublicCertFile"
-          class="set-pay-key-upload"
-          drag
-          :auto-upload="false"
-          :limit="1"
-          accept=".pem"
-          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
-        >
-          <div class="set-pay-upload-box">
-            <el-icon :size="32" color="#6c8ff8">
-              <UploadFilled />
-            </el-icon>
-            <p>点击或拖拽文件至此处上传</p>
-            <span>支持.pem 格式文件,大小不超过2MB</span>
-          </div>
-        </el-upload>
-      </el-form-item>
-      <el-form-item label="支付宝公钥证书" prop="alipayPublicCertFile" v-if="setPayAccountForm.accountType === 'alipay'">
-        <el-upload
-          v-model:file-list="setPayAccountForm.alipayPublicCertFile"
-          class="set-pay-key-upload"
-          drag
-          :auto-upload="false"
-          :limit="1"
-          accept=".pem"
-          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
-        >
-          <div class="set-pay-upload-box">
-            <el-icon :size="32" color="#6c8ff8">
-              <UploadFilled />
-            </el-icon>
-            <p>点击或拖拽文件至此处上传</p>
-            <span>支持.pem 格式文件,大小不超过2MB</span>
-          </div>
-        </el-upload>
-      </el-form-item>
-      <el-form-item label="支付宝根证书" prop="alipayRootCertFile" v-if="setPayAccountForm.accountType === 'alipay'">
-        <el-upload
-          v-model:file-list="setPayAccountForm.alipayRootCertFile"
-          class="set-pay-key-upload"
-          drag
-          :auto-upload="false"
-          :limit="1"
-          accept=".pem"
-          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
-        >
-          <div class="set-pay-upload-box">
-            <el-icon :size="32" color="#6c8ff8">
-              <UploadFilled />
-            </el-icon>
-            <p>点击或拖拽文件至此处上传</p>
-            <span>支持.pem 格式文件,大小不超过2MB</span>
-          </div>
-        </el-upload>
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <el-button @click="setPayAccountDialogVisible = false"> 取消 </el-button>
-      <el-button type="primary" @click="submitSetPayAccount"> 确定 </el-button>
-    </template>
-  </el-dialog>
+  <GoReceivingAccount
+    v-model="setPayAccountDialogVisible"
+    @success="hasPayAccountConfig = true"
+    @has-config="(v: boolean) => (hasPayAccountConfig = v)"
+  />
   <!-- 图片预览 -->
   <el-image-viewer
     v-if="imageViewerVisible"
@@ -426,16 +290,8 @@ import { ElMessage, ElMessageBox, type FormInstance, type FormRules, UploadUserF
 import { Plus } from "@element-plus/icons-vue";
 
 import { applyStore, getMerchantByPhone, getThirdLevelList, verifyIdInfo } from "@/api/modules/homeEntry";
-import {
-  getInputPrompt,
-  getDistrict,
-  uploadImg,
-  ocrRequestUrl,
-  getAiapprovestoreInfo,
-  getPaymentStoreUserId,
-  saveWechatWithFiles,
-  saveAlipayWithFiles
-} from "@/api/modules/newLoginApi";
+import { getInputPrompt, getDistrict, uploadImg, ocrRequestUrl, getAiapprovestoreInfo } from "@/api/modules/newLoginApi";
+import GoReceivingAccount from "./go-receivingAccount.vue";
 import { localGet, localSet } from "@/utils/index";
 import { useAuthStore } from "@/stores/modules/auth";
 
@@ -447,136 +303,9 @@ const showDisportLicence = ref(false);
 const imageViewerVisible = ref(false);
 const imageViewerUrlList = ref<string[]>([]);
 const imageViewerInitialIndex = ref(0);
-//设置收款账号
+// 设置收款账号
 const setPayAccountDialogVisible = ref(false);
 const hasPayAccountConfig = ref(false);
-const setPayAccountForm = reactive({
-  accountType: "wechat",
-  wechatAppid: "",
-  wechatMchld: "",
-  wechatMiniAppId: "",
-  wechatApiCertSerialNo: "",
-  wechatApiV3Key: "",
-  wechatPayPublicKeyId: null,
-  wechatPrivateKeyFile: [] as UploadUserFile[],
-  wechatPayPublicKeyFile: [] as UploadUserFile[],
-
-  aliAppid: "",
-  aliPrivateId: "",
-  alipayRootCertFile: [] as UploadUserFile[],
-  alipayPublicCertFile: [] as UploadUserFile[],
-  appPublicCertFile: [] as UploadUserFile[]
-});
-const setPayAccountRules = ref({
-  accountType: [{ required: true, message: "请选择账号类型", trigger: "change" }],
-  wechatAppid: [{ required: true, message: "请输入appid", trigger: "blur" }],
-  wechatMchld: [{ required: true, message: "请输入mchId", trigger: "blur" }],
-  wechatApiCertSerialNo: [{ required: true, message: "请输入API证书序列号", trigger: "blur" }],
-  wechatApiV3Key: [{ required: true, message: "请输入APIv3 Key", trigger: "blur" }],
-  wechatPayPublicKeyId: [{ required: true, message: "请输入支付公钥ID", trigger: "blur" }],
-  wechatMiniAppId: [{ required: true, message: "请输入小程序AppId", trigger: "blur" }],
-  wechatPrivateKeyFile: [{ required: true, type: "array", min: 1, message: "请上传私钥证书", trigger: "change" }],
-  wechatPayPublicKeyFile: [{ required: true, type: "array", min: 1, message: "请上传公钥证书", trigger: "change" }]
-});
-const setPayAccountFormRef = ref<FormInstance>();
-const submitSetPayAccount = async () => {
-  if (!setPayAccountFormRef.value) return;
-  await setPayAccountFormRef.value.validate(async valid => {
-    if (!valid) return;
-
-    const storeUserId = localGet("geeker-user")?.userInfo?.id;
-    if (!storeUserId) {
-      ElMessage.warning("请先登录");
-      return;
-    }
-    if (setPayAccountForm.accountType === "alipay") {
-      const appPublicCertList = setPayAccountForm.appPublicCertFile as UploadUserFile[];
-      const alipayPublicCertList = setPayAccountForm.alipayPublicCertFile as UploadUserFile[];
-      const alipayRootCertList = setPayAccountForm.alipayRootCertFile as UploadUserFile[];
-
-      const appPublicCertFile = appPublicCertList[0]?.raw as File | undefined;
-      const alipayPublicCertFile = alipayPublicCertList[0]?.raw as File | undefined;
-      const alipayRootCertFile = alipayRootCertList[0]?.raw as File | undefined;
-
-      if (!setPayAccountForm.aliAppid?.trim()) {
-        ElMessage.warning("请输入应用ID");
-        return;
-      }
-      if (!setPayAccountForm.aliPrivateId?.trim()) {
-        ElMessage.warning("请输入应用私钥");
-        return;
-      }
-      if (!appPublicCertFile || !alipayPublicCertFile || !alipayRootCertFile) {
-        ElMessage.warning("请上传应用公钥证书、支付宝公钥证书和支付宝根证书");
-        return;
-      }
-
-      try {
-        const res: any = await saveAlipayWithFiles(
-          {
-            storeUserId: String(storeUserId),
-            appId: setPayAccountForm.aliAppid.trim(),
-            appSecretCert: setPayAccountForm.aliPrivateId.trim()
-          },
-          appPublicCertFile,
-          alipayPublicCertFile,
-          alipayRootCertFile
-        );
-        if (res?.code === 200) {
-          ElMessage.success("保存成功");
-          hasPayAccountConfig.value = true;
-          setPayAccountDialogVisible.value = false;
-        } else {
-          ElMessage.error(res?.msg || "保存失败");
-        }
-      } catch (e: any) {
-        ElMessage.error(e?.message || "保存失败");
-      }
-      return;
-    }
-    if (setPayAccountForm.accountType === "wechat") {
-      const privateKeyUpload = (setPayAccountForm.wechatPrivateKeyFile as UploadUserFile[])[0];
-      const publicKeyUpload = (setPayAccountForm.wechatPayPublicKeyFile as UploadUserFile[])[0];
-
-      const privateKeyFile = privateKeyUpload?.raw as File | undefined;
-      const publicKeyFile = publicKeyUpload?.raw as File | undefined;
-
-      if (!privateKeyFile || !publicKeyFile) {
-        ElMessage.warning("请上传私钥证书和公钥证书");
-        return;
-      }
-
-      try {
-        const res: any = await saveWechatWithFiles(
-          {
-            storeUserId: String(storeUserId),
-            apiV3Key: setPayAccountForm.wechatApiV3Key || "",
-            merchantSerialNumber: setPayAccountForm.wechatApiCertSerialNo || "",
-            wechatAppId: setPayAccountForm.wechatAppid || "",
-            wechatMchId: setPayAccountForm.wechatMchld || "",
-            wechatMiniAppId: setPayAccountForm.wechatMiniAppId || "",
-            wechatPayPublicKeyId: setPayAccountForm.wechatPayPublicKeyId || "",
-            accountType: setPayAccountForm.accountType || "wechat"
-          },
-          privateKeyFile,
-          publicKeyFile
-        );
-        if (res?.code === 200) {
-          ElMessage.success("保存成功");
-          hasPayAccountConfig.value = true;
-          setPayAccountDialogVisible.value = false;
-        } else {
-          ElMessage.error(res?.msg || "保存失败");
-        }
-      } catch (e: any) {
-        ElMessage.error(e?.message || "保存失败");
-      }
-    }
-
-    if (setPayAccountForm.accountType === "alipay") {
-    }
-  });
-};
 const entryList = ref([
   {
     title: "个人实名"
@@ -876,80 +605,8 @@ watch(
   }
 );
 
-/** 将后端返回的 base64 证书转为 File,用于回显且提交时可原样上传 */
-const base64ToFile = (base64Str: string, fileName: string): File => {
-  const bstr = atob(base64Str);
-  const u8arr = new Uint8Array(bstr.length);
-  for (let i = 0; i < bstr.length; i++) u8arr[i] = bstr.charCodeAt(i);
-  return new File([u8arr], fileName, { type: "application/x-pem-file" });
-};
-
-const fetchPayAccountConfig = async () => {
-  const storeUserId = localGet("geeker-user")?.userInfo?.id;
-  if (!storeUserId) return;
-  const res: any = await getPaymentStoreUserId({ storeUserId });
-  if (res?.code !== 200 || !res.data) {
-    hasPayAccountConfig.value = false;
-    return;
-  }
-  const data = res.data;
-  hasPayAccountConfig.value = !!(data.wechatAppId || data.appId);
-
-  // 根据已有数据决定默认展示类型:有微信配置优先微信,否则支付宝
-  if (data.wechatAppId) {
-    setPayAccountForm.accountType = "wechat";
-    setPayAccountForm.wechatAppid = data.wechatAppId ?? "";
-    setPayAccountForm.wechatMchld = data.wechatMchId ?? "";
-    setPayAccountForm.wechatMiniAppId = data.wechatMiniAppId ?? "";
-    setPayAccountForm.wechatApiCertSerialNo = data.merchantSerialNumber ?? "";
-    setPayAccountForm.wechatApiV3Key = data.apiV3Key ?? "";
-    setPayAccountForm.wechatPayPublicKeyId = data.wechatPayPublicKeyId ?? null;
-    setPayAccountForm.wechatPrivateKeyFile = [];
-    setPayAccountForm.wechatPayPublicKeyFile = [];
-    if (data.wechatPrivateKeyFile && data.wechatPrivateKeyName) {
-      const file = base64ToFile(data.wechatPrivateKeyFile, data.wechatPrivateKeyName);
-      setPayAccountForm.wechatPrivateKeyFile = [
-        { name: file.name, raw: file, status: "success", uid: Date.now() } as UploadUserFile
-      ];
-    }
-    if (data.wechatPayPublicKeyFile && data.wechatPayPublicKeyFileName) {
-      const file = base64ToFile(data.wechatPayPublicKeyFile, data.wechatPayPublicKeyFileName);
-      setPayAccountForm.wechatPayPublicKeyFile = [
-        { name: file.name, raw: file, status: "success", uid: Date.now() + 1 } as UploadUserFile
-      ];
-    }
-  }
-
-  if (data.appId) {
-    setPayAccountForm.aliAppid = data.appId ?? "";
-    setPayAccountForm.aliPrivateId = data.appSecretCert ?? "";
-    setPayAccountForm.appPublicCertFile = [];
-    setPayAccountForm.alipayPublicCertFile = [];
-    setPayAccountForm.alipayRootCertFile = [];
-    if (data.appPublicCert && data.appPublicCertName) {
-      const file = base64ToFile(data.appPublicCert, data.appPublicCertName);
-      setPayAccountForm.appPublicCertFile = [
-        { name: file.name, raw: file, status: "success", uid: Date.now() } as UploadUserFile
-      ];
-    }
-    if (data.alipayPublicCert && data.alipayPublicCertName) {
-      const file = base64ToFile(data.alipayPublicCert, data.alipayPublicCertName);
-      setPayAccountForm.alipayPublicCertFile = [
-        { name: file.name, raw: file, status: "success", uid: Date.now() + 1 } as UploadUserFile
-      ];
-    }
-    if (data.alipayRootCert && data.alipayRootCertName) {
-      const file = base64ToFile(data.alipayRootCert, data.alipayRootCertName);
-      setPayAccountForm.alipayRootCertFile = [
-        { name: file.name, raw: file, status: "success", uid: Date.now() + 2 } as UploadUserFile
-      ];
-    }
-    if (!data.wechatAppId) setPayAccountForm.accountType = "alipay";
-  }
-};
 const addPayAccount = () => {
   setPayAccountDialogVisible.value = true;
-  fetchPayAccountConfig();
 };
 onMounted(() => {
   callGetUserInfo();
@@ -1660,6 +1317,9 @@ const handleExceed = () => {
   height: 600px;
   overflow: scroll;
 }
+.set-pay-key-upload {
+  width: 100%;
+}
 </style>
 <style scoped lang="scss">
 // 店铺评价三个输入框纵向排列
@@ -1893,6 +1553,7 @@ const handleExceed = () => {
 }
 .set-pay-key-upload {
   width: 100%;
+  border: 1px solid red !important;
   :deep(.el-upload) {
     width: 100%;
   }

+ 369 - 0
src/views/home/components/go-receivingAccount.vue

@@ -0,0 +1,369 @@
+<template>
+  <el-dialog
+    :model-value="modelValue"
+    title="设置收款账号"
+    width="520px"
+    destroy-on-close
+    append-to-body
+    @update:model-value="emit('update:modelValue', $event)"
+  >
+    <el-form ref="formRef" :model="form" :rules="rules" label-width="140px" label-position="top">
+      <el-form-item label="账号类型" prop="accountType">
+        <el-radio-group v-model="form.accountType">
+          <el-radio value="wechat"> 微信 </el-radio>
+          <el-radio value="alipay"> 支付宝 </el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="appid" prop="wechatAppid" v-if="form.accountType === 'wechat'">
+        <el-input v-model="form.wechatAppid" placeholder="请输入" clearable />
+      </el-form-item>
+      <el-form-item label="mchld" prop="wechatMchld" v-if="form.accountType === 'wechat'">
+        <el-input v-model="form.wechatMchld" placeholder="请输入" clearable />
+      </el-form-item>
+      <el-form-item label="小程序appid" prop="wechatMiniAppId" v-if="form.accountType === 'wechat'">
+        <el-input v-model="form.wechatMiniAppId" placeholder="请输入" clearable />
+      </el-form-item>
+      <el-form-item label="API证书序列号" prop="wechatApiCertSerialNo" v-if="form.accountType === 'wechat'">
+        <el-input v-model="form.wechatApiCertSerialNo" placeholder="请输入" clearable />
+      </el-form-item>
+      <el-form-item label="APIv3 Key" prop="wechatApiV3Key" v-if="form.accountType === 'wechat'">
+        <el-input v-model="form.wechatApiV3Key" placeholder="请输入" clearable />
+      </el-form-item>
+      <el-form-item label="支付公钥ID" prop="wechatPayPublicKeyId" v-if="form.accountType === 'wechat'">
+        <el-input v-model="form.wechatPayPublicKeyId" placeholder="请输入" clearable />
+      </el-form-item>
+      <el-form-item label="私钥证书" prop="wechatPrivateKeyFile" v-if="form.accountType === 'wechat'">
+        <el-upload
+          v-model:file-list="form.wechatPrivateKeyFile"
+          class="set-pay-key-upload"
+          drag
+          :auto-upload="false"
+          :limit="1"
+          accept=".pem"
+          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
+        >
+          <div class="set-pay-upload-box">
+            <el-icon :size="32" color="#6c8ff8">
+              <UploadFilled />
+            </el-icon>
+            <p>点击或拖拽文件至此处上传</p>
+            <span>支持.pem 格式文件,大小不超过2MB</span>
+          </div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="公钥证书" prop="wechatPayPublicKeyFile" v-if="form.accountType === 'wechat'">
+        <el-upload
+          v-model:file-list="form.wechatPayPublicKeyFile"
+          class="set-pay-key-upload"
+          drag
+          :auto-upload="false"
+          :limit="1"
+          accept=".pem"
+          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
+        >
+          <div class="set-pay-upload-box">
+            <el-icon :size="32" color="#6c8ff8">
+              <UploadFilled />
+            </el-icon>
+            <p>点击或拖拽文件至此处上传</p>
+            <span>支持.pem 格式文件,大小不超过2MB</span>
+          </div>
+        </el-upload>
+      </el-form-item>
+
+      <!-- 支付宝 -->
+      <el-form-item label="应用ID" prop="aliAppid" v-if="form.accountType === 'alipay'">
+        <el-input v-model="form.aliAppid" placeholder="请输入" clearable />
+      </el-form-item>
+      <el-form-item label="应用私钥" prop="aliPrivateId" v-if="form.accountType === 'alipay'">
+        <el-input v-model="form.aliPrivateId" placeholder="请输入" clearable />
+      </el-form-item>
+      <el-form-item label="应用公钥证书" prop="appPublicCertFile" v-if="form.accountType === 'alipay'">
+        <el-upload
+          v-model:file-list="form.appPublicCertFile"
+          class="set-pay-key-upload"
+          drag
+          :auto-upload="false"
+          :limit="1"
+          accept=".pem"
+          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
+        >
+          <div class="set-pay-upload-box">
+            <el-icon :size="32" color="#6c8ff8">
+              <UploadFilled />
+            </el-icon>
+            <p>点击或拖拽文件至此处上传</p>
+            <span>支持.pem 格式文件,大小不超过2MB</span>
+          </div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="支付宝公钥证书" prop="alipayPublicCertFile" v-if="form.accountType === 'alipay'">
+        <el-upload
+          v-model:file-list="form.alipayPublicCertFile"
+          class="set-pay-key-upload"
+          drag
+          :auto-upload="false"
+          :limit="1"
+          accept=".pem"
+          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
+        >
+          <div class="set-pay-upload-box">
+            <el-icon :size="32" color="#6c8ff8">
+              <UploadFilled />
+            </el-icon>
+            <p>点击或拖拽文件至此处上传</p>
+            <span>支持.pem 格式文件,大小不超过2MB</span>
+          </div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="支付宝根证书" prop="alipayRootCertFile" v-if="form.accountType === 'alipay'">
+        <el-upload
+          v-model:file-list="form.alipayRootCertFile"
+          class="set-pay-key-upload"
+          drag
+          :auto-upload="false"
+          :limit="1"
+          accept=".pem"
+          :on-exceed="() => ElMessage.warning('最多上传1个文件')"
+        >
+          <div class="set-pay-upload-box">
+            <el-icon :size="32" color="#6c8ff8">
+              <UploadFilled />
+            </el-icon>
+            <p>点击或拖拽文件至此处上传</p>
+            <span>支持.pem 格式文件,大小不超过2MB</span>
+          </div>
+        </el-upload>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="emit('update:modelValue', false)"> 取消 </el-button>
+      <el-button type="primary" @click="submit"> 确定 </el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, watch } from "vue";
+import { ElMessage, type FormInstance, type UploadUserFile } from "element-plus";
+import { UploadFilled } from "@element-plus/icons-vue";
+import { getPaymentStoreUserId, saveWechatWithFiles, saveAlipayWithFiles } from "@/api/modules/newLoginApi";
+import { localGet } from "@/utils/index";
+
+const props = defineProps<{
+  modelValue: boolean;
+}>();
+
+const emit = defineEmits<{
+  (e: "update:modelValue", value: boolean): void;
+  (e: "success"): void;
+  (e: "hasConfig", value: boolean): void;
+}>();
+
+const formRef = ref<FormInstance>();
+const form = reactive({
+  accountType: "wechat",
+  wechatAppid: "",
+  wechatMchld: "",
+  wechatMiniAppId: "",
+  wechatApiCertSerialNo: "",
+  wechatApiV3Key: "",
+  wechatPayPublicKeyId: null as string | null,
+  wechatPrivateKeyFile: [] as UploadUserFile[],
+  wechatPayPublicKeyFile: [] as UploadUserFile[],
+  aliAppid: "",
+  aliPrivateId: "",
+  alipayRootCertFile: [] as UploadUserFile[],
+  alipayPublicCertFile: [] as UploadUserFile[],
+  appPublicCertFile: [] as UploadUserFile[]
+});
+
+const rules = ref({
+  accountType: [{ required: true, message: "请选择账号类型", trigger: "change" }],
+  wechatAppid: [{ required: true, message: "请输入appid", trigger: "blur" }],
+  wechatMchld: [{ required: true, message: "请输入mchId", trigger: "blur" }],
+  wechatApiCertSerialNo: [{ required: true, message: "请输入API证书序列号", trigger: "blur" }],
+  wechatApiV3Key: [{ required: true, message: "请输入APIv3 Key", trigger: "blur" }],
+  wechatPayPublicKeyId: [{ required: true, message: "请输入支付公钥ID", trigger: "blur" }],
+  wechatMiniAppId: [{ required: true, message: "请输入小程序AppId", trigger: "blur" }],
+  wechatPrivateKeyFile: [{ required: true, type: "array" as const, min: 1, message: "请上传私钥证书", trigger: "change" }],
+  wechatPayPublicKeyFile: [{ required: true, type: "array" as const, min: 1, message: "请上传公钥证书", trigger: "change" }]
+});
+
+const base64ToFile = (base64Str: string, fileName: string): File => {
+  const bstr = atob(base64Str);
+  const u8arr = new Uint8Array(bstr.length);
+  for (let i = 0; i < bstr.length; i++) u8arr[i] = bstr.charCodeAt(i);
+  return new File([u8arr], fileName, { type: "application/x-pem-file" });
+};
+
+const fetchPayAccountConfig = async () => {
+  const storeUserId = localGet("geeker-user")?.userInfo?.id;
+  if (!storeUserId) return;
+  const res: any = await getPaymentStoreUserId({ storeUserId });
+  if (res?.code !== 200 || !res.data) {
+    emit("hasConfig", false);
+    return;
+  }
+  const data = res.data;
+  emit("hasConfig", !!(data.wechatAppId || data.appId));
+
+  if (data.wechatAppId) {
+    form.accountType = "wechat";
+    form.wechatAppid = data.wechatAppId ?? "";
+    form.wechatMchld = data.wechatMchId ?? "";
+    form.wechatMiniAppId = data.wechatMiniAppId ?? "";
+    form.wechatApiCertSerialNo = data.merchantSerialNumber ?? "";
+    form.wechatApiV3Key = data.apiV3Key ?? "";
+    form.wechatPayPublicKeyId = data.wechatPayPublicKeyId ?? null;
+    form.wechatPrivateKeyFile = [];
+    form.wechatPayPublicKeyFile = [];
+    if (data.wechatPrivateKeyFile && data.wechatPrivateKeyName) {
+      const file = base64ToFile(data.wechatPrivateKeyFile, data.wechatPrivateKeyName);
+      form.wechatPrivateKeyFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() } as UploadUserFile];
+    }
+    if (data.wechatPayPublicKeyFile && data.wechatPayPublicKeyFileName) {
+      const file = base64ToFile(data.wechatPayPublicKeyFile, data.wechatPayPublicKeyFileName);
+      form.wechatPayPublicKeyFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() + 1 } as UploadUserFile];
+    }
+  }
+
+  if (data.appId) {
+    form.aliAppid = data.appId ?? "";
+    form.aliPrivateId = data.appSecretCert ?? "";
+    form.appPublicCertFile = [];
+    form.alipayPublicCertFile = [];
+    form.alipayRootCertFile = [];
+    if (data.appPublicCert && data.appPublicCertName) {
+      const file = base64ToFile(data.appPublicCert, data.appPublicCertName);
+      form.appPublicCertFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() } as UploadUserFile];
+    }
+    if (data.alipayPublicCert && data.alipayPublicCertName) {
+      const file = base64ToFile(data.alipayPublicCert, data.alipayPublicCertName);
+      form.alipayPublicCertFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() + 1 } as UploadUserFile];
+    }
+    if (data.alipayRootCert && data.alipayRootCertName) {
+      const file = base64ToFile(data.alipayRootCert, data.alipayRootCertName);
+      form.alipayRootCertFile = [{ name: file.name, raw: file, status: "success", uid: Date.now() + 2 } as UploadUserFile];
+    }
+    if (!data.wechatAppId) form.accountType = "alipay";
+  }
+};
+
+const submit = async () => {
+  if (!formRef.value) return;
+  await formRef.value.validate(async valid => {
+    if (!valid) return;
+
+    const storeUserId = localGet("geeker-user")?.userInfo?.id;
+    if (!storeUserId) {
+      ElMessage.warning("请先登录");
+      return;
+    }
+
+    if (form.accountType === "alipay") {
+      const appPublicCertFile = (form.appPublicCertFile as UploadUserFile[])[0]?.raw as File | undefined;
+      const alipayPublicCertFile = (form.alipayPublicCertFile as UploadUserFile[])[0]?.raw as File | undefined;
+      const alipayRootCertFile = (form.alipayRootCertFile as UploadUserFile[])[0]?.raw as File | undefined;
+
+      if (!form.aliAppid?.trim()) {
+        ElMessage.warning("请输入应用ID");
+        return;
+      }
+      if (!form.aliPrivateId?.trim()) {
+        ElMessage.warning("请输入应用私钥");
+        return;
+      }
+      if (!appPublicCertFile || !alipayPublicCertFile || !alipayRootCertFile) {
+        ElMessage.warning("请上传应用公钥证书、支付宝公钥证书和支付宝根证书");
+        return;
+      }
+
+      try {
+        const res: any = await saveAlipayWithFiles(
+          {
+            storeUserId: String(storeUserId),
+            appId: form.aliAppid.trim(),
+            appSecretCert: form.aliPrivateId.trim()
+          },
+          appPublicCertFile,
+          alipayPublicCertFile,
+          alipayRootCertFile
+        );
+        if (res?.code === 200) {
+          ElMessage.success("保存成功");
+          emit("success");
+          emit("update:modelValue", false);
+        } else {
+          ElMessage.error(res?.msg || "保存失败");
+        }
+      } catch (e: any) {
+        ElMessage.error(e?.message || "保存失败");
+      }
+      return;
+    }
+
+    if (form.accountType === "wechat") {
+      const privateKeyUpload = (form.wechatPrivateKeyFile as UploadUserFile[])[0];
+      const publicKeyUpload = (form.wechatPayPublicKeyFile as UploadUserFile[])[0];
+      const privateKeyFile = privateKeyUpload?.raw as File | undefined;
+      const publicKeyFile = publicKeyUpload?.raw as File | undefined;
+
+      if (!privateKeyFile || !publicKeyFile) {
+        ElMessage.warning("请上传私钥证书和公钥证书");
+        return;
+      }
+
+      try {
+        const res: any = await saveWechatWithFiles(
+          {
+            storeUserId: String(storeUserId),
+            apiV3Key: form.wechatApiV3Key || "",
+            merchantSerialNumber: form.wechatApiCertSerialNo || "",
+            wechatAppId: form.wechatAppid || "",
+            wechatMchId: form.wechatMchld || "",
+            wechatMiniAppId: form.wechatMiniAppId || "",
+            wechatPayPublicKeyId: form.wechatPayPublicKeyId || "",
+            accountType: form.accountType || "wechat"
+          },
+          privateKeyFile,
+          publicKeyFile
+        );
+        if (res?.code === 200) {
+          ElMessage.success("保存成功");
+          emit("success");
+          emit("update:modelValue", false);
+        } else {
+          ElMessage.error(res?.msg || "保存失败");
+        }
+      } catch (e: any) {
+        ElMessage.error(e?.message || "保存失败");
+      }
+    }
+  });
+};
+
+watch(
+  () => props.modelValue,
+  visible => {
+    if (visible) fetchPayAccountConfig();
+  }
+);
+</script>
+
+<style scoped>
+.set-pay-key-upload :deep(.el-upload-dragger) {
+  padding: 20px;
+}
+.set-pay-upload-box {
+  color: var(--el-text-color-secondary);
+  text-align: center;
+}
+.set-pay-upload-box p {
+  margin: 8px 0 4px;
+  font-size: 14px;
+}
+.set-pay-upload-box span {
+  font-size: 12px;
+}
+</style>

+ 12 - 1
src/views/storeDecoration/basicStoreInformation/index.vue

@@ -179,7 +179,9 @@
           <el-form-item label="经营类目" prop="businessCategoryName">
             <el-input v-model="formData.businessCategoryName" placeholder="请输入经营类目" clearable maxlength="50" />
           </el-form-item>
-
+          <el-form-item label="设置收款账号">
+            <div style="color: #6c8ff8; cursor: pointer" @click="handleViewPayAccount">查看</div>
+          </el-form-item>
           <!-- 到期时间(只读) -->
           <!--          <el-form-item label="到期时间">-->
           <!--            <el-input v-model="formData.expirationTime" disabled class="readonly-input">-->
@@ -209,6 +211,8 @@
         <el-button type="primary" size="large" :loading="loading" @click="handleSubmit"> 保存 </el-button>
       </div>
     </el-form>
+    <!-- 收款账号弹窗(查看/编辑) -->
+    <GoReceivingAccount v-model="payAccountDialogVisible" />
   </div>
 </template>
 <script setup lang="ts">
@@ -220,6 +224,13 @@ import { getDistrict, getStoreDetail, saveStoreInfo, editStoreInfo } from "@/api
 import { getInputPrompt } from "@/api/modules/newLoginApi";
 import { useRoute } from "vue-router";
 import { localGet } from "@/utils";
+import GoReceivingAccount from "@/views/home/components/go-receivingAccount.vue";
+
+// 收款账号弹窗显隐
+const payAccountDialogVisible = ref(false);
+const handleViewPayAccount = () => {
+  payAccountDialogVisible.value = true;
+};
 
 //地址集合
 const addressList = ref<any[]>([]);