Files
kami_frontend/src/views/camel-oil-info/token/components/add-edit-modal.vue
danial 246ff9f34e feat(token): 新增修改 Token 接口及绑定记录视图切换功能
- 新增 apiTokenUpdatePost 接口支持修改 Token 信息
- 扩展 Token 数据结构,增加充值金额限制和次数限制相关字段
- 调整新增/编辑 Token 弹窗,支持编辑模式下的充值限制显示和输入
- 新增绑定记录卡片视图与表格视图切换功能
- 绑定记录视图显示总记录数和总金额统计信息
- 卡片视图改进绑定记录样式和交互,支持复制卡号和卡密
- 弹窗样式和分页控件优化,提升用户体验
- 修复并完善 Api 文档,补充修改 Token 接口说明和示例代码
2025-12-01 23:41:55 +08:00

255 lines
6.8 KiB
Vue

<template>
<a-modal
v-model:visible="modalVisible"
:title="isEditMode ? '编辑Token' : '新增Token'"
width="600px"
@cancel="handleCancel"
@before-ok="handleBeforeOk"
>
<a-form
ref="formRef"
:model="formModel"
:rules="rules"
:label-col-props="{ span: 6 }"
:wrapper-col-props="{ span: 18 }"
label-align="left"
>
<a-form-item field="tokenName" label="Token名称" required>
<a-input
v-model="formModel.tokenName"
placeholder="请输入Token名称"
:max-length="100"
show-word-limit
/>
</a-form-item>
<a-form-item
v-if="!isEditMode"
field="tokenValue"
label="Token值"
required
>
<a-textarea
v-model="formModel.tokenValue"
placeholder="请输入Token值"
:max-length="1000"
:auto-size="{ minRows: 3, maxRows: 6 }"
show-word-limit
/>
</a-form-item>
<a-form-item field="phone" label="绑定手机号" required>
<a-input
v-model="formModel.phone"
placeholder="请输入绑定的手机号"
:max-length="11"
/>
</a-form-item>
<a-form-item field="remark" label="备注">
<a-textarea
v-model="formModel.remark"
placeholder="请输入备注信息"
:max-length="500"
:auto-size="{ minRows: 2, maxRows: 4 }"
show-word-limit
/>
</a-form-item>
<a-form-item field="rechargeLimitAmount" label="充值金额限制" required>
<a-input-number
v-model="formModel.rechargeLimitAmount"
placeholder="请输入充值金额限制"
:min="0"
:precision="2"
style="width: 100%"
/>
</a-form-item>
<a-form-item field="rechargeLimitCount" label="充值次数限制" required>
<a-input-number
v-model="formModel.rechargeLimitCount"
placeholder="请输入充值次数限制"
:min="0"
:precision="0"
style="width: 100%"
/>
</a-form-item>
</a-form>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue';
import { Notification, FormInstance } from '@arco-design/web-vue';
import { KamiApiCamelOilV1TokenInfo } from '@/api/generated/index.ts';
import { jdV2TokenClient } from '@/api/index.ts';
interface Props {
visible: boolean;
editData?: KamiApiCamelOilV1TokenInfo;
}
interface Emits {
(e: 'update:visible', value: boolean): void;
(e: 'success'): void;
}
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
const modalVisible = computed({
get: () => props.visible,
set: value => emit('update:visible', value)
});
const isEditMode = computed(() => !!props.editData);
const formRef = ref<FormInstance>();
const generateFormModel = () => {
return {
tokenId: 0,
tokenName: '',
tokenValue: '',
phone: '',
remark: '',
rechargeLimitAmount: 0,
rechargeLimitCount: 0
};
};
const formModel = reactive(generateFormModel());
const rules = computed(() => ({
tokenName: [
{ required: true, message: '请输入Token名称' },
{ min: 1, max: 100, message: 'Token名称长度为1-100个字符' }
],
tokenValue: [
{ required: !isEditMode.value, message: '请输入Token值' },
{ min: 1, max: 1000, message: 'Token值长度为1-1000个字符' }
],
phone: [
{ required: true, message: '请输入绑定手机号' },
{ match: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码' }
],
remark: [{ max: 500, message: '备注长度不能超过500个字符' }],
rechargeLimitAmount: [
{ required: true, message: '请输入充值金额限制' },
{ type: 'number', min: 0, message: '充值金额限制不能小于0' }
],
rechargeLimitCount: [
{ required: true, message: '请输入充值次数限制' },
{ type: 'number', min: 0, message: '充值次数限制不能小于0' }
]
}));
// 监听弹窗显示状态和编辑数据,更新表单
watch(
[() => props.visible, () => props.editData],
([visible, editData]) => {
if (visible) {
if (editData && isEditMode.value) {
// 编辑模式,填充现有数据
Object.assign(formModel, {
tokenName: editData.tokenName || '',
tokenValue: editData.tokenValue || '',
phone: editData.phone || '',
remark: editData.remark || '',
rechargeLimitAmount: editData.rechargeLimitAmount || 0,
rechargeLimitCount: editData.rechargeLimitCount || 0,
tokenId: editData.id || 0
});
} else {
// 新增模式,重置表单
Object.assign(formModel, generateFormModel());
}
}
},
{ immediate: true }
);
const handleCancel = () => {
emit('update:visible', false);
};
const handleBeforeOk = async () => {
try {
const valid = await formRef.value?.validate();
if (!valid) {
return false;
}
if (isEditMode.value) {
// 编辑Token
await jdV2TokenClient.apiTokenUpdatePost({
kamiApiCamelOilV1UpdateTokenReq: {
tokenId: formModel.tokenId,
tokenName: formModel.tokenName,
phone: formModel.phone,
remark: formModel.remark,
rechargeLimitAmount: formModel.rechargeLimitAmount,
rechargeLimitCount: formModel.rechargeLimitCount
}
});
Notification.success({
content: '编辑Token成功',
closable: true
});
} else {
// 新增Token
await jdV2TokenClient.apiTokenCreatePost({
kamiApiCamelOilV1CreateTokenReq: {
tokenName: formModel.tokenName,
tokenValue: formModel.tokenValue,
phone: formModel.phone,
remark: formModel.remark,
rechargeLimitAmount: formModel.rechargeLimitAmount,
rechargeLimitCount: formModel.rechargeLimitCount
}
});
Notification.success({
content: '新增Token成功',
closable: true
});
}
emit('success');
emit('update:visible', false);
return true;
} catch (err) {
const action = isEditMode.value ? '编辑' : '新增';
console.error(`${action}Token失败:`, err);
Notification.error({
content: `${action}Token失败`,
closable: true
});
return false;
}
};
</script>
<style scoped>
/* 使用 Arco Design 的原生样式,确保主题兼容性 */
:deep(.arco-modal-body) {
max-height: 60vh;
overflow-y: auto;
/* 确保滚动条样式跟随主题 */
scrollbar-width: thin;
scrollbar-color: var(--color-border-3) transparent;
}
:deep(.arco-modal-body::-webkit-scrollbar) {
width: 6px;
}
:deep(.arco-modal-body::-webkit-scrollbar-thumb) {
background-color: var(--color-border-3);
border-radius: 3px;
}
:deep(.arco-modal-body::-webkit-scrollbar-track) {
background-color: transparent;
}
</style>