<template>
<cl-crud ref="Crud">
<cl-row>
<!-- 刷新按钮 -->
<cl-refresh-btn />
<!-- 新增按钮 -->
<cl-add-btn />
<!-- 删除按钮 -->
<!-- <cl-multi-delete-btn /> -->
<!-- 订单类型 -->
<cl-filter label="订单类型">
<cl-select :options="options.order_type" prop="order_type" :width="120" />
</cl-filter>
<!-- 订单状态 -->
<cl-filter label="订单状态">
<cl-select :options="options.status" prop="status" :width="120" />
</cl-filter>
<cl-flex1 />
<!-- 关键字搜索 -->
<cl-search-key />
</cl-row>
<cl-row>
<!-- 数据表格 -->
<cl-table ref="Table">
<!-- 审批 -->
<template #slot-btn="{ scope }">
<el-button
v-permission="service.base.sys.user.permission.move"
type="primary"
size="small"
:disabled="scope.row.status !== 'PENDING'"
@click="approve(scope.row)"
>
审批
</el-button>
</template>
<template #slot-info-btn="{ scope }">
<el-button
v-permission="service.base.sys.user.permission.move"
type="text"
size="small"
:disabled="scope.row.status === 'PENDING'"
@click="viewDetail(scope.row)"
>
详情
</el-button>
</template>
</cl-table>
</cl-row>
<cl-row>
<cl-flex1 />
<!-- 分页控件 -->
<cl-pagination />
</cl-row>
<!-- 新增、编辑 -->
<cl-upsert ref="Upsert" />
<!-- 审批弹窗 -->
<el-dialog
v-model="dialogVisible"
title="审批详情"
width="800px"
:close-on-click-modal="false"
>
<el-form :model="form" label-width="100px">
<el-form-item label="申请编号">
<el-input v-model="form.id" disabled />
</el-form-item>
<el-form-item label="申请人">
<el-input v-model="form.mch_id" disabled />
</el-form-item>
<el-form-item label="申请时间">
<el-input v-model="form.createTime" disabled />
</el-form-item>
<el-form-item label="订单类型">
<el-tag
:type="getOrderTypeTag(form.order_type).type"
effect="light"
class="order-type-tag"
>
{{ getOrderTypeTag(form.order_type).label }}
</el-tag>
</el-form-item>
<el-form-item label="订单状态" v-if="form.order_status !== 'PENDING'">
<el-tag
:type="getStatusTag(form.order_status).type"
effect="light"
class="status-tag"
>
{{ getStatusTag(form.order_status).label }}
</el-tag>
</el-form-item>
<el-form-item label="审批意见" v-if="form.order_status !== 'PENDING'">
<el-input type="textarea" :rows="3" :value="form.remark || '无'" disabled />
</el-form-item>
<el-form-item label="订单详情">
<div class="order-info">
<template v-if="form.order_type === 'APPROVE_TRANSFER'">
<div class="payment-info">
<div class="info-section">
<div class="section-title">转账信息</div>
<div class="info-item">
<span class="label">请求ID:</span>
<span class="value">{{ orderInfo.request_id }}</span>
</div>
<div class="info-item">
<span class="label">付款账户:</span>
<span class="value">{{ orderInfo.from_account_id }}</span>
</div>
<div class="info-item">
<span class="label">收款账户:</span>
<span class="value">{{ orderInfo.to_account_id }}</span>
</div>
<div class="info-item">
<span class="label">金额:</span>
<span class="value highlight"
>{{ (orderInfo.amount / 100).toFixed(2) }}
{{ orderInfo.currency }}</span
>
</div>
<div class="info-item">
<span class="label">用途:</span>
<span class="value">{{ orderInfo.purpose }}</span>
</div>
</div>
</div>
</template>
<template v-else-if="form.order_type === 'APPROVE_PAYMENT'">
<div class="payment-info">
<div class="info-section">
<div class="section-title">基本信息</div>
<div class="info-item">
<span class="label">请求ID:</span>
<span class="value">{{ orderInfo.request_id }}</span>
</div>
<div class="info-item">
<span class="label">付款账户:</span>
<span class="value">{{ orderInfo.from_account_id }}</span>
</div>
<div class="info-item">
<span class="label">金额:</span>
<span class="value highlight"
>{{ (orderInfo.amount / 100).toFixed(2) }}
{{ orderInfo.currency }}</span
>
</div>
<div class="info-item">
<span class="label">用途:</span>
<span class="value">{{ orderInfo.purpose }}</span>
</div>
<div class="info-item">
<span class="label">备注:</span>
<span class="value">{{ orderInfo.comment }}</span>
</div>
</div>
<div class="info-section">
<div class="section-title">收款方信息</div>
<div class="info-item">
<span class="label">实体类型:</span>
<span class="value">{{
orderInfo.beneficiary.legal_entity_type
}}</span>
</div>
<div class="info-item">
<span class="label">支付类型:</span>
<span class="value">{{
orderInfo.beneficiary.payment_type
}}</span>
</div>
<div class="info-item">
<span class="label">地区:</span>
<span class="value">{{
orderInfo.beneficiary.region
}}</span>
</div>
<div class="info-item">
<span class="label">银行名称:</span>
<span class="value">{{
orderInfo.beneficiary.bank_name
}}</span>
</div>
<div class="info-item">
<span class="label">账户持有人:</span>
<span class="value">{{
orderInfo.beneficiary.account_holder_name
}}</span>
</div>
<div class="info-item">
<span class="label">账号:</span>
<span class="value">{{
orderInfo.beneficiary.account_number
}}</span>
</div>
<div class="info-item">
<span class="label">BIC号码:</span>
<span class="value">{{
orderInfo.beneficiary.bic_number
}}</span>
</div>
<div class="info-item">
<span class="label">地址:</span>
<span class="value">{{
orderInfo.beneficiary.address
}}</span>
</div>
</div>
</div>
</template>
<template v-else-if="form.order_type === 'APPROVE_DEPOSIT'">
<div class="payment-info">
<div class="info-section">
<div class="section-title">入账信息</div>
<div class="info-item">
<span class="label">请求ID:</span>
<span class="value">{{ orderInfo.request_id }}</span>
</div>
<div class="info-item">
<span class="label">收款账户:</span>
<span class="value">{{ orderInfo.to_account_id }}</span>
</div>
<div class="info-item">
<span class="label">金额:</span>
<span class="value highlight"
>{{ (orderInfo.amount / 100).toFixed(2) }}
{{ orderInfo.currency }}</span
>
</div>
<div class="info-item">
<span class="label">用途:</span>
<span class="value">{{ orderInfo.purpose }}</span>
</div>
</div>
</div>
</template>
<template v-else-if="form.order_type === 'APPROVE_EXCHANGE'">
<div class="payment-info">
<div class="info-section">
<div class="section-title">换汇信息</div>
<div class="info-item">
<span class="label">请求ID:</span>
<span class="value">{{ orderInfo.request_id }}</span>
</div>
<div class="info-item">
<span class="label">账户:</span>
<span class="value">{{ orderInfo.from_account_id }}</span>
</div>
<div class="info-item">
<span class="label">卖出币种:</span>
<span class="value">{{ orderInfo.sell_currency }}</span>
</div>
<div class="info-item">
<span class="label">买入币种:</span>
<span class="value">{{ orderInfo.buy_currency }}</span>
</div>
<div class="info-item">
<span class="label">买入金额:</span>
<span class="value highlight"
>{{ (orderInfo.buy_amount / 100).toFixed(2) }}
{{ orderInfo.buy_currency }}</span
>
</div>
<div class="info-item">
<span class="label">业务类型:</span>
<span class="value">{{ orderInfo.biz_type }}</span>
</div>
<div class="info-item" v-if="orderInfo.reference">
<span class="label">参考号:</span>
<span class="value">{{ orderInfo.reference }}</span>
</div>
</div>
</div>
</template>
<template v-else-if="form.order_type === 'APPROVE_ACCOUNT'">
<div class="payment-info">
<div class="info-section">
<div class="section-title">基础信息</div>
<div class="info-item" v-if="false">
<span class="label">请求ID:</span>
<span class="value">{{ orderInfo.request_id }}</span>
</div>
<div class="info-item">
<span class="label">商户ID:</span>
<span class="value">{{ orderInfo.legal_entity.mchId }}</span>
</div>
<div class="info-item" v-if="false">
<span class="label">实体类型:</span>
<span class="value highlight">{{ orderInfo.legal_entity.type }}</span>
</div>
<div class="info-item">
<span class="label">地区:</span>
<span class="value">{{ orderInfo.legal_entity.region }}</span>
</div>
<div class="info-item">
<span class="label">公司名称:</span>
<span class="value">{{ orderInfo.legal_entity.company_name_en }}</span>
</div>
<div class="info-item">
<span class="label">成立日期:</span>
<span class="value">{{ orderInfo.legal_entity.dob }}</span>
</div>
<div class="info-item">
<span class="label">联系电话:</span>
<span class="value">{{ orderInfo.legal_entity.phone_country }}-{{ orderInfo.legal_entity.phone }}</span>
</div>
<div class="info-item">
<span class="label">电子邮箱:</span>
<span class="value">{{ orderInfo.legal_entity.email }}</span>
</div>
<div class="info-item">
<span class="label">公司地址:</span>
<span class="value">{{ orderInfo.legal_entity.address }}</span>
</div>
<div class="info-item">
<span class="label">公司类型:</span>
<span class="value">{{ orderInfo.legal_entity.company_type }}</span>
</div>
<div class="info-item">
<span class="label">经营范围:</span>
<span class="value">{{ orderInfo.legal_entity.business_scope }}</span>
</div>
<div class="info-item">
<span class="label">所属行业:</span>
<span class="value">{{ orderInfo.legal_entity.industry }}</span>
</div>
<div class="info-item">
<span class="label">企业类型:</span>
<span class="value">{{ orderInfo.legal_entity.enterprise_type }}</span>
</div>
</div>
<div class="info-section">
<div class="section-title">企业证件信息</div>
<div class="info-item">
<span class="label">BR号码:</span>
<span class="value">{{ orderInfo.legal_entity.br_number }}</span>
</div>
<div class="info-item">
<span class="label">BR证书:</span>
<span class="value">
<template v-if="isImageFile(orderInfo.legal_entity.br_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(orderInfo.legal_entity.br_image) || orderInfo.legal_entity.br_image"
:preview-src-list="[imageUrlCache.get(orderInfo.legal_entity.br_image) || orderInfo.legal_entity.br_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(orderInfo.legal_entity.br_image)">
下载文件
</el-button>
</template>
</span>
</div>
<div class="info-item">
<span class="label">CR号码:</span>
<span class="value">{{ orderInfo.legal_entity.cr_number }}</span>
</div>
<div class="info-item">
<span class="label">CR证书:</span>
<span class="value">
<template v-if="isImageFile(orderInfo.legal_entity.cr_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(orderInfo.legal_entity.cr_image) || orderInfo.legal_entity.cr_image"
:preview-src-list="[imageUrlCache.get(orderInfo.legal_entity.cr_image) || orderInfo.legal_entity.cr_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(orderInfo.legal_entity.cr_image)">
下载文件
</el-button>
</template>
</span>
</div>
<div class="info-item">
<span class="label">NC1文件:</span>
<span class="value">
<div v-for="(image, index) in orderInfo.legal_entity.nc1_images" :key="index">
<template v-if="isImageFile(image)">
<el-image
style="width: 100px; height: 100px; margin-right: 10px"
:src="imageUrlCache.get(image) || image"
:preview-src-list="orderInfo.legal_entity.nc1_images.map(img => imageUrlCache.get(img) || img)"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(image)">
下载文件
</el-button>
</template>
</div>
</span>
</div>
<div class="info-item">
<span class="label">股权结构:</span>
<span class="value">
<template v-if="isImageFile(orderInfo.legal_entity.ownership_structure_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(orderInfo.legal_entity.ownership_structure_image) || orderInfo.legal_entity.ownership_structure_image"
:preview-src-list="[imageUrlCache.get(orderInfo.legal_entity.ownership_structure_image) || orderInfo.legal_entity.ownership_structure_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(orderInfo.legal_entity.ownership_structure_image)">
下载文件
</el-button>
</template>
</span>
</div>
<div class="info-item">
<span class="label">公司章程:</span>
<span class="value">
<template v-if="isImageFile(orderInfo.legal_entity.aoa)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(orderInfo.legal_entity.aoa) || orderInfo.legal_entity.aoa"
:preview-src-list="[imageUrlCache.get(orderInfo.legal_entity.aoa) || orderInfo.legal_entity.aoa]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(orderInfo.legal_entity.aoa)">
下载文件
</el-button>
</template>
</span>
</div>
</div>
<div class="info-section">
<div class="section-title">公司法人或董事</div>
<div class="info-item">
<span class="label">姓名:</span>
<span class="value">{{ orderInfo.legal_entity.owner.name }}</span>
</div>
<div class="info-item">
<span class="label">证件类型:</span>
<span class="value">{{ orderInfo.legal_entity.owner.id_type }}</span>
</div>
<div class="info-item">
<span class="label">证件号码:</span>
<span class="value">{{ orderInfo.legal_entity.owner.id_card_number }}</span>
</div>
<div class="info-item">
<span class="label">出生日期:</span>
<span class="value">{{ orderInfo.legal_entity.owner.dob }}</span>
</div>
<div class="info-item">
<span class="label">地址:</span>
<span class="value">{{ orderInfo.legal_entity.owner.address }}</span>
</div>
<div class="info-item">
<span class="label">证件照片:</span>
<span class="value">
<div style="display: flex; gap: 10px;">
<template v-if="isImageFile(orderInfo.legal_entity.owner.id_card_front_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(orderInfo.legal_entity.owner.id_card_front_image) || orderInfo.legal_entity.owner.id_card_front_image"
:preview-src-list="[imageUrlCache.get(orderInfo.legal_entity.owner.id_card_front_image) || orderInfo.legal_entity.owner.id_card_front_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(orderInfo.legal_entity.owner.id_card_front_image)">
下载正面照片
</el-button>
</template>
<template v-if="isImageFile(orderInfo.legal_entity.owner.id_card_back_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(orderInfo.legal_entity.owner.id_card_back_image) || orderInfo.legal_entity.owner.id_card_back_image"
:preview-src-list="[imageUrlCache.get(orderInfo.legal_entity.owner.id_card_back_image) || orderInfo.legal_entity.owner.id_card_back_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(orderInfo.legal_entity.owner.id_card_back_image)">
下载背面照片
</el-button>
</template>
<template v-if="isImageFile(orderInfo.legal_entity.owner.id_card_handheld_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(orderInfo.legal_entity.owner.id_card_handheld_image) || orderInfo.legal_entity.owner.id_card_handheld_image"
:preview-src-list="[imageUrlCache.get(orderInfo.legal_entity.owner.id_card_handheld_image) || orderInfo.legal_entity.owner.id_card_handheld_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(orderInfo.legal_entity.owner.id_card_handheld_image)">
下载手持照片
</el-button>
</template>
</div>
</span>
</div>
<div class="info-item">
<span class="label">地址证明:</span>
<span class="value">
<template v-if="isImageFile(orderInfo.legal_entity.owner.address_proof_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(orderInfo.legal_entity.owner.address_proof_image) || orderInfo.legal_entity.owner.address_proof_image"
:preview-src-list="[imageUrlCache.get(orderInfo.legal_entity.owner.address_proof_image) || orderInfo.legal_entity.owner.address_proof_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(orderInfo.legal_entity.owner.address_proof_image)">
下载地址证明
</el-button>
</template>
</span>
</div>
</div>
<div class="info-section" v-if="orderInfo.legal_entity.shareholders && orderInfo.legal_entity.shareholders.length > 0">
<div class="section-title">公司股份占比25%及以上的股东</div>
<div v-for="(shareholder, index) in orderInfo.legal_entity.shareholders" :key="index" class="shareholder-info">
<div class="sub-title">股东 {{ index + 1 }}</div>
<div class="info-item">
<span class="label">姓名:</span>
<span class="value">{{ shareholder.name }}</span>
</div>
<div class="info-item">
<span class="label">持股比例:</span>
<span class="value">{{ Number(shareholder.ratio) * 100 }}%</span>
</div>
<div class="info-item">
<span class="label">证件类型:</span>
<span class="value">{{ shareholder.id_type }}</span>
</div>
<div class="info-item">
<span class="label">证件号码:</span>
<span class="value">{{ shareholder.id_card_number }}</span>
</div>
<div class="info-item">
<span class="label">出生日期:</span>
<span class="value">{{ shareholder.dob }}</span>
</div>
<div class="info-item">
<span class="label">地址:</span>
<span class="value">{{ shareholder.address }}</span>
</div>
<div class="info-item">
<span class="label">证件照片:</span>
<span class="value">
<div style="display: flex; gap: 10px;">
<template v-if="isImageFile(shareholder.id_card_front_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(shareholder.id_card_front_image) || shareholder.id_card_front_image"
:preview-src-list="[imageUrlCache.get(shareholder.id_card_front_image) || shareholder.id_card_front_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(shareholder.id_card_front_image)">
下载正面照片
</el-button>
</template>
<template v-if="isImageFile(shareholder.id_card_back_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(shareholder.id_card_back_image) || shareholder.id_card_back_image"
:preview-src-list="[imageUrlCache.get(shareholder.id_card_back_image) || shareholder.id_card_back_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(shareholder.id_card_back_image)">
下载背面照片
</el-button>
</template>
<template v-if="isImageFile(shareholder.id_card_handheld_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(shareholder.id_card_handheld_image) || shareholder.id_card_handheld_image"
:preview-src-list="[imageUrlCache.get(shareholder.id_card_handheld_image) || shareholder.id_card_handheld_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(shareholder.id_card_handheld_image)">
下载手持照片
</el-button>
</template>
</div>
</span>
</div>
<div class="info-item">
<span class="label">地址证明:</span>
<span class="value">
<template v-if="isImageFile(shareholder.address_proof_image)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(shareholder.address_proof_image) || shareholder.address_proof_image"
:preview-src-list="[imageUrlCache.get(shareholder.address_proof_image) || shareholder.address_proof_image]"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(shareholder.address_proof_image)">
下载地址证明
</el-button>
</template>
</span>
</div>
</div>
</div>
</div>
</template>
<template v-else-if="form.order_type === 'APPROVE_KYC'">
<div class="payment-info">
<div class="info-section">
<div class="section-title">KYC认证信息</div>
<div class="info-item">
<span class="label">请求ID:</span>
<span class="value">{{ orderInfo.request_id }}</span>
</div>
<div class="info-item">
<span class="label">商户ID:</span>
<span class="value">{{ orderInfo.mch_id }}</span>
</div>
<div class="info-item">
<span class="label">认证类型:</span>
<span class="value highlight">{{
orderInfo.kyc_type
}}</span>
</div>
</div>
</div>
</template>
<template v-else-if="form.order_type === 'APPROVE_APPLICATIONS'">
<div class="payment-info">
<div class="info-section">
<div class="section-title">基本信息</div>
<div class="info-item">
<span class="label">请求ID:</span>
<span class="value">{{ orderInfo.request_id }}</span>
</div>
<div class="info-item">
<span class="label">商户ID:</span>
<span class="value">{{ orderInfo.mch_id }}</span>
</div>
<div class="info-item">
<span class="label">用途:</span>
<span class="value">{{ orderInfo.purpose }}</span>
</div>
<div class="info-item">
<span class="label">币种:</span>
<span class="value">{{ orderInfo.currency }}</span>
</div>
<div class="info-item">
<span class="label">支付类型:</span>
<span class="value">{{ orderInfo.payment_type }}</span>
</div>
</div>
<div class="info-section">
<div class="section-title">店铺信息</div>
<div class="info-item">
<span class="label">店铺名称:</span>
<span class="value">{{ orderInfo.additional_info?.store_name }}</span>
</div>
<div class="info-item">
<span class="label">店铺地址:</span>
<span class="value">
{{ orderInfo.additional_info?.store_address?.region }}
{{ orderInfo.additional_info?.store_address?.state_or_province }}
{{ orderInfo.additional_info?.store_address?.city }}
{{ orderInfo.additional_info?.store_address?.street }}
{{ orderInfo.additional_info?.store_address?.zip_code }}
</span>
</div>
<div class="info-item">
<span class="label">业务类别:</span>
<span class="value">{{ orderInfo.additional_info?.business_category }}</span>
</div>
<div class="info-item">
<span class="label">业务地区:</span>
<span class="value">{{ orderInfo.additional_info?.business_regions?.join(', ') }}</span>
</div>
</div>
<div class="info-section">
<div class="section-title">销售信息</div>
<div class="info-item">
<span class="label">线上销售方式:</span>
<span class="value">{{ orderInfo.additional_info?.online_sales_method }}</span>
</div>
<div class="info-item">
<span class="label">付款方:</span>
<span class="value">{{ orderInfo.additional_info?.payer_party }}</span>
</div>
<div class="info-item">
<span class="label">付款方账户:</span>
<span class="value">{{ orderInfo.additional_info?.payer_party_account }}</span>
</div>
</div>
<div class="info-section">
<div class="section-title">店铺照片</div>
<div class="info-item">
<span class="value">
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
<template v-for="(photo, index) in orderInfo.additional_info?.store_photos" :key="index">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(photo) || photo"
:preview-src-list="orderInfo.additional_info?.store_photos?.map(p => imageUrlCache.get(p) || p)"
/>
</template>
</div>
</span>
</div>
</div>
<div class="info-section">
<div class="section-title">主营业务证明材料</div>
<div class="info-item">
<span class="value">
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
<template v-for="(doc, index) in orderInfo.additional_info?.documents" :key="index">
<template v-if="isImageFile(doc)">
<el-image
style="width: 100px; height: 100px"
:src="imageUrlCache.get(doc) || doc"
:preview-src-list="orderInfo.additional_info?.documents?.map(d => imageUrlCache.get(d) || d)"
/>
</template>
<template v-else>
<el-button type="primary" link @click="downloadFile(doc)">
下载文件
</el-button>
</template>
</template>
</div>
</span>
</div>
</div>
</div>
</template>
</div>
</el-form-item>
<el-form-item label="审批结果" v-if="form.order_status === 'PENDING'" required>
<el-radio-group v-model="form.status">
<el-radio label="APPROVED">通过</el-radio>
<el-radio label="REJECTED">拒绝</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="审批意见" v-if="form.order_status === 'PENDING'" required>
<el-input
type="textarea"
v-model="form.remark"
:rows="3"
placeholder="请输入审批意见"
:rules="[
{ required: true, message: '请输入审批意见', trigger: 'blur' },
{ min: 2, max: 200, message: '长度在 2 到 200 个字符', trigger: 'blur' }
]"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button
type="primary"
@click="handleSubmit"
:loading="loading"
:disabled="form.order_status !== 'PENDING'"
>确 定</el-button
>
</div>
</template>
</el-dialog>
</cl-crud>
</template>
<script setup lang="ts">
import { useCrud, useTable, useUpsert } from '@cool-vue/crud';
import { useCool } from '/@/cool';
import { ref, reactive, onMounted, computed } from 'vue';
import { ElMessage } from 'element-plus';
const { service } = useCool();
// 弹窗相关
const dialogVisible = ref(false);
const loading = ref(false);
const form = reactive({
id: '',
mch_id: '',
createTime: '',
order_type: '',
order_info: '',
order_status: '',
status: '',
remark: ''
});
const orderInfo = reactive({
request_id: '',
from_account_id: '',
to_account_id: '',
account_id: '',
currency: '',
amount: 0,
purpose: '',
comment: '',
sell_currency: '',
buy_currency: '',
buy_amount: 0,
biz_type: '',
reference: '',
mch_id: '',
account_type: '',
kyc_type: '',
payment_type: '',
additional_info: {
store_address: {
region: '',
state_or_province: '',
city: '',
street: '',
zip_code: ''
},
online_sales_method: '',
offline_sales_method: '',
website_url: '',
store_name: '',
store_photos: [] as string[],
business_category: '',
business_regions: [] as string[],
payer_party: '',
payer_party_account: '',
funds_type: '',
monthly_transaction_count: '',
monthly_transaction_amount: '',
abbreviated_company_name: '',
documents: [] as string[]
},
legal_entity: {
mchId: '',
type: '',
region: '',
name: '',
company_name_en: '',
dob: '',
gender: '',
email: '',
phone_country: '',
phone: '',
address: '',
address_en: '',
company_type: '',
business_scope: '',
industry: '',
website: '',
br_number: '',
br_image: '',
cr_number: '',
cr_image: '',
nc1_images: [] as string[],
ownership_structure_image: '',
aoa: '',
issue_date: '',
expiry_date: '',
enterprise_type: '',
owner: {
type: '',
id_type: '',
region: '',
name: '',
dob: '',
address: '',
id_card_number: '',
id_card_back_image: '',
id_card_front_image: '',
id_card_handheld_image: '',
issue_date: '',
expiry_date: '',
issue_agency: '',
address_proof_image: ''
},
shareholders: [] as Array<{
name: string;
address: string;
dob: string;
region: string;
id_type: string;
id_card_number: string;
id_card_back_image: string;
issue_date: string;
id_card_front_image: string;
expiry_date: string;
issue_agency: string;
ratio: string;
address_proof_image: string;
id_card_handheld_image: string;
type: string;
}>
},
beneficiary: {
legal_entity_type: '',
payment_type: '',
region: '',
bank_name: '',
account_holder_name: '',
account_number: '',
bic_number: '',
address: ''
}
});
// cl-upsert
const Upsert = useUpsert({
items: []
});
// 筛选选项
const options = reactive({
order_type: [
{ label: '全部', value: '' },
{ label: '支付审批', value: 'APPROVE_PAYMENT', type: 'primary' },
{ label: '转账审批', value: 'APPROVE_TRANSFER', type: 'success' },
{ label: '入账审批', value: 'APPROVE_DEPOSIT', type: 'warning' },
{ label: '换汇审批', value: 'APPROVE_EXCHANGE', type: 'info' },
{ label: '开户审批', value: 'APPROVE_ACCOUNT', type: 'danger' },
{ label: '收款账户审批', value: 'APPROVE_APPLICATIONS', type: 'danger' },
{ label: 'KYC认证审批', value: 'APPROVE_KYC', type: 'success' }
],
status: [
{ label: '全部', value: '' },
{ label: '待审批', value: 'PENDING', type: 'warning' },
{ label: '审批中', value: 'PROCESSING', type: 'primary' },
{ label: '已通过', value: 'APPROVED', type: 'success' },
{ label: '已拒绝', value: 'REJECTED', type: 'danger' },
{ label: '已取消', value: 'CANCELED', type: 'info' }
]
});
// cl-table
const Table = useTable({
columns: [
{
type: 'selection',
width: 60
},
{
label: '申请编号',
prop: 'id'
},
{
label: '申请人',
prop: 'mch_id'
},
{
label: '申请时间',
prop: 'createTime'
},
{
label: '订单类型',
prop: 'order_type',
width: 100,
dict: options.order_type.filter(item => item.value).map(item => ({
label: item.label,
value: item.value,
type: item.type
}))
},
{
label: '状态',
prop: 'status',
width: 100,
dict: options.status.filter(item => item.value).map(item => ({
label: item.label,
value: item.value,
type: item.type
}))
},
{
label: '审批时间',
prop: 'updateTime'
},
{
label: '操作',
type: 'op',
width: 140,
buttons: ['slot-btn', 'slot-info-btn']
}
]
});
// cl-crud
const Crud = useCrud(
{
service: service.api.open_order_approve
},
app => {
app.refresh();
}
);
// 刷新
function refresh(params?: any) {
Crud.value?.refresh(params);
}
// 图片URL缓存
const imageUrlCache = reactive(new Map<string, string>());
// 处理文件URL
async function handleFileUrl(url: string) {
if (!url) return '';
// 如果URL已经在缓存中,直接返回
if (imageUrlCache.has(url)) {
return imageUrlCache.get(url);
}
try {
const filePath = await getFilePathByUrl(url);
// 将结果存入缓存
imageUrlCache.set(url, filePath);
return filePath;
} catch (error) {
console.error('获取文件路径失败:', error);
return url;
}
}
// 预加载所有图片URL
async function preloadImageUrls(data: any) {
if (!data) return;
const urls: string[] = [];
// 收集所有图片URL
if (data.legal_entity) {
const { legal_entity } = data;
urls.push(
legal_entity.br_image,
legal_entity.cr_image,
legal_entity.ownership_structure_image,
legal_entity.aoa,
legal_entity.owner?.id_card_front_image,
legal_entity.owner?.id_card_back_image,
legal_entity.owner?.id_card_handheld_image,
legal_entity.owner?.address_proof_image,
...(legal_entity.nc1_images || []),
...(legal_entity.shareholders || []).flatMap((s: any) => [
s.id_card_front_image,
s.id_card_back_image,
s.id_card_handheld_image,
s.address_proof_image
])
);
}
// 添加店铺照片和文档的URL
if (data.additional_info) {
const { additional_info } = data;
urls.push(
...(additional_info.store_photos || []),
...(additional_info.documents || [])
);
}
// 过滤掉空值并去重
const uniqueUrls = [...new Set(urls.filter(Boolean))];
// 预加载所有URL
await Promise.all(uniqueUrls.map(url => handleFileUrl(url)));
}
// 修改 approve 函数
async function approve(row: any) {
// 重置表单
Object.assign(form, {
id: row.id,
mch_id: row.mch_id,
createTime: row.createTime,
order_type: row.order_type,
order_info: JSON.stringify(JSON.parse(row.order_info), null, 2),
status: '',
remark: ''
});
form.order_status = row.status;
form.remark = row.remark;
// 解析订单详情
const orderInfoData = JSON.parse(row.order_info);
Object.assign(orderInfo, orderInfoData);
// 预加载所有图片URL
await preloadImageUrls(orderInfoData);
dialogVisible.value = true;
}
function viewDetail(row: any) {
approve(row);
}
function handleSubmit() {
if (!form.status) {
ElMessage.warning('请选择审批结果');
return;
}
if (!form.remark) {
ElMessage.warning('请输入审批意见');
return;
}
loading.value = true;
service.api.open_order_approve
.approve({
id: form.id,
status: form.status,
remark: form.remark
})
.then(() => {
dialogVisible.value = false;
refresh();
ElMessage.success('审批成功');
})
.catch((err) => {
ElMessage.error(err.message || '审批失败');
})
.finally(() => {
loading.value = false;
});
}
// 获取订单类型标签
function getOrderTypeTag(type: string) {
const dict = {
APPROVE_PAYMENT: { label: '支付审批', type: 'primary' },
APPROVE_TRANSFER: { label: '转账审批', type: 'success' },
APPROVE_DEPOSIT: { label: '入账审批', type: 'warning' },
APPROVE_EXCHANGE: { label: '换汇审批', type: 'info' },
APPROVE_ACCOUNT: { label: '开户审批', type: 'danger' },
APPROVE_APPLICATIONS: { label: '收款账户审批', type: 'danger' },
APPROVE_KYC: { label: 'KYC认证审批', type: 'success' }
};
return dict[type] || { label: type, type: 'info' };
}
// 获取状态标签
function getStatusTag(status: string) {
const dict = {
PENDING: { label: '待审批', type: 'warning' },
PROCESSING: { label: '审批中', type: 'primary' },
APPROVED: { label: '已通过', type: 'success' },
REJECTED: { label: '已拒绝', type: 'danger' },
CANCELED: { label: '已取消', type: 'info' }
};
return dict[status] || { label: status, type: 'info' };
}
// 判断是否为图片文件
function isImageFile(url: string): boolean {
if (!url) return false;
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'];
return imageExtensions.some(ext => url.toLowerCase().endsWith(ext));
}
// 获取文件名
function getFileName(url: string): string {
if (!url) return '';
return url.split('/').pop() || '';
}
// 获取文件路径
async function getFilePathByUrl(url: string) {
if (!url) return '';
try {
const res = await service.api.open_files.getFilePathByUrl({ url });
return res;
} catch (error) {
console.error('获取文件路径失败:', error);
return url;
}
}
// 下载文件
async function downloadFile(url: string) {
try {
const filePath = await getFilePathByUrl(url);
if (!filePath) {
ElMessage.error('获取文件路径失败');
return;
}
// 在新窗口打开下载链接
window.open(filePath, '_blank');
} catch (error) {
console.error('下载文件失败:', error);
ElMessage.error('下载文件失败');
}
}
</script>
<style scoped>
.dialog-footer {
text-align: right;
}
.order-info {
padding: 10px;
background-color: #f5f7fa;
border-radius: 4px;
}
.payment-info {
display: flex;
flex-direction: column;
gap: 16px;
}
.info-section {
background-color: #fff;
border-radius: 8px;
padding: 16px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #303133;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 1px solid #ebeef5;
}
.info-item {
margin-bottom: 12px;
line-height: 1.6;
display: flex;
align-items: flex-start;
}
.info-item:last-child {
margin-bottom: 0;
}
.info-item .label {
color: #909399;
margin-right: 12px;
min-width: 100px;
}
.info-item .value {
color: #303133;
flex: 1;
}
.info-item .value.highlight {
color: #409eff;
font-weight: 600;
font-size: 16px;
}
.sub-info {
margin-top: 8px;
padding: 8px;
background-color: #fff;
border-radius: 4px;
}
.sub-item {
margin-bottom: 4px;
line-height: 1.5;
}
.sub-item:last-child {
margin-bottom: 0;
}
.sub-item .label {
color: #909399;
margin-right: 8px;
}
.sub-item .value {
color: #606266;
}
.order-type-tag,
.status-tag {
font-size: 14px;
padding: 0 12px;
height: 32px;
line-height: 32px;
}
</style>