This commit is contained in:
@@ -34,6 +34,24 @@ export interface GetUploadUrlResponse {
|
||||
expires_in: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取文件下载预签名 URL 请求
|
||||
*/
|
||||
export interface BatchDownloadUrlsRequest {
|
||||
/** 文件路径标识列表,最多 50 个 */
|
||||
file_keys: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取文件下载预签名 URL 响应
|
||||
*/
|
||||
export interface BatchDownloadUrlsResponse {
|
||||
/** 文件下载地址映射,key 为 file_key */
|
||||
urls: Record<string, string>
|
||||
/** URL 有效期(秒) */
|
||||
expires_in: number
|
||||
}
|
||||
|
||||
export class StorageService extends BaseService {
|
||||
/**
|
||||
* 获取文件上传预签名 URL
|
||||
@@ -100,4 +118,18 @@ export class StorageService extends BaseService {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取文件下载预签名 URL
|
||||
* 用于获取私有文件的临时下载地址
|
||||
* @param data 请求参数
|
||||
*/
|
||||
static batchDownloadUrls(
|
||||
data: BatchDownloadUrlsRequest
|
||||
): Promise<BaseResponse<BatchDownloadUrlsResponse>> {
|
||||
return this.post<BaseResponse<BatchDownloadUrlsResponse>>(
|
||||
'/api/admin/storage/batch-download-urls',
|
||||
data
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
55
src/components/business/PaymentVoucherDialog.vue
Normal file
55
src/components/business/PaymentVoucherDialog.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<ElImageViewer
|
||||
v-if="visible"
|
||||
:url-list="[url]"
|
||||
:initial-index="0"
|
||||
hide-on-click-modal
|
||||
@close="handleClose"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { ElImageViewer } from 'element-plus'
|
||||
import { StorageService } from '@/api/modules'
|
||||
|
||||
interface Props {
|
||||
fileKey?: string
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
close: []
|
||||
}>()
|
||||
|
||||
const visible = ref(false)
|
||||
const url = ref('')
|
||||
|
||||
watch(
|
||||
() => props.fileKey,
|
||||
async (val) => {
|
||||
if (val) {
|
||||
url.value = ''
|
||||
try {
|
||||
const res = await StorageService.batchDownloadUrls({
|
||||
file_keys: [val]
|
||||
})
|
||||
if (res.code === 0 && res.data?.urls?.[val]) {
|
||||
url.value = res.data.urls[val]
|
||||
visible.value = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取支付凭证失败:', error)
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
url.value = ''
|
||||
emit('close')
|
||||
}
|
||||
</script>
|
||||
@@ -63,6 +63,7 @@ export interface Order {
|
||||
purchase_remark?: string // 购买备注
|
||||
operator_name?: string // 操作者
|
||||
items: OrderItem[] | null
|
||||
payment_voucher_key?: string // 支付凭证(线下支付时才有值)
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
1
src/types/components.d.ts
vendored
1
src/types/components.d.ts
vendored
@@ -139,6 +139,7 @@ declare module 'vue' {
|
||||
MenuStyleSettings: typeof import('./../components/core/layouts/art-settings-panel/widget/MenuStyleSettings.vue')['default']
|
||||
OperatorSelect: typeof import('./../components/business/OperatorSelect.vue')['default']
|
||||
PackageSelector: typeof import('./../components/business/PackageSelector.vue')['default']
|
||||
PaymentVoucherDialog: typeof import('./../components/business/PaymentVoucherDialog.vue')['default']
|
||||
RealnamePolicyDialog: typeof import('./../components/device/RealnamePolicyDialog.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
|
||||
@@ -159,6 +159,12 @@
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
|
||||
<!-- 支付凭证预览 -->
|
||||
<PaymentVoucherDialog
|
||||
:file-key="paymentVoucherFileKey"
|
||||
@close="paymentVoucherFileKey = ''"
|
||||
/>
|
||||
</ElCard>
|
||||
</div>
|
||||
</ArtTableFullScreen>
|
||||
@@ -196,6 +202,7 @@
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import { RoutesAlias } from '@/router/routesAlias'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
import PaymentVoucherDialog from '@/components/business/PaymentVoucherDialog.vue'
|
||||
|
||||
defineOptions({ name: 'AgentRechargeList' })
|
||||
|
||||
@@ -210,6 +217,7 @@
|
||||
const createDialogVisible = ref(false)
|
||||
const confirmPayDialogVisible = ref(false)
|
||||
const currentRecharge = ref<AgentRecharge | null>(null)
|
||||
const paymentVoucherFileKey = ref('')
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialSearchState: AgentRechargeQueryParams = {
|
||||
@@ -751,6 +759,19 @@
|
||||
const getActions = (row: AgentRecharge) => {
|
||||
const actions: any[] = []
|
||||
|
||||
// 线下支付且有凭证可以查看
|
||||
if (
|
||||
row.payment_method === 'offline' &&
|
||||
row.payment_voucher_key &&
|
||||
hasAuth('agent_recharge:view_payment_voucher')
|
||||
) {
|
||||
actions.push({
|
||||
label: '查看支付凭证',
|
||||
handler: () => handleViewPaymentVoucher(row),
|
||||
type: 'primary'
|
||||
})
|
||||
}
|
||||
|
||||
// 待支付且线下转账的订单可以确认支付
|
||||
if (
|
||||
row.status === 1 &&
|
||||
@@ -766,6 +787,12 @@
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
// 查看支付凭证
|
||||
const handleViewPaymentVoucher = (row: AgentRecharge) => {
|
||||
if (!row.payment_voucher_key) return
|
||||
paymentVoucherFileKey.value = row.payment_voucher_key
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -300,6 +300,12 @@
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
|
||||
<!-- 支付凭证预览 -->
|
||||
<PaymentVoucherDialog
|
||||
:file-key="paymentVoucherFileKey"
|
||||
@close="paymentVoucherFileKey = ''"
|
||||
/>
|
||||
</ElCard>
|
||||
</div>
|
||||
</ArtTableFullScreen>
|
||||
@@ -337,6 +343,7 @@
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import { RoutesAlias } from '@/router/routesAlias'
|
||||
import PaymentVoucherDialog from '@/components/business/PaymentVoucherDialog.vue'
|
||||
|
||||
defineOptions({ name: 'OrderList' })
|
||||
|
||||
@@ -350,6 +357,7 @@
|
||||
const createDialogVisible = ref(false)
|
||||
const detailDialogVisible = ref(false)
|
||||
const currentOrder = ref<Order | null>(null)
|
||||
const paymentVoucherFileKey = ref('')
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialSearchState: OrderQueryParams = {
|
||||
@@ -1199,6 +1207,19 @@
|
||||
const getActions = (row: Order) => {
|
||||
const actions: any[] = []
|
||||
|
||||
// 线下支付且有凭证可以查看
|
||||
if (
|
||||
row.payment_method === 'offline' &&
|
||||
row.payment_voucher_key &&
|
||||
hasAuth('orders:view_payment_voucher')
|
||||
) {
|
||||
actions.push({
|
||||
label: '查看支付凭证',
|
||||
handler: () => handleViewPaymentVoucher(row),
|
||||
type: 'primary'
|
||||
})
|
||||
}
|
||||
|
||||
// 只有待支付的订单可以删除
|
||||
if (row.payment_status === 1 && hasAuth('orders:delete')) {
|
||||
actions.push({
|
||||
@@ -1210,6 +1231,12 @@
|
||||
|
||||
return actions
|
||||
}
|
||||
|
||||
// 查看支付凭证
|
||||
const handleViewPaymentVoucher = (row: Order) => {
|
||||
if (!row.payment_voucher_key) return
|
||||
paymentVoucherFileKey.value = row.payment_voucher_key
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user