This commit is contained in:
@@ -34,6 +34,24 @@ export interface GetUploadUrlResponse {
|
|||||||
expires_in: number
|
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 {
|
export class StorageService extends BaseService {
|
||||||
/**
|
/**
|
||||||
* 获取文件上传预签名 URL
|
* 获取文件上传预签名 URL
|
||||||
@@ -100,4 +118,18 @@ export class StorageService extends BaseService {
|
|||||||
throw error
|
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 // 购买备注
|
purchase_remark?: string // 购买备注
|
||||||
operator_name?: string // 操作者
|
operator_name?: string // 操作者
|
||||||
items: OrderItem[] | null
|
items: OrderItem[] | null
|
||||||
|
payment_voucher_key?: string // 支付凭证(线下支付时才有值)
|
||||||
created_at: string
|
created_at: string
|
||||||
updated_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']
|
MenuStyleSettings: typeof import('./../components/core/layouts/art-settings-panel/widget/MenuStyleSettings.vue')['default']
|
||||||
OperatorSelect: typeof import('./../components/business/OperatorSelect.vue')['default']
|
OperatorSelect: typeof import('./../components/business/OperatorSelect.vue')['default']
|
||||||
PackageSelector: typeof import('./../components/business/PackageSelector.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']
|
RealnamePolicyDialog: typeof import('./../components/device/RealnamePolicyDialog.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
|||||||
@@ -159,6 +159,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ElDialog>
|
||||||
|
|
||||||
|
<!-- 支付凭证预览 -->
|
||||||
|
<PaymentVoucherDialog
|
||||||
|
:file-key="paymentVoucherFileKey"
|
||||||
|
@close="paymentVoucherFileKey = ''"
|
||||||
|
/>
|
||||||
</ElCard>
|
</ElCard>
|
||||||
</div>
|
</div>
|
||||||
</ArtTableFullScreen>
|
</ArtTableFullScreen>
|
||||||
@@ -196,6 +202,7 @@
|
|||||||
import { formatDateTime } from '@/utils/business/format'
|
import { formatDateTime } from '@/utils/business/format'
|
||||||
import { RoutesAlias } from '@/router/routesAlias'
|
import { RoutesAlias } from '@/router/routesAlias'
|
||||||
import { useAuth } from '@/composables/useAuth'
|
import { useAuth } from '@/composables/useAuth'
|
||||||
|
import PaymentVoucherDialog from '@/components/business/PaymentVoucherDialog.vue'
|
||||||
|
|
||||||
defineOptions({ name: 'AgentRechargeList' })
|
defineOptions({ name: 'AgentRechargeList' })
|
||||||
|
|
||||||
@@ -210,6 +217,7 @@
|
|||||||
const createDialogVisible = ref(false)
|
const createDialogVisible = ref(false)
|
||||||
const confirmPayDialogVisible = ref(false)
|
const confirmPayDialogVisible = ref(false)
|
||||||
const currentRecharge = ref<AgentRecharge | null>(null)
|
const currentRecharge = ref<AgentRecharge | null>(null)
|
||||||
|
const paymentVoucherFileKey = ref('')
|
||||||
|
|
||||||
// 搜索表单初始值
|
// 搜索表单初始值
|
||||||
const initialSearchState: AgentRechargeQueryParams = {
|
const initialSearchState: AgentRechargeQueryParams = {
|
||||||
@@ -751,6 +759,19 @@
|
|||||||
const getActions = (row: AgentRecharge) => {
|
const getActions = (row: AgentRecharge) => {
|
||||||
const actions: any[] = []
|
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 (
|
if (
|
||||||
row.status === 1 &&
|
row.status === 1 &&
|
||||||
@@ -766,6 +787,12 @@
|
|||||||
|
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查看支付凭证
|
||||||
|
const handleViewPaymentVoucher = (row: AgentRecharge) => {
|
||||||
|
if (!row.payment_voucher_key) return
|
||||||
|
paymentVoucherFileKey.value = row.payment_voucher_key
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -300,6 +300,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ElDialog>
|
||||||
|
|
||||||
|
<!-- 支付凭证预览 -->
|
||||||
|
<PaymentVoucherDialog
|
||||||
|
:file-key="paymentVoucherFileKey"
|
||||||
|
@close="paymentVoucherFileKey = ''"
|
||||||
|
/>
|
||||||
</ElCard>
|
</ElCard>
|
||||||
</div>
|
</div>
|
||||||
</ArtTableFullScreen>
|
</ArtTableFullScreen>
|
||||||
@@ -337,6 +343,7 @@
|
|||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store/modules/user'
|
||||||
import { formatDateTime } from '@/utils/business/format'
|
import { formatDateTime } from '@/utils/business/format'
|
||||||
import { RoutesAlias } from '@/router/routesAlias'
|
import { RoutesAlias } from '@/router/routesAlias'
|
||||||
|
import PaymentVoucherDialog from '@/components/business/PaymentVoucherDialog.vue'
|
||||||
|
|
||||||
defineOptions({ name: 'OrderList' })
|
defineOptions({ name: 'OrderList' })
|
||||||
|
|
||||||
@@ -350,6 +357,7 @@
|
|||||||
const createDialogVisible = ref(false)
|
const createDialogVisible = ref(false)
|
||||||
const detailDialogVisible = ref(false)
|
const detailDialogVisible = ref(false)
|
||||||
const currentOrder = ref<Order | null>(null)
|
const currentOrder = ref<Order | null>(null)
|
||||||
|
const paymentVoucherFileKey = ref('')
|
||||||
|
|
||||||
// 搜索表单初始值
|
// 搜索表单初始值
|
||||||
const initialSearchState: OrderQueryParams = {
|
const initialSearchState: OrderQueryParams = {
|
||||||
@@ -1199,6 +1207,19 @@
|
|||||||
const getActions = (row: Order) => {
|
const getActions = (row: Order) => {
|
||||||
const actions: any[] = []
|
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')) {
|
if (row.payment_status === 1 && hasAuth('orders:delete')) {
|
||||||
actions.push({
|
actions.push({
|
||||||
@@ -1210,6 +1231,12 @@
|
|||||||
|
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查看支付凭证
|
||||||
|
const handleViewPaymentVoucher = (row: Order) => {
|
||||||
|
if (!row.payment_voucher_key) return
|
||||||
|
paymentVoucherFileKey.value = row.payment_voucher_key
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
Reference in New Issue
Block a user