修改
This commit is contained in:
parent
3655207bfa
commit
3ccfcea326
@ -46,10 +46,10 @@ export const getBankCardInfo = (params:any) => request.get('/v1/bank_card/bank_c
|
||||
export const delBankCard = (params:any) => request.post('/v1/bank_card/delete_bank_card',params)
|
||||
|
||||
// 发票管理-开票记录
|
||||
export const invoiceList = (params:any) => request.get('/v1/order/invoice_list',{params})
|
||||
export const invoiceList = (params:any) => request.get('/v1/invoice/invoice_list',{params})
|
||||
|
||||
// 发票管理-开发记录详情
|
||||
export const invoiceDetail = (id:any) => request.delete(`/v1/order/invoice_detail/${id}`)
|
||||
export const invoiceDetail = (id:any) => request.delete(`/v1/invoice/invoice_detail/${id}`)
|
||||
|
||||
// 获取订单列表
|
||||
export const getOrderList = (params:any) => request.get('/v1/order/order_list',{params})
|
||||
@ -492,8 +492,8 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.main-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
/* max-width: 1200px;
|
||||
margin: 0 auto; */
|
||||
}
|
||||
|
||||
/* 余额区域 */
|
||||
|
||||
@ -37,13 +37,13 @@
|
||||
<div class="batch-operations" style="margin-bottom: 16px;">
|
||||
<a-space>
|
||||
<!-- :disabled="selectedRowKeys.length === 0" -->
|
||||
<a-button
|
||||
<!-- <a-button
|
||||
type="primary"
|
||||
@click="handleBatchInvoice"
|
||||
|
||||
>
|
||||
批量去开票
|
||||
</a-button>
|
||||
</a-button> -->
|
||||
<span v-if="selectedRowKeys.length > 0">
|
||||
已选择 {{ selectedRowKeys.length }} 条记录
|
||||
</span>
|
||||
@ -94,9 +94,9 @@
|
||||
{{ getPayStatusText(record.pay_status) }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<!-- <template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<!-- :disabled="!canApplyInvoice(record)" -->
|
||||
|
||||
<a-button
|
||||
type="link"
|
||||
size="small"
|
||||
@ -106,7 +106,7 @@
|
||||
去开票
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template> -->
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
@ -483,12 +483,12 @@ const columns = ref([
|
||||
key: 'amount',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 100,
|
||||
align: 'center'
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 100,
|
||||
// align: 'center'
|
||||
// }
|
||||
])
|
||||
|
||||
// 行选择配置
|
||||
|
||||
@ -1,255 +1,345 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 标题 -->
|
||||
<div class="header">
|
||||
<h1>文件存储</h1>
|
||||
<div class="file-storage-page">
|
||||
<div class="page-header">
|
||||
<h2 class="page-title">文件存储</h2>
|
||||
<a-button type="primary" @click="showModal" class="create-btn">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
新建存储
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<!-- 区域选择 -->
|
||||
<div class="region-section">
|
||||
<h2 class="section-title">选择存储区域</h2>
|
||||
<div class="region-tabs">
|
||||
<button
|
||||
v-for="region in regions"
|
||||
:key="region.id"
|
||||
:class="['region-tab', { active: selectedRegion === region.id }]"
|
||||
@click="selectRegion(region.id)"
|
||||
<!-- 表格 -->
|
||||
<div class="table-container">
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="storageList"
|
||||
:row-key="record => record.id"
|
||||
:pagination="{ pageSize: 8 }"
|
||||
class="storage-table"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'size'">
|
||||
<span class="data-cell">{{ record.size }} GB</span>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'duration'">
|
||||
<span class="data-cell">{{ record.duration }} 天</span>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'cost'">
|
||||
<span class="cost-cell">¥{{ record.cost.toFixed(2) }}</span>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'name'">
|
||||
<div class="name-cell">
|
||||
<FolderOutlined class="folder-icon" />
|
||||
<span>{{ record.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
|
||||
<!-- 创建弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="modalVisible"
|
||||
title="创建存储空间"
|
||||
@ok="handleCreate"
|
||||
@cancel="modalVisible = false"
|
||||
:width="520"
|
||||
class="create-modal"
|
||||
>
|
||||
<a-form
|
||||
:model="createForm"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 18 }"
|
||||
ref="createFormRef"
|
||||
class="create-form"
|
||||
>
|
||||
<a-form-item label="存储名称" name="name" :rules="[{ required: true, message: '请输入存储名称' }]">
|
||||
<a-input
|
||||
v-model:value="createForm.name"
|
||||
placeholder="请输入存储空间名称"
|
||||
size="large"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
label="存储大小"
|
||||
name="size"
|
||||
:rules="[{ required: true, message: '请输入存储大小' }, { type: 'number', min: 1, message: '至少1GB' }]"
|
||||
>
|
||||
{{ region.name }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<a-input-number
|
||||
v-model:value="createForm.size"
|
||||
:min="1"
|
||||
:max="10000"
|
||||
style="width: 100%"
|
||||
size="large"
|
||||
addon-after="GB"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 中心图标 -->
|
||||
<div class="center-section">
|
||||
<div class="center-icon">
|
||||
<i class="icon-book"></i>
|
||||
</div>
|
||||
</div>
|
||||
<a-form-item
|
||||
label="购买时长"
|
||||
name="duration"
|
||||
:rules="[{ required: true, message: '请输入购买时长' }, { type: 'number', min: 1, message: '至少1天' }]"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="createForm.duration"
|
||||
:min="1"
|
||||
:max="365"
|
||||
style="width: 100%"
|
||||
size="large"
|
||||
addon-after="天"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<!-- 主要操作按钮 -->
|
||||
<div class="action-section">
|
||||
<button class="btn-primary" @click="initializeStorage">
|
||||
初始化文件存储
|
||||
</button>
|
||||
<p class="action-hint">将在 {{ getSelectedRegionName() }} 创建存储空间</p>
|
||||
</div>
|
||||
<div class="cost-summary">
|
||||
<div class="cost-label">费用合计</div>
|
||||
<div class="cost-amount">
|
||||
<span class="amount">¥{{ totalCost }}</span>
|
||||
<span class="cost-note">(0.1元/GB/天)</span>
|
||||
</div>
|
||||
</div>
|
||||
</a-form>
|
||||
|
||||
<!-- 底部帮助链接 -->
|
||||
<div class="help-section">
|
||||
<div class="help-links">
|
||||
<a href="#" class="link" @click.prevent="viewHelp">文件存储使用介绍</a>
|
||||
<a href="#" class="link" @click.prevent="viewPricing">查看计费规则</a>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<a-button @click="modalVisible = false">取消</a-button>
|
||||
<a-button type="primary" @click="handleCreate" :loading="creating">确认创建</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
<script setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { PlusOutlined, FolderOutlined } from '@ant-design/icons-vue'
|
||||
|
||||
// 定义区域选项
|
||||
interface Region {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
const regions = [
|
||||
{ id: 'a100', name: 'A100专区' },
|
||||
{ id: 'v100', name: 'V100专区' },
|
||||
{ id: 'foshan', name: '佛山区' },
|
||||
{ id: 'beijing', name: '北京B区' }
|
||||
// 表格列定义
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '30%'
|
||||
},
|
||||
{
|
||||
title: '存储大小',
|
||||
dataIndex: 'size',
|
||||
key: 'size',
|
||||
align: 'right'
|
||||
},
|
||||
{
|
||||
title: '购买时长',
|
||||
dataIndex: 'duration',
|
||||
key: 'duration',
|
||||
align: 'right'
|
||||
},
|
||||
{
|
||||
title: '费用',
|
||||
dataIndex: 'cost',
|
||||
key: 'cost',
|
||||
align: 'right'
|
||||
}
|
||||
]
|
||||
|
||||
const selectedRegion = ref('a100') // 默认选中 A100
|
||||
// 存储列表(模拟数据)
|
||||
const storageList = ref([
|
||||
{ id: 1, name: '项目A存储', size: 100, duration: 30, cost: 300 },
|
||||
{ id: 2, name: '备份存储', size: 500, duration: 7, cost: 350 }
|
||||
])
|
||||
|
||||
// 方法:获取选中区域名称
|
||||
const getSelectedRegionName = () => {
|
||||
const region = regions.find(r => r.id === selectedRegion.value)
|
||||
return region ? region.name : ''
|
||||
// 弹窗控制
|
||||
const modalVisible = ref(false)
|
||||
const creating = ref(false)
|
||||
|
||||
// 表单数据
|
||||
const createForm = reactive({
|
||||
name: '',
|
||||
size: 50,
|
||||
duration: 30
|
||||
})
|
||||
|
||||
// 计算费用:0.1 元 / GB / 天
|
||||
const totalCost = computed(() => {
|
||||
return (createForm.size * createForm.duration * 0.1).toFixed(2)
|
||||
})
|
||||
|
||||
// 表单引用(用于校验)
|
||||
const createFormRef = ref()
|
||||
|
||||
// 显示弹窗
|
||||
const showModal = () => {
|
||||
createForm.name = ''
|
||||
createForm.size = 50
|
||||
createForm.duration = 30
|
||||
modalVisible.value = true
|
||||
}
|
||||
|
||||
// 方法:选择区域
|
||||
const selectRegion = (id: string) => {
|
||||
selectedRegion.value = id
|
||||
}
|
||||
// 创建存储
|
||||
const handleCreate = async () => {
|
||||
try {
|
||||
await createFormRef.value.validateFields()
|
||||
creating.value = true
|
||||
|
||||
// 方法:初始化存储
|
||||
const initializeStorage = () => {
|
||||
alert(`正在初始化 ${selectedRegion.value} 的文件存储...`)
|
||||
// 这里可以跳转到下一步流程
|
||||
}
|
||||
// 模拟API调用延迟
|
||||
await new Promise(resolve => setTimeout(resolve, 800))
|
||||
|
||||
// 方法:查看帮助
|
||||
const viewHelp = () => {
|
||||
alert('文件存储使用介绍')
|
||||
}
|
||||
// 添加到列表
|
||||
const newStorage = {
|
||||
id: Date.now(),
|
||||
name: createForm.name,
|
||||
size: createForm.size,
|
||||
duration: createForm.duration,
|
||||
cost: parseFloat(totalCost.value)
|
||||
}
|
||||
storageList.value.unshift(newStorage)
|
||||
modalVisible.value = false
|
||||
|
||||
// 方法:查看计费规则
|
||||
const viewPricing = () => {
|
||||
alert('计费规则详情')
|
||||
// 可在此处调用 API
|
||||
console.log('创建成功:', newStorage)
|
||||
} catch (error) {
|
||||
console.log('校验失败:', error)
|
||||
} finally {
|
||||
creating.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
/* max-width: 800px;
|
||||
margin: 0 auto; */
|
||||
padding: 40px 30px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
color: #333;
|
||||
.file-storage-page {
|
||||
padding: 24px;
|
||||
background: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 标题区域 */
|
||||
.header {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* 区域选择 */
|
||||
.region-section {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 500;
|
||||
color: #555;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.region-tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.region-tab {
|
||||
padding: 12px 24px;
|
||||
border: 1px solid #ddd;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
font-size: 14px;
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.region-tab:hover {
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
.region-tab.active {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
border-color: #3498db;
|
||||
}
|
||||
|
||||
/* 中心图标区域 */
|
||||
.center-section {
|
||||
margin: 40px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.center-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #f5f5f5;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
|
||||
.create-btn {
|
||||
height: 40px;
|
||||
padding: 0 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.storage-table {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.icon-book {
|
||||
font-size: 36px;
|
||||
color: #3498db;
|
||||
.storage-table :deep(.ant-table-thead > tr > th) {
|
||||
background: #fafbfc;
|
||||
font-weight: 600;
|
||||
color: #5e6d82;
|
||||
border-bottom: 2px solid #e8e8e8;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.icon-book::before {
|
||||
content: "📁";
|
||||
.storage-table :deep(.ant-table-tbody > tr > td) {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
/* 操作区域 */
|
||||
.action-section {
|
||||
margin: 40px 0;
|
||||
text-align: center;
|
||||
.storage-table :deep(.ant-table-tbody > tr:hover > td) {
|
||||
background-color: #f9fafc;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 14px 32px;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #2980b9;
|
||||
}
|
||||
|
||||
.action-hint {
|
||||
margin-top: 12px;
|
||||
font-size: 0.9rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 帮助区域 */
|
||||
.help-section {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.help-links {
|
||||
.name-cell {
|
||||
display: flex;
|
||||
gap: 30px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.link {
|
||||
text-decoration: none;
|
||||
color: #3498db;
|
||||
.folder-icon {
|
||||
color: #1890ff;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.data-cell {
|
||||
color: #5e6d82;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.cost-cell {
|
||||
color: #1890ff;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.create-form {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.create-form :deep(.ant-form-item-label) {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.create-form :deep(.ant-input-number),
|
||||
.create-form :deep(.ant-input) {
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.cost-summary {
|
||||
background: #f8f9fa;
|
||||
border-radius: 6px;
|
||||
padding: 16px 20px;
|
||||
margin-top: 8px;
|
||||
border: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.cost-label {
|
||||
font-size: 14px;
|
||||
transition: color 0.2s;
|
||||
color: #5e6d82;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: #2980b9;
|
||||
text-decoration: underline;
|
||||
.cost-amount {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
padding: 30px 20px;
|
||||
}
|
||||
.amount {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.region-tabs {
|
||||
flex-direction: column;
|
||||
}
|
||||
.cost-note {
|
||||
font-size: 13px;
|
||||
color: #8c98ae;
|
||||
}
|
||||
|
||||
.region-tab {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
.create-modal :deep(.ant-modal-header) {
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
padding: 20px 24px;
|
||||
}
|
||||
|
||||
.help-links {
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
.create-modal :deep(.ant-modal-title) {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.center-section {
|
||||
justify-content: center;
|
||||
}
|
||||
.create-modal :deep(.ant-modal-footer) {
|
||||
border-top: 1px solid #e8e8e8;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user