This commit is contained in:
@@ -1,124 +1,42 @@
|
||||
<template>
|
||||
<ArtDataViewer
|
||||
:service="loadDetailData"
|
||||
:card-title="pageTitle"
|
||||
@back="handleBack"
|
||||
@refresh="handleRefresh"
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<ElDescriptions :column="2" border>
|
||||
<ElDescriptionsItem label="充值单号">
|
||||
{{ data.recharge_no }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="充值记录ID">
|
||||
{{ data.id }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="代理钱包ID">
|
||||
{{ data.agent_wallet_id }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="店铺ID">
|
||||
{{ data.shop_id }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="店铺名称">
|
||||
{{ data.shop_name }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="充值金额">
|
||||
<span style="color: var(--el-color-success); font-weight: bold">
|
||||
{{ formatCurrency(data.amount) }}
|
||||
</span>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="状态">
|
||||
<ElTag :type="getStatusType(data.status)">
|
||||
{{ getStatusText(data.status) }}
|
||||
</ElTag>
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="支付方式">
|
||||
{{ getPaymentMethodText(data.payment_method) }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="支付通道">
|
||||
{{ data.payment_channel }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="支付配置ID">
|
||||
{{ data.payment_config_id || '-' }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="第三方支付流水号" :span="2">
|
||||
{{ data.payment_transaction_id || '-' }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="创建时间">
|
||||
{{ formatDateTime(data.created_at) }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="支付时间">
|
||||
{{ data.paid_at ? formatDateTime(data.paid_at) : '-' }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="完成时间">
|
||||
{{ data.completed_at ? formatDateTime(data.completed_at) : '-' }}
|
||||
</ElDescriptionsItem>
|
||||
<ElDescriptionsItem label="更新时间">
|
||||
{{ formatDateTime(data.updated_at) }}
|
||||
</ElDescriptionsItem>
|
||||
</ElDescriptions>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div style="margin-top: 20px; text-align: right">
|
||||
<ElButton v-if="data.status === 1 && data.payment_method === 'offline'" type="primary" @click="handleConfirmPay(data)">
|
||||
确认支付
|
||||
</ElButton>
|
||||
<ElButton @click="handleBack">返回列表</ElButton>
|
||||
</div>
|
||||
<div class="agent-recharge-detail-page">
|
||||
<ElCard shadow="never">
|
||||
<!-- 页面头部 -->
|
||||
<div class="detail-header">
|
||||
<ElButton @click="handleBack">
|
||||
<template #icon>
|
||||
<ElIcon><ArrowLeft /></ElIcon>
|
||||
</template>
|
||||
</ArtDataViewer>
|
||||
|
||||
<!-- 确认线下支付对话框 -->
|
||||
<ElDialog
|
||||
v-model="confirmPayDialogVisible"
|
||||
title="确认线下充值"
|
||||
width="400px"
|
||||
@closed="handleConfirmPayDialogClosed"
|
||||
>
|
||||
<ElForm
|
||||
ref="confirmPayFormRef"
|
||||
:model="confirmPayForm"
|
||||
:rules="confirmPayRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<ElFormItem label="充值单号">
|
||||
<span>{{ currentRecharge?.recharge_no }}</span>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="充值金额">
|
||||
<span>{{ formatCurrency(currentRecharge?.amount || 0) }}</span>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="操作密码" prop="operation_password">
|
||||
<ElInput
|
||||
v-model="confirmPayForm.operation_password"
|
||||
type="password"
|
||||
placeholder="请输入操作密码"
|
||||
show-password
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="confirmPayDialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleConfirmPaySubmit" :loading="confirmPayLoading">
|
||||
确认支付
|
||||
返回
|
||||
</ElButton>
|
||||
<h2 class="detail-title">{{ pageTitle }}</h2>
|
||||
</div>
|
||||
|
||||
<!-- 详情内容 -->
|
||||
<DetailPage v-if="detailData" :sections="detailSections" :data="detailData" />
|
||||
|
||||
<!-- 加载中 -->
|
||||
<div v-if="loading" class="loading-container">
|
||||
<ElIcon class="is-loading"><Loading /></ElIcon>
|
||||
<span>加载中...</span>
|
||||
</div>
|
||||
</ElCard>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, h } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElCard, ElButton, ElIcon, ElMessage, ElTag } from 'element-plus'
|
||||
import { ArrowLeft, Loading } from '@element-plus/icons-vue'
|
||||
import DetailPage from '@/components/common/DetailPage.vue'
|
||||
import type { DetailSection } from '@/components/common/DetailPage.vue'
|
||||
import { AgentRechargeService } from '@/api/modules'
|
||||
import { ElMessage, ElTag } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type {
|
||||
AgentRecharge,
|
||||
AgentRechargeStatus,
|
||||
AgentRechargePaymentMethod,
|
||||
ConfirmOfflinePaymentRequest
|
||||
AgentRechargePaymentMethod
|
||||
} from '@/types/api'
|
||||
import ArtDataViewer from '@/components/core/views/ArtDataViewer.vue'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import { RoutesAlias } from '@/router/routesAlias'
|
||||
|
||||
@@ -126,22 +44,13 @@
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const loading = ref(false)
|
||||
const detailData = ref<AgentRecharge | null>(null)
|
||||
|
||||
const rechargeId = computed(() => Number(route.params.id))
|
||||
const pageTitle = computed(() => `充值订单详情 #${rechargeId.value}`)
|
||||
|
||||
const confirmPayDialogVisible = ref(false)
|
||||
const confirmPayLoading = ref(false)
|
||||
const currentRecharge = ref<AgentRecharge | null>(null)
|
||||
const confirmPayFormRef = ref<FormInstance>()
|
||||
|
||||
const confirmPayRules = reactive<FormRules>({
|
||||
operation_password: [{ required: true, message: '请输入操作密码', trigger: 'blur' }]
|
||||
})
|
||||
|
||||
const confirmPayForm = reactive<ConfirmOfflinePaymentRequest>({
|
||||
operation_password: ''
|
||||
})
|
||||
|
||||
// 格式化货币 - 将分转换为元
|
||||
const formatCurrency = (amount: number): string => {
|
||||
return `¥${(amount / 100).toFixed(2)}`
|
||||
@@ -176,13 +85,97 @@
|
||||
return methodMap[method] || method
|
||||
}
|
||||
|
||||
// 详情配置
|
||||
const detailSections = computed((): DetailSection[] => [
|
||||
{
|
||||
title: '订单信息',
|
||||
fields: [
|
||||
{ label: '充值单号', prop: 'recharge_no' },
|
||||
{ label: '充值记录ID', prop: 'id' },
|
||||
{ label: '店铺名称', prop: 'shop_name' },
|
||||
{ label: '店铺ID', prop: 'shop_id' },
|
||||
{
|
||||
label: '充值金额',
|
||||
formatter: (_, data) => formatCurrency(data.amount)
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
render: (data) => h(ElTag, { type: getStatusType(data.status) }, () => getStatusText(data.status))
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '支付信息',
|
||||
fields: [
|
||||
{
|
||||
label: '支付方式',
|
||||
formatter: (_, data) => getPaymentMethodText(data.payment_method)
|
||||
},
|
||||
{
|
||||
label: '支付通道',
|
||||
prop: 'payment_channel',
|
||||
formatter: (value) => value || '-'
|
||||
},
|
||||
{
|
||||
label: '支付配置ID',
|
||||
prop: 'payment_config_id',
|
||||
formatter: (value) => value || '-'
|
||||
},
|
||||
{
|
||||
label: '代理钱包ID',
|
||||
prop: 'agent_wallet_id'
|
||||
},
|
||||
{
|
||||
label: '第三方支付流水号',
|
||||
prop: 'payment_transaction_id',
|
||||
formatter: (value) => value || '-',
|
||||
fullWidth: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '时间信息',
|
||||
fields: [
|
||||
{
|
||||
label: '创建时间',
|
||||
prop: 'created_at',
|
||||
formatter: (value) => formatDateTime(value)
|
||||
},
|
||||
{
|
||||
label: '支付时间',
|
||||
prop: 'paid_at',
|
||||
formatter: (value) => (value ? formatDateTime(value) : '-')
|
||||
},
|
||||
{
|
||||
label: '完成时间',
|
||||
prop: 'completed_at',
|
||||
formatter: (value) => (value ? formatDateTime(value) : '-')
|
||||
},
|
||||
{
|
||||
label: '更新时间',
|
||||
prop: 'updated_at',
|
||||
formatter: (value) => formatDateTime(value)
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
// 加载详情数据
|
||||
const loadDetailData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await AgentRechargeService.getAgentRechargeById(rechargeId.value)
|
||||
if (res.code === 0) {
|
||||
return res.data
|
||||
detailData.value = res.data
|
||||
} else {
|
||||
ElMessage.error(res.msg || '加载失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ElMessage.error('加载失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
throw new Error(res.msg || '加载失败')
|
||||
}
|
||||
|
||||
// 返回列表
|
||||
@@ -190,46 +183,41 @@
|
||||
router.push(RoutesAlias.AgentRecharge)
|
||||
}
|
||||
|
||||
// 刷新数据
|
||||
const handleRefresh = () => {
|
||||
// ArtDataViewer 会自动重新加载数据
|
||||
}
|
||||
|
||||
// 显示确认支付对话框
|
||||
const handleConfirmPay = (data: AgentRecharge) => {
|
||||
currentRecharge.value = data
|
||||
confirmPayDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 确认支付对话框关闭后的清理
|
||||
const handleConfirmPayDialogClosed = () => {
|
||||
confirmPayFormRef.value?.resetFields()
|
||||
confirmPayForm.operation_password = ''
|
||||
currentRecharge.value = null
|
||||
}
|
||||
|
||||
// 确认线下支付
|
||||
const handleConfirmPaySubmit = async () => {
|
||||
if (!confirmPayFormRef.value || !currentRecharge.value) return
|
||||
|
||||
await confirmPayFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
confirmPayLoading.value = true
|
||||
try {
|
||||
await AgentRechargeService.confirmOfflinePayment(currentRecharge.value!.id, {
|
||||
operation_password: confirmPayForm.operation_password
|
||||
onMounted(() => {
|
||||
loadDetailData()
|
||||
})
|
||||
ElMessage.success('确认支付成功')
|
||||
confirmPayDialogVisible.value = false
|
||||
confirmPayFormRef.value.resetFields()
|
||||
// 刷新页面数据
|
||||
handleRefresh()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
confirmPayLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.agent-recharge-detail-page {
|
||||
padding: 20px;
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.detail-title {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 0;
|
||||
gap: 12px;
|
||||
color: var(--el-text-color-secondary);
|
||||
|
||||
.el-icon {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,14 +32,29 @@
|
||||
:pageSize="pagination.page_size"
|
||||
:total="pagination.total"
|
||||
:marginTop="10"
|
||||
:row-class-name="getRowClassName"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
@row-contextmenu="handleRowContextMenu"
|
||||
@cell-mouse-enter="handleCellMouseEnter"
|
||||
@cell-mouse-leave="handleCellMouseLeave"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
|
||||
</template>
|
||||
</ArtTable>
|
||||
|
||||
<!-- 鼠标悬浮提示 -->
|
||||
<TableContextMenuHint :visible="showContextMenuHint" :position="hintPosition" />
|
||||
|
||||
<!-- 充值订单操作右键菜单 -->
|
||||
<ArtMenuRight
|
||||
ref="rechargeOperationMenuRef"
|
||||
:menu-items="rechargeOperationMenuItems"
|
||||
:menu-width="140"
|
||||
@select="handleRechargeOperationMenuSelect"
|
||||
/>
|
||||
|
||||
<!-- 创建充值订单对话框 -->
|
||||
<ElDialog
|
||||
v-model="createDialogVisible"
|
||||
@@ -151,7 +166,7 @@
|
||||
import { h } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { AgentRechargeService, ShopService } from '@/api/modules'
|
||||
import { ElMessage, ElTag, ElTreeSelect } from 'element-plus'
|
||||
import { ElMessage, ElTag, ElTreeSelect, ElButton } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type {
|
||||
AgentRecharge,
|
||||
@@ -165,6 +180,10 @@
|
||||
import type { SearchFormItem } from '@/types'
|
||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { useTableContextMenu } from '@/composables/useTableContextMenu'
|
||||
import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
|
||||
import TableContextMenuHint from '@/components/core/others/TableContextMenuHint.vue'
|
||||
import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import { RoutesAlias } from '@/router/routesAlias'
|
||||
|
||||
@@ -181,6 +200,10 @@
|
||||
const confirmPayDialogVisible = ref(false)
|
||||
const currentRecharge = ref<AgentRecharge | null>(null)
|
||||
|
||||
// 右键菜单
|
||||
const rechargeOperationMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
|
||||
const currentOperatingRecharge = ref<AgentRecharge | null>(null)
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialSearchState: AgentRechargeQueryParams = {
|
||||
shop_id: undefined,
|
||||
@@ -249,7 +272,6 @@
|
||||
|
||||
// 列配置
|
||||
const columnOptions = [
|
||||
{ label: 'ID', prop: 'id' },
|
||||
{ label: '充值单号', prop: 'recharge_no' },
|
||||
{ label: '店铺名称', prop: 'shop_name' },
|
||||
{ label: '充值金额', prop: 'amount' },
|
||||
@@ -258,8 +280,7 @@
|
||||
{ label: '支付通道', prop: 'payment_channel' },
|
||||
{ label: '创建时间', prop: 'created_at' },
|
||||
{ label: '支付时间', prop: 'paid_at' },
|
||||
{ label: '完成时间', prop: 'completed_at' },
|
||||
{ label: '操作', prop: 'actions' }
|
||||
{ label: '完成时间', prop: 'completed_at' }
|
||||
]
|
||||
|
||||
const createFormRef = ref<FormInstance>()
|
||||
@@ -323,15 +344,10 @@
|
||||
|
||||
// 动态列配置
|
||||
const { columnChecks, columns } = useCheckedColumns(() => [
|
||||
{
|
||||
prop: 'id',
|
||||
label: 'ID',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
prop: 'recharge_no',
|
||||
label: '充值单号',
|
||||
minWidth: 200,
|
||||
minWidth: 240,
|
||||
formatter: (row: AgentRecharge) => {
|
||||
return h(
|
||||
'span',
|
||||
@@ -374,7 +390,8 @@
|
||||
{
|
||||
prop: 'payment_channel',
|
||||
label: '支付通道',
|
||||
width: 120
|
||||
width: 120,
|
||||
formatter: (row: AgentRecharge) => row.payment_channel || '-'
|
||||
},
|
||||
{
|
||||
prop: 'created_at',
|
||||
@@ -393,46 +410,6 @@
|
||||
label: '完成时间',
|
||||
width: 180,
|
||||
formatter: (row: AgentRecharge) => (row.completed_at ? formatDateTime(row.completed_at) : '-')
|
||||
},
|
||||
{
|
||||
prop: 'actions',
|
||||
label: '操作',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
formatter: (row: AgentRecharge) => {
|
||||
const buttons: any[] = []
|
||||
|
||||
// 待支付且线下转账的订单可以确认支付
|
||||
if (row.status === 1 && row.payment_method === 'offline') {
|
||||
buttons.push(
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
type: 'primary',
|
||||
link: true,
|
||||
size: 'small',
|
||||
onClick: () => handleShowConfirmPay(row)
|
||||
},
|
||||
() => '确认支付'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
buttons.push(
|
||||
h(
|
||||
ElButton,
|
||||
{
|
||||
type: 'primary',
|
||||
link: true,
|
||||
size: 'small',
|
||||
onClick: () => handleViewDetail(row)
|
||||
},
|
||||
() => '查看详情'
|
||||
)
|
||||
)
|
||||
|
||||
return h('div', { style: 'display: flex; gap: 8px;' }, buttons)
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
@@ -502,7 +479,7 @@
|
||||
}
|
||||
const res = await AgentRechargeService.getAgentRecharges(params)
|
||||
if (res.code === 0) {
|
||||
rechargeList.value = res.data.list || []
|
||||
rechargeList.value = res.data.items || []
|
||||
pagination.total = res.data.total || 0
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -551,6 +528,8 @@
|
||||
|
||||
// 显示创建订单对话框
|
||||
const showCreateDialog = async () => {
|
||||
// 重新加载店铺列表,确保获取最新数据
|
||||
await loadShops()
|
||||
createDialogVisible.value = true
|
||||
}
|
||||
|
||||
@@ -633,10 +612,65 @@
|
||||
path: `${RoutesAlias.AgentRecharge}/detail/${row.id}`
|
||||
})
|
||||
}
|
||||
|
||||
// 充值订单操作菜单项配置
|
||||
const rechargeOperationMenuItems = computed((): MenuItemType[] => {
|
||||
const items: MenuItemType[] = []
|
||||
|
||||
// 待支付且线下转账的订单可以确认支付
|
||||
if (
|
||||
currentOperatingRecharge.value?.status === 1 &&
|
||||
currentOperatingRecharge.value?.payment_method === 'offline'
|
||||
) {
|
||||
items.push({
|
||||
key: 'confirm_pay',
|
||||
label: '确认支付'
|
||||
})
|
||||
}
|
||||
|
||||
return items
|
||||
})
|
||||
|
||||
// 显示充值订单操作右键菜单
|
||||
const showRechargeOperationMenu = (e: MouseEvent, row: AgentRecharge) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
currentOperatingRecharge.value = row
|
||||
rechargeOperationMenuRef.value?.show(e)
|
||||
}
|
||||
|
||||
// 处理表格行右键菜单
|
||||
const handleRowContextMenu = (row: AgentRecharge, column: any, event: MouseEvent) => {
|
||||
showRechargeOperationMenu(event, row)
|
||||
}
|
||||
|
||||
// 处理充值订单操作菜单选择
|
||||
const handleRechargeOperationMenuSelect = (item: MenuItemType) => {
|
||||
if (!currentOperatingRecharge.value) return
|
||||
|
||||
switch (item.key) {
|
||||
case 'confirm_pay':
|
||||
handleShowConfirmPay(currentOperatingRecharge.value)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 使用表格右键菜单功能
|
||||
const {
|
||||
showContextMenuHint,
|
||||
hintPosition,
|
||||
getRowClassName,
|
||||
handleCellMouseEnter,
|
||||
handleCellMouseLeave
|
||||
} = useTableContextMenu()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.agent-recharge-page {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-table__row.table-row-with-context-menu) {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
批量为表格页面添加右键菜单和悬浮提示功能
|
||||
"""
|
||||
|
||||
import re
|
||||
import os
|
||||
|
||||
def add_imports(content):
|
||||
"""添加必要的导入"""
|
||||
# 检查是否已经导入
|
||||
if 'useTableContextMenu' in content:
|
||||
return content
|
||||
|
||||
# 找到 useAuth 导入位置
|
||||
import_pattern = r"(import\s+{\s+useAuth\s+}\s+from\s+'@/composables/useAuth')"
|
||||
|
||||
if re.search(import_pattern, content):
|
||||
# 在 useAuth 后面添加 useTableContextMenu
|
||||
content = re.sub(
|
||||
import_pattern,
|
||||
r"\1\n import { useTableContextMenu } from '@/composables/useTableContextMenu'",
|
||||
content
|
||||
)
|
||||
|
||||
# 添加 TableContextMenuHint 组件导入
|
||||
arttable_pattern = r"(import\s+ArtButtonTable\s+from\s+'@/components/core/forms/ArtButtonTable\.vue')"
|
||||
if re.search(arttable_pattern, content):
|
||||
content = re.sub(
|
||||
arttable_pattern,
|
||||
r"\1\n import TableContextMenuHint from '@/components/core/others/TableContextMenuHint.vue'",
|
||||
content
|
||||
)
|
||||
|
||||
# 如果没有 ArtMenuRight,添加它
|
||||
if 'ArtMenuRight' not in content:
|
||||
content = re.sub(
|
||||
arttable_pattern,
|
||||
r"\1\n import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'\n import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'",
|
||||
content
|
||||
)
|
||||
|
||||
return content
|
||||
|
||||
def add_context_menu_usage(content):
|
||||
"""添加 useTableContextMenu 的使用"""
|
||||
if 'useTableContextMenu()' in content:
|
||||
return content
|
||||
|
||||
# 查找 const currentRow = ref 或类似的变量声明
|
||||
pattern = r"(const\s+currentRow\s*=\s*ref[^\n]+)"
|
||||
|
||||
usage_code = """
|
||||
// 使用表格右键菜单功能
|
||||
const {
|
||||
showContextMenuHint,
|
||||
hintPosition,
|
||||
getRowClassName,
|
||||
handleCellMouseEnter,
|
||||
handleCellMouseLeave
|
||||
} = useTableContextMenu()"""
|
||||
|
||||
if re.search(pattern, content):
|
||||
content = re.sub(pattern, r"\1" + usage_code, content)
|
||||
|
||||
return content
|
||||
|
||||
def add_table_events(content):
|
||||
"""为 ArtTable 添加事件监听"""
|
||||
# 查找 ArtTable 标签
|
||||
table_pattern = r"(<ArtTable[^>]*?)(\s*@row-contextmenu=\"[^\"]+\")?([^>]*>)"
|
||||
|
||||
if '@cell-mouse-enter' in content:
|
||||
return content
|
||||
|
||||
# 添加必要的属性和事件
|
||||
def replace_table(match):
|
||||
prefix = match.group(1)
|
||||
existing_contextmenu = match.group(2) or ''
|
||||
suffix = match.group(3)
|
||||
|
||||
# 如果没有 row-class-name,添加它
|
||||
if ':row-class-name' not in prefix and 'row-class-name' not in prefix:
|
||||
prefix += '\n :row-class-name="getRowClassName"'
|
||||
|
||||
# 如果没有 row-contextmenu,添加它
|
||||
if not existing_contextmenu and '@row-contextmenu' not in prefix:
|
||||
existing_contextmenu = '\n @row-contextmenu="handleRowContextMenu"'
|
||||
|
||||
# 添加 cell mouse 事件
|
||||
cell_events = '\n @cell-mouse-enter="handleCellMouseEnter"\n @cell-mouse-leave="handleCellMouseLeave"'
|
||||
|
||||
return prefix + existing_contextmenu + cell_events + suffix
|
||||
|
||||
content = re.sub(table_pattern, replace_table, content, flags=re.DOTALL)
|
||||
|
||||
return content
|
||||
|
||||
def add_hint_component(content):
|
||||
"""添加悬浮提示组件"""
|
||||
if 'TableContextMenuHint' in content and ':visible="showContextMenuHint"' in content:
|
||||
return content
|
||||
|
||||
# 在 </ArtTable> 后添加提示组件
|
||||
table_end_pattern = r"(</ArtTable>)"
|
||||
|
||||
hint_component = r"""\1
|
||||
|
||||
<!-- 鼠标悬浮提示 -->
|
||||
<TableContextMenuHint :visible="showContextMenuHint" :position="hintPosition" />"""
|
||||
|
||||
content = re.sub(table_end_pattern, hint_component, content)
|
||||
|
||||
return content
|
||||
|
||||
def add_context_menu_component(content):
|
||||
"""添加右键菜单组件"""
|
||||
if 'ArtMenuRight' in content and 'contextMenuRef' in content:
|
||||
return content
|
||||
|
||||
# 在提示组件后添加右键菜单
|
||||
hint_pattern = r"(<TableContextMenuHint[^>]+/>)"
|
||||
|
||||
menu_component = r"""\1
|
||||
|
||||
<!-- 右键菜单 -->
|
||||
<ArtMenuRight
|
||||
ref="contextMenuRef"
|
||||
:menu-items="contextMenuItems"
|
||||
:menu-width="120"
|
||||
@select="handleContextMenuSelect"
|
||||
/>"""
|
||||
|
||||
content = re.sub(hint_pattern, menu_component, content)
|
||||
|
||||
return content
|
||||
|
||||
def add_css_styles(content):
|
||||
"""添加 CSS 样式"""
|
||||
if 'table-row-with-context-menu' in content:
|
||||
return content
|
||||
|
||||
# 查找 <style> 标签
|
||||
style_pattern = r"(<style[^>]*>)"
|
||||
|
||||
css_code = r"""\1
|
||||
:deep(.el-table__row.table-row-with-context-menu) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
content = re.sub(style_pattern, css_code, content)
|
||||
|
||||
return content
|
||||
|
||||
def process_file(file_path):
|
||||
"""处理单个文件"""
|
||||
print(f"Processing: {file_path}")
|
||||
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
original_content = content
|
||||
|
||||
# 执行所有转换
|
||||
content = add_imports(content)
|
||||
content = add_context_menu_usage(content)
|
||||
content = add_table_events(content)
|
||||
content = add_hint_component(content)
|
||||
content = add_context_menu_component(content)
|
||||
content = add_css_styles(content)
|
||||
|
||||
# 如果内容有变化,写回文件
|
||||
if content != original_content:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print(f" ✓ Updated")
|
||||
return True
|
||||
else:
|
||||
print(f" - No changes needed")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f" ✗ Error: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
# 定义需要处理的文件列表
|
||||
files_to_process = [
|
||||
"src/views/package-management/package-list/index.vue",
|
||||
"src/views/account-management/account/index.vue",
|
||||
"src/views/account-management/enterprise-customer/index.vue",
|
||||
"src/views/account-management/enterprise-cards/index.vue",
|
||||
"src/views/asset-management/iot-card-management/index.vue",
|
||||
"src/views/asset-management/iot-card-task/index.vue",
|
||||
"src/views/asset-management/device-task/index.vue",
|
||||
"src/views/asset-management/asset-assign/index.vue",
|
||||
"src/views/asset-management/authorization-records/index.vue",
|
||||
"src/views/finance/commission/agent-commission/index.vue",
|
||||
]
|
||||
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
updated_count = 0
|
||||
for file_rel_path in files_to_process:
|
||||
file_path = os.path.join(base_dir, file_rel_path)
|
||||
if os.path.exists(file_path):
|
||||
if process_file(file_path):
|
||||
updated_count += 1
|
||||
else:
|
||||
print(f"File not found: {file_path}")
|
||||
|
||||
print(f"\n完成! 更新了 {updated_count} 个文件")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user