2
0
Files
fe.wfc/src/views/billing/rule/index.vue
2025-02-26 12:00:14 +08:00

256 lines
6.1 KiB
Vue

<template>
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
<ACard
:title="t('page.rule.title')"
:bordered="false"
:body-style="{ flex: 1, overflow: 'hidden' }"
class="flex-col-stretch sm:flex-1-hidden"
>
<ATable
:columns="columns"
:data-source="data"
:loading="loading"
row-key="id"
size="small"
:pagination="false"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<ASpace>
<AButton type="primary" ghost @click="handleEdit(record)">{{ t('page.rule.edit') }}</AButton>
</ASpace>
</template>
</template>
</ATable>
</ACard>
<!-- 编辑抽屉 -->
<ADrawer
v-model:visible="drawerVisible"
:title="drawerTitle"
placement="right"
width="500px"
@close="closeDrawer"
>
<AForm
v-if="currentRule"
ref="formRef"
:model="currentRule"
:rules="rules"
layout="vertical"
>
<AFormItem :label="t('page.rule.traffic')" name="traffic">
<AInputNumber
v-model:value="currentRule.traffic"
:min="1"
:precision="0"
style="width: 100%"
:placeholder="t('page.rule.pletraffic')"
/>
</AFormItem>
<AFormItem :label="t('page.rule.price')" name="price">
<AInputNumber
v-model:value="currentRule.price"
:min="0"
:precision="2"
style="width: 100%"
:placeholder="t('page.rule.pleprice')"
/>
</AFormItem>
<AFormItem :label="t('page.rule.unit')" name="unit">
<ASelect
v-model:value="currentRule.unit"
style="width: 100%"
:placeholder="t('page.rule.pleunit')"
>
<ASelect.Option
v-for="option in unitOptions"
:key="option.value"
:value="option.value"
>
{{ option.label }}
</ASelect.Option>
</ASelect>
</AFormItem>
<AFormItem :label="t('page.rule.status')" name="enable">
<ASwitch v-model:checked="currentRule.enable" />
</AFormItem>
</AForm>
<template #footer>
<ASpace>
<AButton @click="closeDrawer">{{ t('page.rule.close') }}</AButton>
<AButton type="primary" :loading="submitLoading" @click="handleSubmit">{{ t('page.rule.confirm') }}</AButton>
</ASpace>
</template>
</ADrawer>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { fetchBillRuleList, updateBillRule } from '@/service/api/auth';
import {
Card as ACard,
Table as ATable,
Space as ASpace,
Switch as ASwitch,
Button as AButton,
Drawer as ADrawer,
Form as AForm,
FormItem as AFormItem,
InputNumber as AInputNumber,
message,
Select as ASelect
} from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue';
import type { ColumnsType } from 'ant-design-vue/es/table';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
interface BillRule {
id: number;
traffic: number;
price: number;
unit: number;
enable: boolean;
createBy: string | null;
createTime: string;
updateBy: string | null;
updateTime: string | null;
}
interface BillRuleUpdate {
traffic: number;
price: number;
unit: number;
enable: boolean;
}
const loading = ref(false);
const submitLoading = ref(false);
const data = ref<BillRule[]>([]);
const drawerVisible = ref(false);
const drawerTitle = ref(t('page.rule.modaltitle'));
const currentRule = ref<BillRuleUpdate | null>(null);
const formRef = ref<FormInstance>();
// 单位选项
const unitOptions = [
{ label: 'B', value: 0 },
{ label: 'KB', value: 1 },
{ label: 'MB', value: 2 },
{ label: 'GB', value: 3 },
{ label: 'TB', value: 4 }
];
// 获取单位显示文本
const getUnitText = (unit: number) => {
return unitOptions.find(option => option.value === unit)?.label || '';
};
const columns: ColumnsType = [
{
title: t('page.rule.traffic'),
dataIndex: 'traffic',
key: 'traffic',
align: 'center',
width: 150
},
{
title: t('page.rule.price'),
dataIndex: 'price',
key: 'price',
align: 'center',
width: 150
},
{
title: t('page.rule.unit'),
dataIndex: 'unit',
key: 'unit',
align: 'center',
width: 150,
customRender: ({ text }) => getUnitText(text)
},
{
title: t('page.rule.status'),
dataIndex: 'enable',
key: 'enable',
align: 'center',
width: 100,
customRender: ({ text: enable }) => (enable ? t('page.rule.use') : t('page.rule.unuse'))
},
{
title: t('page.rule.action'),
key: 'action',
align: 'center',
width: 100,
fixed: 'right'
}
];
const rules = {
traffic: [{ required: true, message: t('page.rule.pletraffic') }],
price: [{ required: true, message: t('page.rule.pleprice') }],
unit: [{ required: true, message: t('page.rule.pleunit') }]
};
// 获取列表数据
const getData = async () => {
loading.value = true;
try {
const res = await fetchBillRuleList();
if (res.data && Array.isArray(res.data)) {
data.value = res.data;
} else {
data.value = [];
}
} catch (error) {
data.value = [];
} finally {
loading.value = false;
}
};
// 打开编辑抽屉
const handleEdit = (record: BillRule) => {
currentRule.value = { ...record };
drawerVisible.value = true;
};
// 关闭抽屉
const closeDrawer = () => {
drawerVisible.value = false;
currentRule.value = null;
formRef.value?.resetFields();
};
// 提交表单
const handleSubmit = async () => {
if (!currentRule.value) return;
try {
await formRef.value?.validate();
submitLoading.value = true;
await updateBillRule(currentRule.value);
message.success(t('page.rule.updatesuc'));
closeDrawer();
getData();
} catch (error) {
} finally {
submitLoading.value = false;
}
};
onMounted(() => {
getData();
});
</script>
<style scoped>
:deep(.ant-form-item) {
margin-bottom: 24px;
}
</style>