【重构】Vue3 管理后台:[支付管理 -> 应用信息][支付管理 -> 支付订单][支付管理 -> 退款订单] 使用 Element Plus 原生实现
							parent
							
								
									7e3f6190a5
								
							
						
					
					
						commit
						7cb859e976
					
				| 
						 | 
				
			
			@ -114,6 +114,10 @@ export const PayChannelEnum = {
 | 
			
		|||
  ALIPAY_QR: {
 | 
			
		||||
    code: 'alipay_qr',
 | 
			
		||||
    name: '支付宝扫码支付'
 | 
			
		||||
  },
 | 
			
		||||
  ALIPAY_BAR: {
 | 
			
		||||
    code: 'alipay_bar',
 | 
			
		||||
    name: '支付宝条码支付'
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,158 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
 | 
			
		||||
    <el-form
 | 
			
		||||
      ref="formRef"
 | 
			
		||||
      :model="formData"
 | 
			
		||||
      :rules="formRules"
 | 
			
		||||
      label-width="160px"
 | 
			
		||||
      v-loading="formLoading"
 | 
			
		||||
    >
 | 
			
		||||
      <el-form-item label="应用名" prop="name">
 | 
			
		||||
        <el-input v-model="formData.name" placeholder="请输入应用名" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
 | 
			
		||||
      <el-form-item label="所属商户" prop="merchantId">
 | 
			
		||||
        <el-select
 | 
			
		||||
          v-model="formData.merchantId"
 | 
			
		||||
          filterable
 | 
			
		||||
          remote
 | 
			
		||||
          reserve-keyword
 | 
			
		||||
          placeholder="请选择所属商户"
 | 
			
		||||
          :remote-method="handleGetMerchantListByName"
 | 
			
		||||
          :loading="formLoading"
 | 
			
		||||
        >
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="item in merchantList"
 | 
			
		||||
            :key="item.id"
 | 
			
		||||
            :label="item.name"
 | 
			
		||||
            :value="item.id"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="开启状态" prop="status">
 | 
			
		||||
        <el-radio-group v-model="formData.status">
 | 
			
		||||
          <el-radio
 | 
			
		||||
            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
            :key="dict.value"
 | 
			
		||||
            :label="dict.value"
 | 
			
		||||
          >
 | 
			
		||||
            {{ dict.label }}
 | 
			
		||||
          </el-radio>
 | 
			
		||||
        </el-radio-group>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="支付结果的回调地址" prop="payNotifyUrl">
 | 
			
		||||
        <el-input v-model="formData.payNotifyUrl" placeholder="请输入支付结果的回调地址" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款结果的回调地址" prop="refundNotifyUrl">
 | 
			
		||||
        <el-input v-model="formData.refundNotifyUrl" placeholder="请输入退款结果的回调地址" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="备注" prop="remark">
 | 
			
		||||
        <el-input v-model="formData.remark" placeholder="请输入备注" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
    <template #footer>
 | 
			
		||||
      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
 | 
			
		||||
      <el-button @click="dialogVisible = false">取 消</el-button>
 | 
			
		||||
    </template>
 | 
			
		||||
  </Dialog>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 | 
			
		||||
import * as AppApi from '@/api/pay/app'
 | 
			
		||||
import * as MerchantApi from '@/api/pay/merchant'
 | 
			
		||||
import { CommonStatusEnum } from '@/utils/constants'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
const message = useMessage() // 消息弹窗
 | 
			
		||||
const dialogVisible = ref(false) // 弹窗的是否展示
 | 
			
		||||
const dialogTitle = ref('') // 弹窗的标题
 | 
			
		||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 | 
			
		||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
 | 
			
		||||
const formData = ref({
 | 
			
		||||
  id: undefined,
 | 
			
		||||
  name: undefined,
 | 
			
		||||
  packageId: undefined,
 | 
			
		||||
  contactName: undefined,
 | 
			
		||||
  contactMobile: undefined,
 | 
			
		||||
  accountCount: undefined,
 | 
			
		||||
  expireTime: undefined,
 | 
			
		||||
  domain: undefined,
 | 
			
		||||
  status: CommonStatusEnum.ENABLE
 | 
			
		||||
})
 | 
			
		||||
const formRules = reactive({
 | 
			
		||||
  name: [{ required: true, message: '应用名不能为空', trigger: 'blur' }],
 | 
			
		||||
  status: [{ required: true, message: '开启状态不能为空', trigger: 'blur' }],
 | 
			
		||||
  payNotifyUrl: [{ required: true, message: '支付结果的回调地址不能为空', trigger: 'blur' }],
 | 
			
		||||
  refundNotifyUrl: [{ required: true, message: '退款结果的回调地址不能为空', trigger: 'blur' }],
 | 
			
		||||
  merchantId: [{ required: true, message: '商户编号不能为空', trigger: 'blur' }]
 | 
			
		||||
})
 | 
			
		||||
const formRef = ref() // 表单 Ref
 | 
			
		||||
const merchantList = ref([]) // 商户列表
 | 
			
		||||
 | 
			
		||||
/** 打开弹窗 */
 | 
			
		||||
const open = async (type: string, id?: number) => {
 | 
			
		||||
  dialogVisible.value = true
 | 
			
		||||
  dialogTitle.value = t('action.' + type)
 | 
			
		||||
  formType.value = type
 | 
			
		||||
  resetForm()
 | 
			
		||||
  // 修改时,设置数据
 | 
			
		||||
  if (id) {
 | 
			
		||||
    formLoading.value = true
 | 
			
		||||
    try {
 | 
			
		||||
      formData.value = await AppApi.getApp(id)
 | 
			
		||||
    } finally {
 | 
			
		||||
      formLoading.value = false
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  await handleGetMerchantListByName(null)
 | 
			
		||||
}
 | 
			
		||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 | 
			
		||||
 | 
			
		||||
/** 提交表单 */
 | 
			
		||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
 | 
			
		||||
const submitForm = async () => {
 | 
			
		||||
  // 校验表单
 | 
			
		||||
  if (!formRef) return
 | 
			
		||||
  const valid = await formRef.value.validate()
 | 
			
		||||
  if (!valid) return
 | 
			
		||||
  // 提交请求
 | 
			
		||||
  formLoading.value = true
 | 
			
		||||
  try {
 | 
			
		||||
    const data = formData.value as unknown as AppApi.AppVO
 | 
			
		||||
    if (formType.value === 'create') {
 | 
			
		||||
      await AppApi.createApp(data)
 | 
			
		||||
      message.success(t('common.createSuccess'))
 | 
			
		||||
    } else {
 | 
			
		||||
      await AppApi.updateApp(data)
 | 
			
		||||
      message.success(t('common.updateSuccess'))
 | 
			
		||||
    }
 | 
			
		||||
    dialogVisible.value = false
 | 
			
		||||
    // 发送操作成功的事件
 | 
			
		||||
    emit('success')
 | 
			
		||||
  } finally {
 | 
			
		||||
    formLoading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 根据商户名称模糊匹配商户信息
 | 
			
		||||
 * @param name 商户名称
 | 
			
		||||
 */
 | 
			
		||||
const handleGetMerchantListByName = async (name) => {
 | 
			
		||||
  merchantList.value = await MerchantApi.getMerchantListByName(name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 重置表单 */
 | 
			
		||||
const resetForm = () => {
 | 
			
		||||
  formData.value = {
 | 
			
		||||
    id: undefined,
 | 
			
		||||
    name: undefined,
 | 
			
		||||
    status: CommonStatusEnum.ENABLE,
 | 
			
		||||
    remark: undefined,
 | 
			
		||||
    payNotifyUrl: undefined,
 | 
			
		||||
    refundNotifyUrl: undefined,
 | 
			
		||||
    merchantId: undefined
 | 
			
		||||
  }
 | 
			
		||||
  formRef.value?.resetFields()
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,71 +0,0 @@
 | 
			
		|||
import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
 | 
			
		||||
// 表单校验
 | 
			
		||||
export const rules = reactive({
 | 
			
		||||
  name: [required],
 | 
			
		||||
  status: [required],
 | 
			
		||||
  payNotifyUrl: [required],
 | 
			
		||||
  refundNotifyUrl: [required],
 | 
			
		||||
  merchantId: [required]
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
// CrudSchema
 | 
			
		||||
const crudSchemas = reactive<VxeCrudSchema>({
 | 
			
		||||
  primaryKey: 'id',
 | 
			
		||||
  primaryType: 'seq',
 | 
			
		||||
  primaryTitle: '编号',
 | 
			
		||||
  action: true,
 | 
			
		||||
  columns: [
 | 
			
		||||
    {
 | 
			
		||||
      title: '应用名',
 | 
			
		||||
      field: 'name',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '商户名称',
 | 
			
		||||
      field: 'payMerchant',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: t('common.status'),
 | 
			
		||||
      field: 'status',
 | 
			
		||||
      dictType: DICT_TYPE.COMMON_STATUS,
 | 
			
		||||
      dictClass: 'number',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '支付结果的回调地址',
 | 
			
		||||
      field: 'payNotifyUrl',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款结果的回调地址',
 | 
			
		||||
      field: 'refundNotifyUrl',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '商户名称',
 | 
			
		||||
      field: 'merchantName',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '备注',
 | 
			
		||||
      field: 'remark',
 | 
			
		||||
      isTable: false,
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: t('common.createTime'),
 | 
			
		||||
      field: 'createTime',
 | 
			
		||||
      isForm: false,
 | 
			
		||||
      search: {
 | 
			
		||||
        show: true,
 | 
			
		||||
        itemRender: {
 | 
			
		||||
          name: 'XDataTimePicker'
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,155 +1,475 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <!-- 搜索 -->
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <XTable @register="registerTable">
 | 
			
		||||
      <template #toolbar_buttons>
 | 
			
		||||
        <!-- 操作:新增 -->
 | 
			
		||||
        <XButton
 | 
			
		||||
    <el-form
 | 
			
		||||
      class="-mb-15px"
 | 
			
		||||
      :model="queryParams"
 | 
			
		||||
      ref="queryFormRef"
 | 
			
		||||
      :inline="true"
 | 
			
		||||
      label-width="68px"
 | 
			
		||||
    >
 | 
			
		||||
      <el-form-item label="应用名" prop="name">
 | 
			
		||||
        <el-input
 | 
			
		||||
          v-model="queryParams.name"
 | 
			
		||||
          placeholder="请输入应用名"
 | 
			
		||||
          clearable
 | 
			
		||||
          @keyup.enter="handleQuery"
 | 
			
		||||
          class="!w-240px"
 | 
			
		||||
        />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商户名称" prop="contactName">
 | 
			
		||||
        <el-input
 | 
			
		||||
          v-model="queryParams.contactName"
 | 
			
		||||
          placeholder="请输入商户名称"
 | 
			
		||||
          clearable
 | 
			
		||||
          @keyup.enter="handleQuery"
 | 
			
		||||
          class="!w-240px"
 | 
			
		||||
        />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="开启状态" prop="status">
 | 
			
		||||
        <el-select
 | 
			
		||||
          v-model="queryParams.status"
 | 
			
		||||
          placeholder="请选择开启状态"
 | 
			
		||||
          clearable
 | 
			
		||||
          class="!w-240px"
 | 
			
		||||
        >
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
            :key="dict.value"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="dict.value"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker
 | 
			
		||||
          v-model="queryParams.createTime"
 | 
			
		||||
          value-format="YYYY-MM-DD HH:mm:ss"
 | 
			
		||||
          type="daterange"
 | 
			
		||||
          start-placeholder="开始日期"
 | 
			
		||||
          end-placeholder="结束日期"
 | 
			
		||||
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
 | 
			
		||||
          class="!w-240px"
 | 
			
		||||
        />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button @click="handleQuery">
 | 
			
		||||
          <Icon icon="ep:search" class="mr-5px" />
 | 
			
		||||
          搜索
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button @click="resetQuery">
 | 
			
		||||
          <Icon icon="ep:refresh" class="mr-5px" />
 | 
			
		||||
          重置
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          type="primary"
 | 
			
		||||
          preIcon="ep:zoom-in"
 | 
			
		||||
          :title="t('action.add')"
 | 
			
		||||
          v-hasPermi="['pay:app:create']"
 | 
			
		||||
          @click="handleCreate()"
 | 
			
		||||
        />
 | 
			
		||||
        <!-- 操作:导出 -->
 | 
			
		||||
        <XButton
 | 
			
		||||
          type="warning"
 | 
			
		||||
          preIcon="ep:download"
 | 
			
		||||
          :title="t('action.export')"
 | 
			
		||||
          v-hasPermi="['pay:app:export']"
 | 
			
		||||
          @click="exportList('应用信息.xls')"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
      <template #actionbtns_default="{ row }">
 | 
			
		||||
        <!-- 操作:修改 -->
 | 
			
		||||
        <XTextButton
 | 
			
		||||
          preIcon="ep:edit"
 | 
			
		||||
          :title="t('action.edit')"
 | 
			
		||||
          v-hasPermi="['pay:app:update']"
 | 
			
		||||
          @click="handleUpdate(row.id)"
 | 
			
		||||
        />
 | 
			
		||||
        <!-- 操作:详情 -->
 | 
			
		||||
        <XTextButton
 | 
			
		||||
          preIcon="ep:view"
 | 
			
		||||
          :title="t('action.detail')"
 | 
			
		||||
          v-hasPermi="['pay:app:query']"
 | 
			
		||||
          @click="handleDetail(row.id)"
 | 
			
		||||
        />
 | 
			
		||||
        <!-- 操作:删除 -->
 | 
			
		||||
        <XTextButton
 | 
			
		||||
          preIcon="ep:delete"
 | 
			
		||||
          :title="t('action.del')"
 | 
			
		||||
          v-hasPermi="['pay:app:delete']"
 | 
			
		||||
          @click="deleteData(row.id)"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
    </XTable>
 | 
			
		||||
          plain
 | 
			
		||||
          @click="openForm('create')"
 | 
			
		||||
          v-hasPermi="['system:tenant:create']"
 | 
			
		||||
        >
 | 
			
		||||
          <Icon icon="ep:plus" class="mr-5px" />
 | 
			
		||||
          新增
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          type="success"
 | 
			
		||||
          plain
 | 
			
		||||
          @click="handleExport"
 | 
			
		||||
          :loading="exportLoading"
 | 
			
		||||
          v-hasPermi="['system:tenant:export']"
 | 
			
		||||
        >
 | 
			
		||||
          <Icon icon="ep:download" class="mr-5px" />
 | 
			
		||||
          导出
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
  </ContentWrap>
 | 
			
		||||
 | 
			
		||||
  <XModal v-model="dialogVisible" :title="dialogTitle">
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <Form
 | 
			
		||||
      v-if="['create', 'update'].includes(actionType)"
 | 
			
		||||
      :schema="allSchemas.formSchema"
 | 
			
		||||
      :rules="rules"
 | 
			
		||||
      ref="formRef"
 | 
			
		||||
    />
 | 
			
		||||
    <!-- 对话框(详情) -->
 | 
			
		||||
    <Descriptions
 | 
			
		||||
      v-if="actionType === 'detail'"
 | 
			
		||||
      :schema="allSchemas.detailSchema"
 | 
			
		||||
      :data="detailData"
 | 
			
		||||
    />
 | 
			
		||||
    <!-- 操作按钮 -->
 | 
			
		||||
    <template #footer>
 | 
			
		||||
      <!-- 按钮:保存 -->
 | 
			
		||||
      <XButton
 | 
			
		||||
        v-if="['create', 'update'].includes(actionType)"
 | 
			
		||||
        type="primary"
 | 
			
		||||
        :title="t('action.save')"
 | 
			
		||||
        :loading="actionLoading"
 | 
			
		||||
        @click="submitForm()"
 | 
			
		||||
  <!-- 列表 -->
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="应用编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="应用名" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="开启状态" align="center" prop="status">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="商户名称" align="center" prop="payMerchant.name" />
 | 
			
		||||
      <el-table-column label="支付宝配置" align="center">
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-button
 | 
			
		||||
              type="success"
 | 
			
		||||
              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_APP.code)"
 | 
			
		||||
              @click="
 | 
			
		||||
                handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_APP.code, payType.ALIPAY)
 | 
			
		||||
              "
 | 
			
		||||
              circle
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:check" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              v-else
 | 
			
		||||
              type="danger"
 | 
			
		||||
              circle
 | 
			
		||||
              @click="
 | 
			
		||||
                handleCreateChannel(scope.row, payChannelEnum.ALIPAY_APP.code, payType.ALIPAY)
 | 
			
		||||
              "
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:close" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-button
 | 
			
		||||
              type="success"
 | 
			
		||||
              circle
 | 
			
		||||
              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_PC.code)"
 | 
			
		||||
              @click="handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_PC.code, payType.ALIPAY)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:check" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              v-else
 | 
			
		||||
              type="danger"
 | 
			
		||||
              circle
 | 
			
		||||
              @click="handleCreateChannel(scope.row, payChannelEnum.ALIPAY_PC.code, payType.ALIPAY)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:close" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-button
 | 
			
		||||
              type="success"
 | 
			
		||||
              circle
 | 
			
		||||
              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_WAP.code)"
 | 
			
		||||
              @click="
 | 
			
		||||
                handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_WAP.code, payType.ALIPAY)
 | 
			
		||||
              "
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:check" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              v-else
 | 
			
		||||
              type="danger"
 | 
			
		||||
              circle
 | 
			
		||||
              @click="
 | 
			
		||||
                handleCreateChannel(scope.row, payChannelEnum.ALIPAY_WAP.code, payType.ALIPAY)
 | 
			
		||||
              "
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:close" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-button
 | 
			
		||||
              type="success"
 | 
			
		||||
              circle
 | 
			
		||||
              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_QR.code)"
 | 
			
		||||
              @click="handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_QR.code, payType.ALIPAY)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:check" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              v-else
 | 
			
		||||
              type="danger"
 | 
			
		||||
              circle
 | 
			
		||||
              @click="handleCreateChannel(scope.row, payChannelEnum.ALIPAY_QR.code, payType.ALIPAY)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:close" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_BAR.name" align="center">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-button
 | 
			
		||||
              type="success"
 | 
			
		||||
              circle
 | 
			
		||||
              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.ALIPAY_BAR.code)"
 | 
			
		||||
              @click="
 | 
			
		||||
                handleUpdateChannel(scope.row, payChannelEnum.ALIPAY_BAR.code, payType.ALIPAY)
 | 
			
		||||
              "
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:check" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              v-else
 | 
			
		||||
              type="danger"
 | 
			
		||||
              circle
 | 
			
		||||
              @click="
 | 
			
		||||
                handleCreateChannel(scope.row, payChannelEnum.ALIPAY_BAR.code, payType.ALIPAY)
 | 
			
		||||
              "
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:close" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="微信配置" align="center">
 | 
			
		||||
        <el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-button
 | 
			
		||||
              type="success"
 | 
			
		||||
              circle
 | 
			
		||||
              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.WX_LITE.code)"
 | 
			
		||||
              @click="handleUpdateChannel(scope.row, payChannelEnum.WX_LITE.code, payType.WECHAT)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:check" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              v-else
 | 
			
		||||
              type="danger"
 | 
			
		||||
              circle
 | 
			
		||||
              @click="handleCreateChannel(scope.row, payChannelEnum.WX_LITE.code, payType.WECHAT)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:close" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-button
 | 
			
		||||
              type="success"
 | 
			
		||||
              circle
 | 
			
		||||
              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.WX_PUB.code)"
 | 
			
		||||
              @click="handleUpdateChannel(scope.row, payChannelEnum.WX_PUB.code, payType.WECHAT)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:check" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              v-else
 | 
			
		||||
              type="danger"
 | 
			
		||||
              circle
 | 
			
		||||
              @click="handleCreateChannel(scope.row, payChannelEnum.WX_PUB.code, payType.WECHAT)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:close" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.WX_APP.name" align="center">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <el-button
 | 
			
		||||
              type="success"
 | 
			
		||||
              circle
 | 
			
		||||
              v-if="judgeChannelExist(scope.row.channelCodes, payChannelEnum.WX_APP.code)"
 | 
			
		||||
              @click="handleUpdateChannel(scope.row, payChannelEnum.WX_APP.code, payType.WECHAT)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:check" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button
 | 
			
		||||
              v-else
 | 
			
		||||
              type="danger"
 | 
			
		||||
              circle
 | 
			
		||||
              @click="handleCreateChannel(scope.row, payChannelEnum.WX_APP.code, payType.WECHAT)"
 | 
			
		||||
            >
 | 
			
		||||
              <Icon icon="ep:close" />
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column
 | 
			
		||||
        label="创建时间"
 | 
			
		||||
        align="center"
 | 
			
		||||
        prop="createTime"
 | 
			
		||||
        width="180"
 | 
			
		||||
        :formatter="dateFormatter"
 | 
			
		||||
      />
 | 
			
		||||
      <!-- 按钮:关闭 -->
 | 
			
		||||
      <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
 | 
			
		||||
    </template>
 | 
			
		||||
  </XModal>
 | 
			
		||||
      <el-table-column label="操作" align="center" min-width="110" fixed="right">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <el-button
 | 
			
		||||
            link
 | 
			
		||||
            type="primary"
 | 
			
		||||
            @click="openForm('update', scope.row.id)"
 | 
			
		||||
            v-hasPermi="['system:tenant:update']"
 | 
			
		||||
          >
 | 
			
		||||
            编辑
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button
 | 
			
		||||
            link
 | 
			
		||||
            type="danger"
 | 
			
		||||
            @click="handleDelete(scope.row.id)"
 | 
			
		||||
            v-hasPermi="['system:tenant:delete']"
 | 
			
		||||
          >
 | 
			
		||||
            删除
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页 -->
 | 
			
		||||
    <Pagination
 | 
			
		||||
      :total="total"
 | 
			
		||||
      v-model:page="queryParams.pageNo"
 | 
			
		||||
      v-model:limit="queryParams.pageSize"
 | 
			
		||||
      @pagination="getList"
 | 
			
		||||
    />
 | 
			
		||||
  </ContentWrap>
 | 
			
		||||
 | 
			
		||||
  <!-- 表单弹窗:添加/修改 -->
 | 
			
		||||
  <AppForm ref="formRef" @success="getList" />
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts" name="PayApp">
 | 
			
		||||
import type { FormExpose } from '@/components/Form'
 | 
			
		||||
import { rules, allSchemas } from './app.data'
 | 
			
		||||
<script setup lang="ts" name="App">
 | 
			
		||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 | 
			
		||||
import download from '@/utils/download'
 | 
			
		||||
import * as AppApi from '@/api/pay/app'
 | 
			
		||||
import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
 | 
			
		||||
import { dateFormatter } from '@/utils/formatTime'
 | 
			
		||||
import AppForm from '@/views/pay/app/AppForm.vue'
 | 
			
		||||
import { PayChannelEnum as payChannelEnum, PayType } from '@/utils/constants'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
const message = useMessage() // 消息弹窗
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
 | 
			
		||||
// 列表相关的变量
 | 
			
		||||
const [registerTable, { reload, deleteData, exportList }] = useXTable({
 | 
			
		||||
  allSchemas: allSchemas,
 | 
			
		||||
  getListApi: AppApi.getAppPage,
 | 
			
		||||
  deleteApi: AppApi.deleteApp,
 | 
			
		||||
  exportListApi: AppApi.exportApp
 | 
			
		||||
const loading = ref(true) // 列表的加载中
 | 
			
		||||
const total = ref(0) // 列表的总页数
 | 
			
		||||
const list = ref([]) // 列表的数据
 | 
			
		||||
const queryParams = reactive({
 | 
			
		||||
  pageNo: 1,
 | 
			
		||||
  pageSize: 10,
 | 
			
		||||
  name: undefined,
 | 
			
		||||
  status: undefined,
 | 
			
		||||
  remark: undefined,
 | 
			
		||||
  payNotifyUrl: undefined,
 | 
			
		||||
  refundNotifyUrl: undefined,
 | 
			
		||||
  merchantName: undefined,
 | 
			
		||||
  createTime: []
 | 
			
		||||
})
 | 
			
		||||
const queryFormRef = ref() // 搜索的表单
 | 
			
		||||
const exportLoading = ref(false) // 导出的加载中
 | 
			
		||||
const channelParam = reactive({
 | 
			
		||||
  loading: false,
 | 
			
		||||
  // 是否修改
 | 
			
		||||
  edit: false,
 | 
			
		||||
  // 微信是否显示
 | 
			
		||||
  wechatOpen: false,
 | 
			
		||||
  // 支付宝是否显示
 | 
			
		||||
  aliPayOpen: false,
 | 
			
		||||
  // 应用ID
 | 
			
		||||
  appId: null,
 | 
			
		||||
  // 渠道编码
 | 
			
		||||
  payCode: null,
 | 
			
		||||
  // 商户对象
 | 
			
		||||
  payMerchant: {
 | 
			
		||||
    // 编号
 | 
			
		||||
    id: null,
 | 
			
		||||
    // 名称
 | 
			
		||||
    name: null
 | 
			
		||||
  }
 | 
			
		||||
}) // 微信组件传参参数
 | 
			
		||||
 | 
			
		||||
// ========== CRUD 相关 ==========
 | 
			
		||||
const actionLoading = ref(false) // 遮罩层
 | 
			
		||||
const actionType = ref('') // 操作按钮的类型
 | 
			
		||||
const dialogVisible = ref(false) // 是否显示弹出层
 | 
			
		||||
const dialogTitle = ref('edit') // 弹出层标题
 | 
			
		||||
const formRef = ref<FormExpose>() // 表单 Ref
 | 
			
		||||
const detailData = ref() // 详情 Ref
 | 
			
		||||
 | 
			
		||||
// 设置标题
 | 
			
		||||
const setDialogTile = (type: string) => {
 | 
			
		||||
  dialogTitle.value = t('action.' + type)
 | 
			
		||||
  actionType.value = type
 | 
			
		||||
  dialogVisible.value = true
 | 
			
		||||
/** 查询列表 */
 | 
			
		||||
const getList = async () => {
 | 
			
		||||
  loading.value = true
 | 
			
		||||
  try {
 | 
			
		||||
    const data = await AppApi.getAppPage(queryParams)
 | 
			
		||||
    list.value = data.list
 | 
			
		||||
    total.value = data.total
 | 
			
		||||
  } finally {
 | 
			
		||||
    loading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 新增操作
 | 
			
		||||
const handleCreate = () => {
 | 
			
		||||
  setDialogTile('create')
 | 
			
		||||
/** 搜索按钮操作 */
 | 
			
		||||
const handleQuery = () => {
 | 
			
		||||
  queryParams.pageNo = 1
 | 
			
		||||
  getList()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 修改操作
 | 
			
		||||
const handleUpdate = async (rowId: number) => {
 | 
			
		||||
  setDialogTile('update')
 | 
			
		||||
  // 设置数据
 | 
			
		||||
  const res = await AppApi.getApp(rowId)
 | 
			
		||||
  unref(formRef)?.setValues(res)
 | 
			
		||||
/** 重置按钮操作 */
 | 
			
		||||
const resetQuery = () => {
 | 
			
		||||
  queryFormRef.value.resetFields()
 | 
			
		||||
  handleQuery()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 详情操作
 | 
			
		||||
const handleDetail = async (rowId: number) => {
 | 
			
		||||
  setDialogTile('detail')
 | 
			
		||||
  const res = await AppApi.getApp(rowId)
 | 
			
		||||
  detailData.value = res
 | 
			
		||||
/** 添加/修改操作 */
 | 
			
		||||
const formRef = ref()
 | 
			
		||||
const openForm = (type: string, id?: number) => {
 | 
			
		||||
  formRef.value.open(type, id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 提交按钮
 | 
			
		||||
const submitForm = async () => {
 | 
			
		||||
  const elForm = unref(formRef)?.getElFormRef()
 | 
			
		||||
  if (!elForm) return
 | 
			
		||||
  elForm.validate(async (valid) => {
 | 
			
		||||
    if (valid) {
 | 
			
		||||
      actionLoading.value = true
 | 
			
		||||
      // 提交请求
 | 
			
		||||
      try {
 | 
			
		||||
        const data = unref(formRef)?.formModel as AppApi.AppVO
 | 
			
		||||
        if (actionType.value === 'create') {
 | 
			
		||||
          await AppApi.createApp(data)
 | 
			
		||||
          message.success(t('common.createSuccess'))
 | 
			
		||||
        } else {
 | 
			
		||||
          await AppApi.updateApp(data)
 | 
			
		||||
          message.success(t('common.updateSuccess'))
 | 
			
		||||
        }
 | 
			
		||||
        dialogVisible.value = false
 | 
			
		||||
      } finally {
 | 
			
		||||
        actionLoading.value = false
 | 
			
		||||
        // 刷新列表
 | 
			
		||||
        await reload()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
/** 删除按钮操作 */
 | 
			
		||||
const handleDelete = async (id: number) => {
 | 
			
		||||
  try {
 | 
			
		||||
    // 删除的二次确认
 | 
			
		||||
    await message.delConfirm()
 | 
			
		||||
    // 发起删除
 | 
			
		||||
    await AppApi.deleteApp(id)
 | 
			
		||||
    message.success(t('common.delSuccess'))
 | 
			
		||||
    // 刷新列表
 | 
			
		||||
    await getList()
 | 
			
		||||
  } catch {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 导出按钮操作 */
 | 
			
		||||
const handleExport = async () => {
 | 
			
		||||
  try {
 | 
			
		||||
    // 导出的二次确认
 | 
			
		||||
    await message.exportConfirm()
 | 
			
		||||
    // 发起导出
 | 
			
		||||
    exportLoading.value = true
 | 
			
		||||
    const data = await AppApi.exportApp(queryParams)
 | 
			
		||||
    download.excel(data, '支付应用信息.xls')
 | 
			
		||||
  } catch {
 | 
			
		||||
  } finally {
 | 
			
		||||
    exportLoading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 根据渠道编码判断渠道列表中是否存在
 | 
			
		||||
 * @param channels 渠道列表
 | 
			
		||||
 * @param channelCode 渠道编码
 | 
			
		||||
 */
 | 
			
		||||
const judgeChannelExist = (channels, channelCode) => {
 | 
			
		||||
  if (!channels) {
 | 
			
		||||
    return false
 | 
			
		||||
  }
 | 
			
		||||
  return channels.indexOf(channelCode) !== -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 修改支付渠道信息
 | 
			
		||||
 * @param row 行记录
 | 
			
		||||
 * @param payCode 支付编码
 | 
			
		||||
 * @param type 支付类型
 | 
			
		||||
 */
 | 
			
		||||
const handleUpdateChannel = async (row, payCode, type) => {
 | 
			
		||||
  await settingChannelParam(row, payCode, type)
 | 
			
		||||
  channelParam.edit = true
 | 
			
		||||
  channelParam.loading = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 新增支付渠道信息
 | 
			
		||||
 */
 | 
			
		||||
const handleCreateChannel = async (row, payCode, type) => {
 | 
			
		||||
  await settingChannelParam(row, payCode, type)
 | 
			
		||||
  channelParam.edit = false
 | 
			
		||||
  channelParam.loading = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const settingChannelParam = async (row, payCode, type) => {
 | 
			
		||||
  if (type === PayType.WECHAT) {
 | 
			
		||||
    channelParam.wechatOpen = true
 | 
			
		||||
    channelParam.aliPayOpen = false
 | 
			
		||||
  }
 | 
			
		||||
  if (type === PayType.ALIPAY) {
 | 
			
		||||
    channelParam.aliPayOpen = true
 | 
			
		||||
    channelParam.wechatOpen = false
 | 
			
		||||
  }
 | 
			
		||||
  channelParam.edit = false
 | 
			
		||||
  channelParam.loading = false
 | 
			
		||||
  channelParam.appId = row.id
 | 
			
		||||
  channelParam.payCode = payCode
 | 
			
		||||
  channelParam.payMerchant = row.payMerchant
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 初始化 **/
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
  await getList()
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,79 +1,359 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <XTable @register="registerTable">
 | 
			
		||||
      <template #toolbar_buttons>
 | 
			
		||||
        <!-- 操作:新增 -->
 | 
			
		||||
        <XButton
 | 
			
		||||
          type="primary"
 | 
			
		||||
          preIcon="ep:zoom-in"
 | 
			
		||||
          :title="t('action.add')"
 | 
			
		||||
          v-hasPermi="['pay:order:create']"
 | 
			
		||||
          @click="handleCreate()"
 | 
			
		||||
    <el-form
 | 
			
		||||
      class="-mb-15px"
 | 
			
		||||
      :model="queryParams"
 | 
			
		||||
      ref="queryFormRef"
 | 
			
		||||
      :inline="true"
 | 
			
		||||
      label-width="120px"
 | 
			
		||||
    >
 | 
			
		||||
      <el-form-item label="所属商户" prop="merchantId">
 | 
			
		||||
        <el-select
 | 
			
		||||
          v-model="queryParams.merchantId"
 | 
			
		||||
          clearable
 | 
			
		||||
          @clear="
 | 
			
		||||
            () => {
 | 
			
		||||
              queryParams.merchantId = null
 | 
			
		||||
            }
 | 
			
		||||
          "
 | 
			
		||||
          filterable
 | 
			
		||||
          remote
 | 
			
		||||
          reserve-keyword
 | 
			
		||||
          placeholder="请选择所属商户"
 | 
			
		||||
          @change="handleGetAppListByMerchantId"
 | 
			
		||||
          :remote-method="handleGetMerchantListByName"
 | 
			
		||||
          :loading="merchantLoading"
 | 
			
		||||
        >
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="item in merchantList"
 | 
			
		||||
            :key="item.id"
 | 
			
		||||
            :label="item.name"
 | 
			
		||||
            :value="item.id"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="应用编号" prop="appId">
 | 
			
		||||
        <el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息">
 | 
			
		||||
          <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="渠道编码" prop="channelCode">
 | 
			
		||||
        <el-select
 | 
			
		||||
          v-model="queryParams.channelCode"
 | 
			
		||||
          placeholder="请输入渠道编码"
 | 
			
		||||
          clearable
 | 
			
		||||
          @clear="
 | 
			
		||||
            () => {
 | 
			
		||||
              queryParams.channelCode = null
 | 
			
		||||
            }
 | 
			
		||||
          "
 | 
			
		||||
        >
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)"
 | 
			
		||||
            :key="dict.value"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="dict.value"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商户订单编号" prop="merchantOrderId">
 | 
			
		||||
        <el-input
 | 
			
		||||
          v-model="queryParams.merchantOrderId"
 | 
			
		||||
          placeholder="请输入商户订单编号"
 | 
			
		||||
          clearable
 | 
			
		||||
          @keyup.enter="handleQuery"
 | 
			
		||||
        />
 | 
			
		||||
        <!-- 操作:导出 -->
 | 
			
		||||
        <XButton
 | 
			
		||||
          type="warning"
 | 
			
		||||
          preIcon="ep:download"
 | 
			
		||||
          :title="t('action.export')"
 | 
			
		||||
          v-hasPermi="['pay:order:export']"
 | 
			
		||||
          @click="exportList('订单数据.xls')"
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="渠道订单号" prop="channelOrderNo">
 | 
			
		||||
        <el-input
 | 
			
		||||
          v-model="queryParams.channelOrderNo"
 | 
			
		||||
          placeholder="请输入渠道订单号"
 | 
			
		||||
          clearable
 | 
			
		||||
          @keyup.enter="handleQuery"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
      <template #actionbtns_default="{ row }">
 | 
			
		||||
        <!-- 操作:详情 -->
 | 
			
		||||
        <XTextButton
 | 
			
		||||
          preIcon="ep:view"
 | 
			
		||||
          :title="t('action.detail')"
 | 
			
		||||
          v-hasPermi="['pay:order:query']"
 | 
			
		||||
          @click="handleDetail(row.id)"
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="支付状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择支付状态" clearable size="small">
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getDictOptions(DICT_TYPE.PAY_ORDER_STATUS)"
 | 
			
		||||
            :key="parseInt(dict.value)"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="parseInt(dict.value)"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款状态" prop="refundStatus">
 | 
			
		||||
        <el-select v-model="queryParams.refundStatus" placeholder="请选择退款状态" clearable>
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getDictOptions(DICT_TYPE.PAY_ORDER_REFUND_STATUS)"
 | 
			
		||||
            :key="parseInt(dict.value)"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="parseInt(dict.value)"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="回调商户状态" prop="notifyStatus">
 | 
			
		||||
        <el-select
 | 
			
		||||
          v-model="queryParams.notifyStatus"
 | 
			
		||||
          placeholder="请选择订单回调商户状态"
 | 
			
		||||
          clearable
 | 
			
		||||
        >
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getDictOptions(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS)"
 | 
			
		||||
            :key="parseInt(dict.value)"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="parseInt(dict.value)"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker
 | 
			
		||||
          v-model="queryParams.createTime"
 | 
			
		||||
          value-format="YYYY-MM-DD HH:mm:ss"
 | 
			
		||||
          type="daterange"
 | 
			
		||||
          start-placeholder="开始日期"
 | 
			
		||||
          end-placeholder="结束日期"
 | 
			
		||||
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
 | 
			
		||||
          class="!w-240px"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
    </XTable>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button @click="handleQuery">
 | 
			
		||||
          <Icon icon="ep:search" class="mr-5px" />
 | 
			
		||||
          搜索
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button @click="resetQuery">
 | 
			
		||||
          <Icon icon="ep:refresh" class="mr-5px" />
 | 
			
		||||
          重置
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          type="success"
 | 
			
		||||
          plain
 | 
			
		||||
          @click="handleExport"
 | 
			
		||||
          :loading="exportLoading"
 | 
			
		||||
          v-hasPermi="['system:tenant:export']"
 | 
			
		||||
        >
 | 
			
		||||
          <Icon icon="ep:download" class="mr-5px" />
 | 
			
		||||
          导出
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
  </ContentWrap>
 | 
			
		||||
  <XModal v-model="dialogVisible" :title="dialogTitle">
 | 
			
		||||
    <!-- 对话框(详情) -->
 | 
			
		||||
    <Descriptions :schema="allSchemas.detailSchema" :data="detailData" />
 | 
			
		||||
    <!-- 操作按钮 -->
 | 
			
		||||
    <template #footer>
 | 
			
		||||
      <!-- 按钮:关闭 -->
 | 
			
		||||
      <XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
 | 
			
		||||
    </template>
 | 
			
		||||
  </XModal>
 | 
			
		||||
  <content-wrap>
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="订单编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="商户名称" align="center" prop="merchantName" width="120" />
 | 
			
		||||
      <el-table-column label="应用名称" align="center" prop="appName" width="120" />
 | 
			
		||||
      <el-table-column label="渠道名称" align="center" prop="channelCodeName" width="120" />
 | 
			
		||||
      <el-table-column label="渠道订单号" align="center" prop="merchantOrderId" width="120" />
 | 
			
		||||
      <el-table-column label="商品标题" align="center" prop="subject" width="250" />
 | 
			
		||||
      <el-table-column label="商品描述" align="center" prop="body" width="250" />
 | 
			
		||||
      <el-table-column label="异步通知地址" align="center" prop="notifyUrl" width="250" />
 | 
			
		||||
      <el-table-column label="回调状态" align="center" prop="notifyStatus">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付订单" align="left">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <p class="order-font">
 | 
			
		||||
            <el-tag size="small">商户</el-tag>
 | 
			
		||||
            {{ scope.row.merchantOrderId }}
 | 
			
		||||
          </p>
 | 
			
		||||
          <p class="order-font">
 | 
			
		||||
            <el-tag size="small" type="warning">支付</el-tag>
 | 
			
		||||
            {{ scope.row.channelOrderNo }}
 | 
			
		||||
          </p>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付金额" align="center" prop="amount">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          ¥{{ parseFloat(scope.row.amount / 100).toFixed(2) }}
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="手续金额" align="center" prop="channelFeeAmount">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          ¥{{ parseFloat(scope.row.channelFeeAmount / 100).toFixed(2) }}
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款金额" align="center" prop="refundAmount">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          ¥{{ parseFloat(scope.row.refundAmount / 100).toFixed(2) }}
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付状态" align="center" prop="status">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="回调状态" align="center" prop="notifyStatus">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column
 | 
			
		||||
        label="创建时间"
 | 
			
		||||
        align="center"
 | 
			
		||||
        prop="createTime"
 | 
			
		||||
        width="100"
 | 
			
		||||
        :formatter="dateFormatter"
 | 
			
		||||
      />
 | 
			
		||||
      <el-table-column
 | 
			
		||||
        label="支付时间"
 | 
			
		||||
        align="center"
 | 
			
		||||
        prop="successTime"
 | 
			
		||||
        width="100"
 | 
			
		||||
        :formatter="dateFormatter"
 | 
			
		||||
      />
 | 
			
		||||
      <el-table-column
 | 
			
		||||
        label="操作"
 | 
			
		||||
        align="center"
 | 
			
		||||
        fixed="right"
 | 
			
		||||
        class-name="small-padding fixed-width"
 | 
			
		||||
      >
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <el-button
 | 
			
		||||
            size="small"
 | 
			
		||||
            type="text"
 | 
			
		||||
            icon="el-icon-search"
 | 
			
		||||
            @click="openForm(scope.row.id)"
 | 
			
		||||
            v-hasPermi="['pay:order:query']"
 | 
			
		||||
            >查看详情
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <!-- 分页 -->
 | 
			
		||||
    <Pagination
 | 
			
		||||
      :total="total"
 | 
			
		||||
      v-model:page="queryParams.pageNo"
 | 
			
		||||
      v-model:limit="queryParams.pageSize"
 | 
			
		||||
      @pagination="getList"
 | 
			
		||||
    />
 | 
			
		||||
  </content-wrap>
 | 
			
		||||
 | 
			
		||||
  <!-- 表单弹窗:预览 -->
 | 
			
		||||
  <OrderForm ref="formRef" @success="getList" />
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts" name="PayOrder">
 | 
			
		||||
import { allSchemas } from './order.data'
 | 
			
		||||
<script setup lang="ts" name="Order">
 | 
			
		||||
import { DICT_TYPE, getDictOptions } from '@/utils/dict'
 | 
			
		||||
import ContentWrap from '@/components/ContentWrap/src/ContentWrap.vue'
 | 
			
		||||
import * as MerchantApi from '@/api/pay/merchant'
 | 
			
		||||
import * as OrderApi from '@/api/pay/order'
 | 
			
		||||
import download from '@/utils/download'
 | 
			
		||||
import * as AppApi from '@/api/pay/app'
 | 
			
		||||
import { dateFormatter } from '@/utils/formatTime'
 | 
			
		||||
import OrderForm from '@/views/pay/order/orderForm.vue'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
// 列表相关的变量
 | 
			
		||||
const [registerTable, { exportList }] = useXTable({
 | 
			
		||||
  allSchemas: allSchemas,
 | 
			
		||||
  getListApi: OrderApi.getOrderPage,
 | 
			
		||||
  exportListApi: OrderApi.exportOrder
 | 
			
		||||
const message = useMessage() // 消息弹窗
 | 
			
		||||
 | 
			
		||||
// const { t } = useI18n() // 国际化
 | 
			
		||||
const queryFormRef = ref() // 搜索的表单
 | 
			
		||||
const merchantList = ref([]) // 商户列表
 | 
			
		||||
const merchantLoading = ref(false) // 商户加载遮罩层
 | 
			
		||||
const appList = ref([]) // 支付应用列表集合
 | 
			
		||||
const loading = ref(false) // 列表的加载中
 | 
			
		||||
const exportLoading = ref(false) // 导出等待
 | 
			
		||||
const total = ref(0) // 列表的总页数
 | 
			
		||||
const list = ref([]) // 列表的数据
 | 
			
		||||
const queryParams = reactive({
 | 
			
		||||
  pageNo: 1,
 | 
			
		||||
  pageSize: 10,
 | 
			
		||||
  merchantId: undefined,
 | 
			
		||||
  appId: undefined,
 | 
			
		||||
  channelId: undefined,
 | 
			
		||||
  channelCode: undefined,
 | 
			
		||||
  merchantOrderId: undefined,
 | 
			
		||||
  subject: undefined,
 | 
			
		||||
  body: undefined,
 | 
			
		||||
  notifyUrl: undefined,
 | 
			
		||||
  notifyStatus: undefined,
 | 
			
		||||
  amount: undefined,
 | 
			
		||||
  channelFeeRate: undefined,
 | 
			
		||||
  channelFeeAmount: undefined,
 | 
			
		||||
  status: undefined,
 | 
			
		||||
  userIp: undefined,
 | 
			
		||||
  successExtensionId: undefined,
 | 
			
		||||
  refundStatus: undefined,
 | 
			
		||||
  refundTimes: undefined,
 | 
			
		||||
  refundAmount: undefined,
 | 
			
		||||
  channelUserId: undefined,
 | 
			
		||||
  channelOrderNo: undefined,
 | 
			
		||||
  expireTime: [],
 | 
			
		||||
  successTime: [],
 | 
			
		||||
  notifyTime: [],
 | 
			
		||||
  createTime: []
 | 
			
		||||
})
 | 
			
		||||
// ========== CRUD 相关 ==========
 | 
			
		||||
const actionLoading = ref(false) // 遮罩层
 | 
			
		||||
const actionType = ref('') // 操作按钮的类型
 | 
			
		||||
const dialogVisible = ref(false) // 是否显示弹出层
 | 
			
		||||
const dialogTitle = ref('edit') // 弹出层标题
 | 
			
		||||
const detailData = ref() // 详情 Ref
 | 
			
		||||
// 设置标题
 | 
			
		||||
const setDialogTile = (type: string) => {
 | 
			
		||||
  dialogTitle.value = t('action.' + type)
 | 
			
		||||
  actionType.value = type
 | 
			
		||||
  dialogVisible.value = true
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 根据商户名称模糊匹配商户信息
 | 
			
		||||
 * @param name 商户名称
 | 
			
		||||
 */
 | 
			
		||||
const handleGetMerchantListByName = async (name) => {
 | 
			
		||||
  merchantList.value = await MerchantApi.getMerchantListByName(name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 新增操作
 | 
			
		||||
const handleCreate = () => {
 | 
			
		||||
  setDialogTile('create')
 | 
			
		||||
/**
 | 
			
		||||
 * 根据商户 ID 查询支付应用信息
 | 
			
		||||
 */
 | 
			
		||||
const handleGetAppListByMerchantId = () => {
 | 
			
		||||
  queryParams.appId = undefined
 | 
			
		||||
  if (queryParams.merchantId) {
 | 
			
		||||
    AppApi.getAppListByMerchantId(queryParams.merchantId).then((response) => {
 | 
			
		||||
      appList.value = response.data
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 详情操作
 | 
			
		||||
const handleDetail = async (rowId: number) => {
 | 
			
		||||
  setDialogTile('detail')
 | 
			
		||||
  const res = await OrderApi.getOrder(rowId)
 | 
			
		||||
  detailData.value = res
 | 
			
		||||
/** 搜索按钮操作 */
 | 
			
		||||
const handleQuery = () => {
 | 
			
		||||
  queryParams.pageNo = 1
 | 
			
		||||
  getList()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 查询列表 */
 | 
			
		||||
const getList = async () => {
 | 
			
		||||
  loading.value = true
 | 
			
		||||
  try {
 | 
			
		||||
    const data = await OrderApi.getOrderPage(queryParams)
 | 
			
		||||
    list.value = data.list
 | 
			
		||||
    total.value = data.total
 | 
			
		||||
  } finally {
 | 
			
		||||
    loading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 重置按钮操作 */
 | 
			
		||||
const resetQuery = () => {
 | 
			
		||||
  queryFormRef.value.resetFields()
 | 
			
		||||
  handleQuery()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 导出按钮操作 */
 | 
			
		||||
const handleExport = async () => {
 | 
			
		||||
  // 处理查询参数
 | 
			
		||||
  // 导出的二次确认
 | 
			
		||||
  await message.exportConfirm()
 | 
			
		||||
  // 发起导出
 | 
			
		||||
  exportLoading.value = true
 | 
			
		||||
  const data = await OrderApi.exportOrder(queryParams)
 | 
			
		||||
  download.excel(data, '支付订单.xls')
 | 
			
		||||
}
 | 
			
		||||
/** 预览详情 */
 | 
			
		||||
const formRef = ref()
 | 
			
		||||
const openForm = (id?: number) => {
 | 
			
		||||
  formRef.value.open(id)
 | 
			
		||||
}
 | 
			
		||||
/** 初始化 **/
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
  await getList()
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.order-font {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  padding: 2px 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,152 +0,0 @@
 | 
			
		|||
import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
 | 
			
		||||
// 表单校验
 | 
			
		||||
export const rules = reactive({
 | 
			
		||||
  merchantId: [required],
 | 
			
		||||
  appId: [required],
 | 
			
		||||
  merchantOrderId: [required],
 | 
			
		||||
  subject: [required],
 | 
			
		||||
  body: [required],
 | 
			
		||||
  notifyUrl: [required],
 | 
			
		||||
  notifyStatus: [required],
 | 
			
		||||
  amount: [required],
 | 
			
		||||
  status: [required],
 | 
			
		||||
  userIp: [required],
 | 
			
		||||
  expireTime: [required],
 | 
			
		||||
  refundStatus: [required],
 | 
			
		||||
  refundTimes: [required],
 | 
			
		||||
  refundAmount: [required]
 | 
			
		||||
})
 | 
			
		||||
// CrudSchema
 | 
			
		||||
const crudSchemas = reactive<VxeCrudSchema>({
 | 
			
		||||
  primaryKey: 'id',
 | 
			
		||||
  primaryType: 'seq',
 | 
			
		||||
  primaryTitle: '岗位编号',
 | 
			
		||||
  action: true,
 | 
			
		||||
  columns: [
 | 
			
		||||
    {
 | 
			
		||||
      title: '商户编号',
 | 
			
		||||
      field: 'merchantId',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '应用编号',
 | 
			
		||||
      field: 'appId',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道编号',
 | 
			
		||||
      field: 'channelId'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道编码',
 | 
			
		||||
      field: 'channelCode',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道订单号',
 | 
			
		||||
      field: 'merchantOrderId',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '商品标题',
 | 
			
		||||
      field: 'subject'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '商品描述',
 | 
			
		||||
      field: 'body'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '异步通知地址',
 | 
			
		||||
      field: 'notifyUrl'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '回调状态',
 | 
			
		||||
      field: 'notifyStatus',
 | 
			
		||||
      dictType: DICT_TYPE.PAY_ORDER_NOTIFY_STATUS,
 | 
			
		||||
      dictClass: 'number'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '支付金额',
 | 
			
		||||
      field: 'amount',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道手续费',
 | 
			
		||||
      field: 'channelFeeRate',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道手续金额',
 | 
			
		||||
      field: 'channelFeeAmount',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '支付状态',
 | 
			
		||||
      field: 'status',
 | 
			
		||||
      dictType: DICT_TYPE.PAY_ORDER_STATUS,
 | 
			
		||||
      dictClass: 'number',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '用户 IP',
 | 
			
		||||
      field: 'userIp'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '订单失效时间',
 | 
			
		||||
      field: 'expireTime',
 | 
			
		||||
      formatter: 'formatDate'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '支付时间',
 | 
			
		||||
      field: 'successTime',
 | 
			
		||||
      formatter: 'formatDate'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '支付通知时间',
 | 
			
		||||
      field: 'notifyTime',
 | 
			
		||||
      formatter: 'formatDate'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '拓展编号',
 | 
			
		||||
      field: 'successExtensionId'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款状态',
 | 
			
		||||
      field: 'refundStatus',
 | 
			
		||||
      dictType: DICT_TYPE.PAY_ORDER_REFUND_STATUS,
 | 
			
		||||
      dictClass: 'number',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款次数',
 | 
			
		||||
      field: 'refundTimes'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款总金额',
 | 
			
		||||
      field: 'refundAmount'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道用户编号',
 | 
			
		||||
      field: 'channelUserId'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道订单号',
 | 
			
		||||
      field: 'channelOrderNo'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: t('common.createTime'),
 | 
			
		||||
      field: 'createTime',
 | 
			
		||||
      formatter: 'formatDate',
 | 
			
		||||
      isForm: false,
 | 
			
		||||
      search: {
 | 
			
		||||
        show: true,
 | 
			
		||||
        itemRender: {
 | 
			
		||||
          name: 'XDataTimePicker'
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,152 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
 | 
			
		||||
    <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
      <el-descriptions-item label="商户名称">{{ orderDetail.merchantName }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="应用名称">{{ orderDetail.appName }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="商品名称">{{ orderDetail.subject }}</el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
    <el-divider />
 | 
			
		||||
    <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
      <el-descriptions-item label="商户订单号">
 | 
			
		||||
        <el-tag size="small">{{ orderDetail.merchantOrderId }}</el-tag>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="渠道订单号">
 | 
			
		||||
        <el-tag class="tag-purple" size="small">{{ orderDetail.channelOrderNo }}</el-tag>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="支付订单号">
 | 
			
		||||
        <el-tag v-if="orderDetail.payOrderExtension.no !== ''" class="tag-pink" size="small">
 | 
			
		||||
          {{ orderDetail.payOrderExtension.no }}
 | 
			
		||||
        </el-tag>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="金额">
 | 
			
		||||
        <el-tag type="success" size="small">{{ parseFloat(orderDetail.amount / 100, 2) }}</el-tag>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="手续费">
 | 
			
		||||
        <el-tag type="warning" size="small"
 | 
			
		||||
          >{{ parseFloat(orderDetail.channelFeeAmount / 100, 2) }}
 | 
			
		||||
        </el-tag>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="手续费比例">
 | 
			
		||||
        {{ parseFloat(orderDetail.channelFeeRate / 100, 2) }}%
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="支付状态">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="orderDetail.status" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="回调状态">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="orderDetail.notifyStatus" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="回调地址">{{ orderDetail.notifyUrl }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="创建时间" :formatter="dateFormatter">
 | 
			
		||||
        {{ formatDate(orderDetail.createTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="支付时间" :formatter="dateFormatter">
 | 
			
		||||
        {{ formatDate(orderDetail.successTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="失效时间" :formatter="dateFormatter">
 | 
			
		||||
        {{ formatDate(orderDetail.expireTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="通知时间" :formatter="dateFormatter">
 | 
			
		||||
        {{ formatDate(orderDetail.notifyTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
    <el-divider />
 | 
			
		||||
    <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
      <el-descriptions-item label="支付渠道"
 | 
			
		||||
        >{{ orderDetail.channelCodeName }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="支付IP">{{ orderDetail.userIp }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款状态">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_ORDER_REFUND_STATUS" :value="orderDetail.refundStatus" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款次数">{{ orderDetail.refundTimes }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款金额">
 | 
			
		||||
        <el-tag type="warning">
 | 
			
		||||
          {{ parseFloat(orderDetail.refundAmount / 100, 2) }}
 | 
			
		||||
        </el-tag>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
    <el-divider />
 | 
			
		||||
    <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
 | 
			
		||||
      <el-descriptions-item label="商品描述">
 | 
			
		||||
        {{ orderDetail.body }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="支付通道异步回调内容">
 | 
			
		||||
        {{ orderDetail.payOrderExtension.channelNotifyData }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
  </Dialog>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts" name="orderForm">
 | 
			
		||||
import { DICT_TYPE } from '@/utils/dict'
 | 
			
		||||
import * as OrderApi from '@/api/pay/order'
 | 
			
		||||
import { dateFormatter, formatDate } from '@/utils/formatTime'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
// const message = useMessage() // 消息弹窗
 | 
			
		||||
const dialogVisible = ref(false) // 弹窗的是否展示
 | 
			
		||||
const dialogTitle = ref('订单详情') // 弹窗的标题
 | 
			
		||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 | 
			
		||||
const defaultOrderDetail = {
 | 
			
		||||
  merchantName: '',
 | 
			
		||||
  appName: '',
 | 
			
		||||
  channelCodeName: '',
 | 
			
		||||
  subject: '',
 | 
			
		||||
  merchantOrderId: null,
 | 
			
		||||
  channelOrderNo: '',
 | 
			
		||||
  body: '',
 | 
			
		||||
  amount: null,
 | 
			
		||||
  channelFeeRate: null,
 | 
			
		||||
  channelFeeAmount: null,
 | 
			
		||||
  userIp: '',
 | 
			
		||||
  status: null,
 | 
			
		||||
  notifyUrl: '',
 | 
			
		||||
  notifyStatus: null,
 | 
			
		||||
  refundStatus: null,
 | 
			
		||||
  refundTimes: '',
 | 
			
		||||
  refundAmount: null,
 | 
			
		||||
  createTime: '',
 | 
			
		||||
  successTime: '',
 | 
			
		||||
  notifyTime: '',
 | 
			
		||||
  expireTime: '',
 | 
			
		||||
  payOrderExtension: {
 | 
			
		||||
    channelNotifyData: '',
 | 
			
		||||
    no: ''
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
const orderDetail = ref(JSON.parse(JSON.stringify(defaultOrderDetail)))
 | 
			
		||||
 | 
			
		||||
/** 打开弹窗 */
 | 
			
		||||
const open = async (id?: number) => {
 | 
			
		||||
  dialogVisible.value = true
 | 
			
		||||
  dialogTitle.value = t('action.preview')
 | 
			
		||||
  // 修改时,设置数据
 | 
			
		||||
  if (id) {
 | 
			
		||||
    formLoading.value = true
 | 
			
		||||
    try {
 | 
			
		||||
      orderDetail.value = await OrderApi.getOrderDetail(id)
 | 
			
		||||
      if (orderDetail.value.payOrderExtension === null) {
 | 
			
		||||
        orderDetail.value.payOrderExtension = Object.assign(
 | 
			
		||||
          defaultOrderDetail.payOrderExtension,
 | 
			
		||||
          {}
 | 
			
		||||
        )
 | 
			
		||||
      }
 | 
			
		||||
    } finally {
 | 
			
		||||
      formLoading.value = false
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 | 
			
		||||
</script>
 | 
			
		||||
<style>
 | 
			
		||||
.tag-purple {
 | 
			
		||||
  color: #722ed1;
 | 
			
		||||
  background: #f9f0ff;
 | 
			
		||||
  border-color: #d3adf7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-pink {
 | 
			
		||||
  color: #eb2f96;
 | 
			
		||||
  background: #fff0f6;
 | 
			
		||||
  border-color: #ffadd2;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,59 +1,359 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <XTable @register="registerTable">
 | 
			
		||||
      <template #toolbar_buttons>
 | 
			
		||||
        <!-- 操作:导出 -->
 | 
			
		||||
        <XButton
 | 
			
		||||
          type="warning"
 | 
			
		||||
          preIcon="ep:download"
 | 
			
		||||
          :title="t('action.export')"
 | 
			
		||||
          v-hasPermi="['pay:refund:export']"
 | 
			
		||||
          @click="exportList('退款订单.xls')"
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form
 | 
			
		||||
      :model="queryParams"
 | 
			
		||||
      ref="queryFormRef"
 | 
			
		||||
      size="small"
 | 
			
		||||
      :inline="true"
 | 
			
		||||
      label-width="120px"
 | 
			
		||||
    >
 | 
			
		||||
      <el-form-item label="所属商户" prop="merchantId">
 | 
			
		||||
        <el-select
 | 
			
		||||
          v-model="queryParams.merchantId"
 | 
			
		||||
          clearable
 | 
			
		||||
          @clear="
 | 
			
		||||
            () => {
 | 
			
		||||
              queryParams.merchantId = null
 | 
			
		||||
            }
 | 
			
		||||
          "
 | 
			
		||||
          filterable
 | 
			
		||||
          remote
 | 
			
		||||
          reserve-keyword
 | 
			
		||||
          placeholder="请选择所属商户"
 | 
			
		||||
          @change="handleGetAppListByMerchantId"
 | 
			
		||||
          :remote-method="handleGetMerchantListByName"
 | 
			
		||||
          :loading="merchantLoading"
 | 
			
		||||
        >
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="item in merchantList"
 | 
			
		||||
            :key="item.id"
 | 
			
		||||
            :label="item.name"
 | 
			
		||||
            :value="item.id"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="应用编号" prop="appId">
 | 
			
		||||
        <el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息">
 | 
			
		||||
          <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="渠道编码" prop="channelCode">
 | 
			
		||||
        <el-select
 | 
			
		||||
          v-model="queryParams.channelCode"
 | 
			
		||||
          placeholder="请输入渠道编码"
 | 
			
		||||
          clearable
 | 
			
		||||
          @clear="
 | 
			
		||||
            () => {
 | 
			
		||||
              queryParams.channelCode = null
 | 
			
		||||
            }
 | 
			
		||||
          "
 | 
			
		||||
        >
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getDictOptions(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)"
 | 
			
		||||
            :key="dict.value"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="dict.value"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款类型" prop="type">
 | 
			
		||||
        <el-select v-model="queryParams.type" placeholder="请选择退款类型" clearable>
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getDictOptions(DICT_TYPE.PAY_REFUND_ORDER_TYPE)"
 | 
			
		||||
            :key="parseInt(dict.value)"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="parseInt(dict.value)"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商户退款订单号" prop="merchantRefundNo">
 | 
			
		||||
        <el-input
 | 
			
		||||
          v-model="queryParams.merchantRefundNo"
 | 
			
		||||
          placeholder="请输入商户退款订单号"
 | 
			
		||||
          clearable
 | 
			
		||||
          @keyup.enter="handleQuery"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
      <template #actionbtns_default="{ row }">
 | 
			
		||||
        <!-- 操作:详情 -->
 | 
			
		||||
        <XTextButton
 | 
			
		||||
          preIcon="ep:view"
 | 
			
		||||
          :title="t('action.detail')"
 | 
			
		||||
          v-hasPermi="['pay:refund:query']"
 | 
			
		||||
          @click="handleDetail(row.id)"
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable>
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getDictOptions(DICT_TYPE.PAY_REFUND_ORDER_STATUS)"
 | 
			
		||||
            :key="parseInt(dict.value)"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="parseInt(dict.value)"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款回调状态" prop="notifyStatus">
 | 
			
		||||
        <el-select
 | 
			
		||||
          v-model="queryParams.notifyStatus"
 | 
			
		||||
          placeholder="请选择通知商户退款结果的回调状态"
 | 
			
		||||
          clearable
 | 
			
		||||
        >
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getDictOptions(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS)"
 | 
			
		||||
            :key="parseInt(dict.value)"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="parseInt(dict.value)"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker
 | 
			
		||||
          v-model="queryParams.createTime"
 | 
			
		||||
          value-format="YYYY-MM-DD HH:mm:ss"
 | 
			
		||||
          type="daterange"
 | 
			
		||||
          start-placeholder="开始日期"
 | 
			
		||||
          end-placeholder="结束日期"
 | 
			
		||||
          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
 | 
			
		||||
          class="!w-240px"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
    </XTable>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button @click="handleQuery">
 | 
			
		||||
          <Icon icon="ep:search" class="mr-5px" />
 | 
			
		||||
          搜索
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button @click="resetQuery">
 | 
			
		||||
          <Icon icon="ep:refresh" class="mr-5px" />
 | 
			
		||||
          重置
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          type="success"
 | 
			
		||||
          plain
 | 
			
		||||
          @click="handleExport"
 | 
			
		||||
          :loading="exportLoading"
 | 
			
		||||
          v-hasPermi="['system:tenant:export']"
 | 
			
		||||
        >
 | 
			
		||||
          <Icon icon="ep:download" class="mr-5px" />
 | 
			
		||||
          导出
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
  </ContentWrap>
 | 
			
		||||
 | 
			
		||||
  <XModal v-model="dialogVisible" :title="t('action.detail')">
 | 
			
		||||
    <!-- 对话框(详情) -->
 | 
			
		||||
    <Descriptions :schema="allSchemas.detailSchema" :data="detailData" />
 | 
			
		||||
    <!-- 操作按钮 -->
 | 
			
		||||
    <template #footer>
 | 
			
		||||
      <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>
 | 
			
		||||
    </template>
 | 
			
		||||
  </XModal>
 | 
			
		||||
  <el-table v-loading="loading" :data="list">
 | 
			
		||||
    <el-table-column label="编号" align="center" prop="id" />
 | 
			
		||||
    <el-table-column label="商户名称" align="center" prop="merchantName" width="120" />
 | 
			
		||||
    <el-table-column label="应用名称" align="center" prop="appName" width="120" />
 | 
			
		||||
    <el-table-column label="渠道名称" align="center" prop="channelCodeName" width="120" />
 | 
			
		||||
    <el-table-column label="交易订单号" align="center" prop="tradeNo" width="140" />
 | 
			
		||||
    <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140" />
 | 
			
		||||
    <el-table-column label="商户订单号" align="left" width="230">
 | 
			
		||||
      <template #default="scope">
 | 
			
		||||
        <p class="order-font">
 | 
			
		||||
          <el-tag size="small">退款</el-tag>
 | 
			
		||||
          {{ scope.row.merchantRefundNo }}
 | 
			
		||||
        </p>
 | 
			
		||||
        <p class="order-font">
 | 
			
		||||
          <el-tag type="success">交易</el-tag>
 | 
			
		||||
          {{ scope.row.merchantOrderId }}
 | 
			
		||||
        </p>
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column label="支付订单号" align="center" prop="merchantRefundNo" width="250">
 | 
			
		||||
      <template #default="scope">
 | 
			
		||||
        <p class="order-font">
 | 
			
		||||
          <el-tag size="small">交易</el-tag>
 | 
			
		||||
          {{ scope.row.tradeNo }}
 | 
			
		||||
        </p>
 | 
			
		||||
        <p class="order-font">
 | 
			
		||||
          <el-tag size="small" type="warning">渠道</el-tag>
 | 
			
		||||
          {{ scope.row.channelOrderNo }}
 | 
			
		||||
        </p>
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column label="支付金额(元)" align="center" prop="payAmount" width="100">
 | 
			
		||||
      <template #default="scope">
 | 
			
		||||
        ¥{{ parseFloat(scope.row.payAmount / 100).toFixed(2) }}
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column label="退款金额(元)" align="center" prop="refundAmount" width="100">
 | 
			
		||||
      <template #default="scope">
 | 
			
		||||
        ¥{{ parseFloat(scope.row.refundAmount / 100).toFixed(2) }}
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column label="退款类型" align="center" prop="type" width="80">
 | 
			
		||||
      <template #default="scope">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="scope.row.type" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column label="退款状态" align="center" prop="status">
 | 
			
		||||
      <template #default="scope">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="scope.row.status" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column label="回调状态" align="center" prop="notifyStatus">
 | 
			
		||||
      <template #default="scope">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
    <el-table-column
 | 
			
		||||
      label="退款原因"
 | 
			
		||||
      align="center"
 | 
			
		||||
      prop="reason"
 | 
			
		||||
      width="140"
 | 
			
		||||
      :show-overflow-tooltip="true"
 | 
			
		||||
    />
 | 
			
		||||
    <el-table-column
 | 
			
		||||
      label="创建时间"
 | 
			
		||||
      align="center"
 | 
			
		||||
      prop="createTime"
 | 
			
		||||
      width="100"
 | 
			
		||||
      :formatter="dateFormatter"
 | 
			
		||||
    />
 | 
			
		||||
    <el-table-column
 | 
			
		||||
      label="退款成功时间"
 | 
			
		||||
      align="center"
 | 
			
		||||
      prop="successTime"
 | 
			
		||||
      width="100"
 | 
			
		||||
      :formatter="dateFormatter"
 | 
			
		||||
    />
 | 
			
		||||
    <el-table-column
 | 
			
		||||
      label="操作"
 | 
			
		||||
      align="center"
 | 
			
		||||
      fixed="right"
 | 
			
		||||
      class-name="small-padding fixed-width"
 | 
			
		||||
    >
 | 
			
		||||
      <template #default="scope">
 | 
			
		||||
        <el-button
 | 
			
		||||
          size="small"
 | 
			
		||||
          type="text"
 | 
			
		||||
          icon="el-icon-search"
 | 
			
		||||
          @click="openForm(scope.row.id)"
 | 
			
		||||
          v-hasPermi="['pay:order:query']"
 | 
			
		||||
          >查看详情
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-table-column>
 | 
			
		||||
  </el-table>
 | 
			
		||||
  <content-wrap>
 | 
			
		||||
    <!-- 分页 -->
 | 
			
		||||
    <Pagination
 | 
			
		||||
      :total="total"
 | 
			
		||||
      v-model:page="queryParams.pageNo"
 | 
			
		||||
      v-model:limit="queryParams.pageSize"
 | 
			
		||||
      @pagination="getList"
 | 
			
		||||
    />
 | 
			
		||||
  </content-wrap>
 | 
			
		||||
  <!-- 表单弹窗:预览 -->
 | 
			
		||||
  <RefundForm ref="formRef" @success="getList" />
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts" name="PayRefund">
 | 
			
		||||
import { allSchemas } from './refund.data'
 | 
			
		||||
<script setup lang="ts" name="Refund">
 | 
			
		||||
import * as AppApi from '@/api/pay/app'
 | 
			
		||||
import * as MerchantApi from '@/api/pay/merchant'
 | 
			
		||||
import * as RefundApi from '@/api/pay/refund'
 | 
			
		||||
import { DICT_TYPE, getDictOptions } from '@/utils/dict'
 | 
			
		||||
import download from '@/utils/download'
 | 
			
		||||
import { dateFormatter } from '@/utils/formatTime'
 | 
			
		||||
import RefundForm from '@/views/pay/refund/refundForm.vue'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
 | 
			
		||||
// 列表相关的变量
 | 
			
		||||
const [registerTable, { exportList }] = useXTable({
 | 
			
		||||
  allSchemas: allSchemas,
 | 
			
		||||
  getListApi: RefundApi.getRefundPage,
 | 
			
		||||
  exportListApi: RefundApi.exportRefund
 | 
			
		||||
const merchantLoading = ref(false) // 商户加载遮罩层
 | 
			
		||||
const message = useMessage() // 消息弹窗
 | 
			
		||||
const appList = ref([]) // 支付应用列表集合
 | 
			
		||||
const merchantList = ref([]) // 商户列表
 | 
			
		||||
const exportLoading = ref(false) // 导出等待
 | 
			
		||||
const loading = ref(false) // 列表遮罩层
 | 
			
		||||
const total = ref(0) // 列表的总页数
 | 
			
		||||
const list = ref([]) // 列表的数据
 | 
			
		||||
const queryFormRef = ref() // 搜索的表单
 | 
			
		||||
const queryParams = reactive({
 | 
			
		||||
  pageNo: 1,
 | 
			
		||||
  pageSize: 10,
 | 
			
		||||
  merchantId: undefined,
 | 
			
		||||
  appId: undefined,
 | 
			
		||||
  channelId: undefined,
 | 
			
		||||
  channelCode: undefined,
 | 
			
		||||
  orderId: undefined,
 | 
			
		||||
  tradeNo: undefined,
 | 
			
		||||
  merchantOrderId: undefined,
 | 
			
		||||
  merchantRefundNo: undefined,
 | 
			
		||||
  notifyUrl: undefined,
 | 
			
		||||
  notifyStatus: undefined,
 | 
			
		||||
  status: undefined,
 | 
			
		||||
  type: undefined,
 | 
			
		||||
  payAmount: undefined,
 | 
			
		||||
  refundAmount: undefined,
 | 
			
		||||
  reason: undefined,
 | 
			
		||||
  userIp: undefined,
 | 
			
		||||
  channelOrderNo: undefined,
 | 
			
		||||
  channelRefundNo: undefined,
 | 
			
		||||
  channelErrorCode: undefined,
 | 
			
		||||
  channelErrorMsg: undefined,
 | 
			
		||||
  channelExtras: undefined,
 | 
			
		||||
  expireTime: [],
 | 
			
		||||
  successTime: [],
 | 
			
		||||
  notifyTime: [],
 | 
			
		||||
  createTime: []
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
// ========== CRUD 相关 ==========
 | 
			
		||||
const dialogVisible = ref(false) // 是否显示弹出层
 | 
			
		||||
const detailData = ref() // 详情 Ref
 | 
			
		||||
 | 
			
		||||
// 详情操作
 | 
			
		||||
const handleDetail = async (rowId: number) => {
 | 
			
		||||
  // 设置数据
 | 
			
		||||
  detailData.value = RefundApi.getRefund(rowId)
 | 
			
		||||
  dialogVisible.value = true
 | 
			
		||||
/**
 | 
			
		||||
 * 根据商户 ID 查询支付应用信息
 | 
			
		||||
 */
 | 
			
		||||
const handleGetAppListByMerchantId = () => {
 | 
			
		||||
  queryParams.appId = undefined
 | 
			
		||||
  if (queryParams.merchantId) {
 | 
			
		||||
    AppApi.getAppListByMerchantId(queryParams.merchantId).then((response) => {
 | 
			
		||||
      appList.value = response.data
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 根据商户名称模糊匹配商户信息
 | 
			
		||||
 * @param name 商户名称
 | 
			
		||||
 */
 | 
			
		||||
const handleGetMerchantListByName = async (name) => {
 | 
			
		||||
  merchantList.value = await MerchantApi.getMerchantListByName(name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 搜索按钮操作 */
 | 
			
		||||
const handleQuery = () => {
 | 
			
		||||
  queryParams.pageNo = 1
 | 
			
		||||
  getList()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 查询列表 */
 | 
			
		||||
const getList = async () => {
 | 
			
		||||
  loading.value = true
 | 
			
		||||
  try {
 | 
			
		||||
    const data = await RefundApi.getRefundPage(queryParams)
 | 
			
		||||
    list.value = data.list
 | 
			
		||||
    total.value = data.total
 | 
			
		||||
  } finally {
 | 
			
		||||
    loading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 重置按钮操作 */
 | 
			
		||||
const resetQuery = () => {
 | 
			
		||||
  queryFormRef.value.resetFields()
 | 
			
		||||
  handleQuery()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 导出按钮操作 */
 | 
			
		||||
const handleExport = async () => {
 | 
			
		||||
  // 导出的二次确认
 | 
			
		||||
  await message.exportConfirm()
 | 
			
		||||
  // 发起导出
 | 
			
		||||
  exportLoading.value = true
 | 
			
		||||
  const data = await RefundApi.exportRefund(queryParams)
 | 
			
		||||
  download.excel(data, '退款订单.xls')
 | 
			
		||||
}
 | 
			
		||||
/** 预览详情 */
 | 
			
		||||
const formRef = ref()
 | 
			
		||||
const openForm = (id?: number) => {
 | 
			
		||||
  formRef.value.open(id)
 | 
			
		||||
}
 | 
			
		||||
/** 初始化 **/
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
  await getList()
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.order-font {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  padding: 2px 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,173 +0,0 @@
 | 
			
		|||
import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
 | 
			
		||||
// CrudSchema
 | 
			
		||||
const crudSchemas = reactive<VxeCrudSchema>({
 | 
			
		||||
  primaryKey: 'id',
 | 
			
		||||
  primaryType: 'seq',
 | 
			
		||||
  primaryTitle: '序号',
 | 
			
		||||
  action: true,
 | 
			
		||||
  columns: [
 | 
			
		||||
    {
 | 
			
		||||
      title: '商户编号',
 | 
			
		||||
      field: 'merchantId',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '应用编号',
 | 
			
		||||
      field: 'appId',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道编号',
 | 
			
		||||
      field: 'channelId',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道编码',
 | 
			
		||||
      field: 'channelCode',
 | 
			
		||||
      dictType: DICT_TYPE.PAY_CHANNEL_CODE_TYPE,
 | 
			
		||||
      dictClass: 'number',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '支付订单编号',
 | 
			
		||||
      field: 'orderId',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '交易订单号',
 | 
			
		||||
      field: 'tradeNo',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '商户订单号',
 | 
			
		||||
      field: 'merchantOrderId',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '商户退款单号',
 | 
			
		||||
      field: 'merchantRefundNo',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '回调地址',
 | 
			
		||||
      field: 'notifyUrl',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '回调状态',
 | 
			
		||||
      field: 'notifyStatus',
 | 
			
		||||
      dictType: DICT_TYPE.PAY_ORDER_NOTIFY_STATUS,
 | 
			
		||||
      dictClass: 'number',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款类型',
 | 
			
		||||
      field: 'type',
 | 
			
		||||
      dictType: DICT_TYPE.PAY_REFUND_ORDER_TYPE,
 | 
			
		||||
      dictClass: 'number',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: t('common.status'),
 | 
			
		||||
      field: 'status',
 | 
			
		||||
      dictType: DICT_TYPE.PAY_REFUND_ORDER_STATUS,
 | 
			
		||||
      dictClass: 'number',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '支付金额',
 | 
			
		||||
      field: 'payAmount',
 | 
			
		||||
      formatter: 'formatAmount',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款金额',
 | 
			
		||||
      field: 'refundAmount',
 | 
			
		||||
      formatter: 'formatAmount',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款原因',
 | 
			
		||||
      field: 'reason',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '用户IP',
 | 
			
		||||
      field: 'userIp',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道订单号',
 | 
			
		||||
      field: 'channelOrderNo',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道退款单号',
 | 
			
		||||
      field: 'channelRefundNo',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道调用报错时',
 | 
			
		||||
      field: 'channelErrorCode'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '渠道调用报错时',
 | 
			
		||||
      field: 'channelErrorMsg'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '支付渠道的额外参数',
 | 
			
		||||
      field: 'channelExtras'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款失效时间',
 | 
			
		||||
      field: 'expireTime',
 | 
			
		||||
      formatter: 'formatDate',
 | 
			
		||||
      isForm: false,
 | 
			
		||||
      search: {
 | 
			
		||||
        show: true,
 | 
			
		||||
        itemRender: {
 | 
			
		||||
          name: 'XDataTimePicker'
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款成功时间',
 | 
			
		||||
      field: 'successTime',
 | 
			
		||||
      formatter: 'formatDate',
 | 
			
		||||
      isForm: false,
 | 
			
		||||
      search: {
 | 
			
		||||
        show: true,
 | 
			
		||||
        itemRender: {
 | 
			
		||||
          name: 'XDataTimePicker'
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '退款通知时间',
 | 
			
		||||
      field: 'notifyTime',
 | 
			
		||||
      formatter: 'formatDate',
 | 
			
		||||
      isForm: false,
 | 
			
		||||
      search: {
 | 
			
		||||
        show: true,
 | 
			
		||||
        itemRender: {
 | 
			
		||||
          name: 'XDataTimePicker'
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: t('common.createTime'),
 | 
			
		||||
      field: 'createTime',
 | 
			
		||||
      formatter: 'formatDate',
 | 
			
		||||
      isForm: false,
 | 
			
		||||
      search: {
 | 
			
		||||
        show: true,
 | 
			
		||||
        itemRender: {
 | 
			
		||||
          name: 'XDataTimePicker'
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,154 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <Dialog :title="dialogTitle" v-model="dialogVisible" width="50%">
 | 
			
		||||
    <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
      <el-descriptions-item label="商户名称">{{ refundDetail.merchantName }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="应用名称">{{ refundDetail.appName }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="商品名称">{{ refundDetail.subject }}</el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
    <el-divider />
 | 
			
		||||
    <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
      <el-descriptions-item label="商户退款单号">
 | 
			
		||||
        <el-tag size="small">{{ refundDetail.merchantRefundNo }}</el-tag>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="商户订单号"
 | 
			
		||||
        >{{ refundDetail.merchantOrderId }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
    <el-divider />
 | 
			
		||||
    <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
      <el-descriptions-item label="支付金额">
 | 
			
		||||
        {{ parseFloat(refundDetail.payAmount / 100).toFixed(2) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款金额" size="small">
 | 
			
		||||
        <el-tag class="tag-purple" size="small">
 | 
			
		||||
          {{ parseFloat(refundDetail.refundAmount / 100).toFixed(2) }}
 | 
			
		||||
        </el-tag>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款类型">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="refundDetail.type" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款状态">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="refundDetail.status" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="创建时间"
 | 
			
		||||
        >{{ formatDate(refundDetail.createTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款成功时间"
 | 
			
		||||
        >{{ formatDate(refundDetail.successTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款失效时间"
 | 
			
		||||
        >{{ formatDate(refundDetail.expireTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="更新时间"
 | 
			
		||||
        >{{ formatDate(refundDetail.updateTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
    <el-divider />
 | 
			
		||||
    <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
      <el-descriptions-item label="支付渠道">
 | 
			
		||||
        {{ refundDetail.channelCodeName }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="支付IP" size="small">
 | 
			
		||||
        {{ refundDetail.userIp }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="回调地址">{{ refundDetail.notifyUrl }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="回调状态">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="refundDetail.notifyStatus" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="回调时间"
 | 
			
		||||
        >{{ formatDate(refundDetail.notifyTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
    <el-divider />
 | 
			
		||||
    <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
      <el-descriptions-item label="渠道订单号"
 | 
			
		||||
        >{{ refundDetail.channelOrderNo }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="渠道退款单号"
 | 
			
		||||
        >{{ refundDetail.channelRefundNo }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="渠道错误码"
 | 
			
		||||
        >{{ refundDetail.channelErrorCode }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="渠道错误码描述"
 | 
			
		||||
        >{{ refundDetail.channelErrorMsg }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
    <br />
 | 
			
		||||
    <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
 | 
			
		||||
      <el-descriptions-item label="渠道额外参数"
 | 
			
		||||
        >{{ refundDetail.channelExtras }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="退款原因">{{ refundDetail.reason }}</el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
  </Dialog>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts" name="refundForm">
 | 
			
		||||
import { DICT_TYPE } from '@/utils/dict'
 | 
			
		||||
import * as RefundApi from '@/api/pay/refund'
 | 
			
		||||
import { formatDate } from '@/utils/formatTime'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
// const message = useMessage() // 消息弹窗
 | 
			
		||||
const dialogVisible = ref(false) // 弹窗的是否展示
 | 
			
		||||
const dialogTitle = ref('退款订单详情') // 弹窗的标题
 | 
			
		||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 | 
			
		||||
const defaultrefundDetail = {
 | 
			
		||||
  id: null,
 | 
			
		||||
  appId: null,
 | 
			
		||||
  appName: '',
 | 
			
		||||
  channelCode: '',
 | 
			
		||||
  channelCodeName: '',
 | 
			
		||||
  channelErrorCode: '',
 | 
			
		||||
  channelErrorMsg: '',
 | 
			
		||||
  channelExtras: '',
 | 
			
		||||
  channelId: null,
 | 
			
		||||
  channelOrderNo: '',
 | 
			
		||||
  channelRefundNo: '',
 | 
			
		||||
  createTime: null,
 | 
			
		||||
  expireTime: null,
 | 
			
		||||
  merchantId: null,
 | 
			
		||||
  merchantName: '',
 | 
			
		||||
  merchantOrderId: '',
 | 
			
		||||
  merchantRefundNo: '',
 | 
			
		||||
  notifyStatus: null,
 | 
			
		||||
  notifyTime: null,
 | 
			
		||||
  notifyUrl: '',
 | 
			
		||||
  orderId: null,
 | 
			
		||||
  payAmount: null,
 | 
			
		||||
  reason: '',
 | 
			
		||||
  refundAmount: null,
 | 
			
		||||
  status: null,
 | 
			
		||||
  subject: '',
 | 
			
		||||
  successTime: null,
 | 
			
		||||
  tradeNo: '',
 | 
			
		||||
  type: null,
 | 
			
		||||
  userIp: ''
 | 
			
		||||
}
 | 
			
		||||
const refundDetail = ref(JSON.parse(JSON.stringify(defaultrefundDetail)))
 | 
			
		||||
 | 
			
		||||
/** 打开弹窗 */
 | 
			
		||||
const open = async (id?: number) => {
 | 
			
		||||
  dialogVisible.value = true
 | 
			
		||||
  dialogTitle.value = t('action.preview')
 | 
			
		||||
  // 修改时,设置数据
 | 
			
		||||
  if (id) {
 | 
			
		||||
    formLoading.value = true
 | 
			
		||||
    try {
 | 
			
		||||
      refundDetail.value = await RefundApi.getRefundApi(id)
 | 
			
		||||
    } finally {
 | 
			
		||||
      formLoading.value = false
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
.tag-purple {
 | 
			
		||||
  color: #722ed1;
 | 
			
		||||
  background: #f9f0ff;
 | 
			
		||||
  border-color: #d3adf7;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
		Loading…
	
		Reference in New Issue