554 lines
14 KiB
Vue
554 lines
14 KiB
Vue
<script setup lang="ts">
|
|
import {ref, onMounted} from "vue";
|
|
import { useRoute } from "vue-router";
|
|
import myAxios from "../../api/myAxios";
|
|
import {message} from "ant-design-vue";
|
|
import { reactive } from 'vue';
|
|
|
|
const columns = [
|
|
{
|
|
title: '项目明细ID',
|
|
dataIndex: 'id',
|
|
width: 20,
|
|
key: 'id',
|
|
fixed: 'left',
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '项目明细名称',
|
|
dataIndex: 'projectDetailName',
|
|
key: 'projectDetailName',
|
|
width: 20,
|
|
fixed: 'left',
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '项目结算价',
|
|
dataIndex: 'projectSettlementPrice',
|
|
width: 30,
|
|
key: 'projectSettlementPrice',
|
|
fixed: 'left',
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '项目最小结算价',
|
|
dataIndex: 'projectMinSettlementPrice',
|
|
width: 30,
|
|
key: 'projectMinSettlementPrice',
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '最大抽成比例',
|
|
dataIndex: 'maxCommissionRate',
|
|
width: 40,
|
|
key: 'maxCommissionRate',
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '项目ID',
|
|
dataIndex: 'projectId',
|
|
key: 'projectId',
|
|
width: 70,
|
|
align: 'center'
|
|
},
|
|
{
|
|
title: '操作',
|
|
key: 'action',
|
|
fixed: 'right',
|
|
width: 70,
|
|
align: 'center'
|
|
}
|
|
];
|
|
|
|
interface ProjectDetail {
|
|
id: number;
|
|
projectDetailName: string;
|
|
projectSettlementPrice: number;
|
|
projectMinSettlementPrice: number; // 修正接口字段
|
|
maxCommissionRate: number;
|
|
projectId: number;
|
|
}
|
|
|
|
const route = useRoute();
|
|
const projectId = ref<string | number>("");
|
|
const tableData = ref<ProjectDetail[]>([]); // 改为数组存储
|
|
const loading = ref(false);
|
|
const error = ref("");
|
|
const searchId = ref(""); // 新增搜索ID绑定
|
|
|
|
const getMoneyDetail = async (id: string | number) => {
|
|
const storedToken = localStorage.getItem('token');
|
|
try {
|
|
loading.value = true;
|
|
const response:any = await myAxios.post(
|
|
"/projectDetail/query/pid",
|
|
{ id },
|
|
{
|
|
headers: {
|
|
Authorization: storedToken,
|
|
"Content-Type": "application/json"
|
|
}
|
|
}
|
|
);
|
|
|
|
if (response.code === 1) {
|
|
tableData.value = response.data;
|
|
} else {
|
|
error.value = "获取项目详情失败";
|
|
tableData.value = [];
|
|
}
|
|
} catch (err) {
|
|
error.value = "数据加载失败,请重试";
|
|
tableData.value = [];
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// 新增根据明细ID查询的方法
|
|
const queryDetailById = async (id: string | number) => {
|
|
const storedToken = localStorage.getItem('token');
|
|
try {
|
|
loading.value = true;
|
|
const response:any = await myAxios.post(
|
|
"/projectDetail/queryById", // 使用文档中的接口路径
|
|
{ id }, // 请求参数
|
|
{
|
|
headers: {
|
|
Authorization: storedToken,
|
|
"Content-Type": "application/json"
|
|
}
|
|
}
|
|
);
|
|
console.log(response.data)
|
|
if (response.code === 1) {
|
|
tableData.value = [response.data];
|
|
} else {
|
|
message.error(response.message || "查询失败");
|
|
tableData.value = [];
|
|
}
|
|
} catch (err) {
|
|
message.error("查询请求失败");
|
|
tableData.value = [];
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// 新增搜索处理方法
|
|
const handleIdSearch = async (value: string) => {
|
|
if (!value.trim()) {
|
|
message.warning("请输入有效的项目明细ID");
|
|
return;
|
|
}
|
|
|
|
const id = Number(value);
|
|
if (isNaN(id)) {
|
|
message.warning("ID必须为数字");
|
|
return;
|
|
}
|
|
|
|
await queryDetailById(id);
|
|
};
|
|
|
|
// 修改重置方法
|
|
const reset = () => {
|
|
searchId.value = "";
|
|
// 重置时重新加载原始项目数据
|
|
if (projectId.value) {
|
|
getMoneyDetail(projectId.value);
|
|
}
|
|
};
|
|
|
|
// 初始化逻辑
|
|
if (typeof route.query.id === "string") {
|
|
projectId.value = route.query.id;
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (projectId.value) {
|
|
getMoneyDetail(projectId.value);
|
|
}
|
|
});
|
|
|
|
const deleteMoneyDetail = async (id: number) => {
|
|
try {
|
|
const storedToken = localStorage.getItem('token');
|
|
// 修正接口路径为项目明细的删除接口
|
|
const res: any = await myAxios.post(
|
|
"/projectDetail/delete", // 修改这里
|
|
{ id },
|
|
{
|
|
headers: {
|
|
Authorization: storedToken,
|
|
'AfterScript': 'required-script'
|
|
}
|
|
}
|
|
);
|
|
|
|
if (res.code === 1) {
|
|
message.success('删除成功');
|
|
if (projectId.value) {
|
|
await getMoneyDetail(projectId.value);
|
|
}
|
|
} else {
|
|
message.error(res.message || '删除失败');
|
|
}
|
|
} catch (error) {
|
|
console.error('删除失败:', error);
|
|
message.error('删除操作失败');
|
|
}
|
|
};
|
|
|
|
const drawerVisible = ref(false);
|
|
const formState = reactive({
|
|
id: 0,
|
|
projectDetailName: '',
|
|
projectSettlementPrice: 0,
|
|
projectMinSettlementPrice: 0,
|
|
maxCommissionRate: 0,
|
|
projectId: 0
|
|
});
|
|
|
|
// 修改updateMoneyDetail方法
|
|
const updateMoneyDetail = async (id: number) => {
|
|
try {
|
|
// 先获取明细数据
|
|
const storedToken = localStorage.getItem('token');
|
|
const res:any = await myAxios.post(
|
|
"/projectDetail/queryById",
|
|
{ id },
|
|
{
|
|
headers: {
|
|
Authorization: storedToken,
|
|
"Content-Type": "application/json"
|
|
}
|
|
}
|
|
);
|
|
if (res.code === 1) {
|
|
// 映射字段到表单
|
|
const detail = res.data;
|
|
Object.assign(formState, {
|
|
id: detail.id,
|
|
projectDetailName: detail.projectDetailName,
|
|
projectSettlementPrice: detail.projectSettlementPrice,
|
|
projectMinSettlementPrice: detail.projectMinSettlementPrice,
|
|
maxCommissionRate: detail.maxCommissionRate,
|
|
projectId: detail.projectId
|
|
});
|
|
drawerVisible.value = true;
|
|
}
|
|
} catch (error) {
|
|
message.error('获取明细数据失败');
|
|
}
|
|
};
|
|
|
|
// 新增表单相关状态
|
|
const addDrawerVisible = ref(false);
|
|
const addFormState = reactive({
|
|
projectDetailName: '',
|
|
projectSettlementPrice: 0,
|
|
projectMinSettlementPrice: 0, // 注意字段名称需要与接口一致
|
|
maxCommissionRate: 0,
|
|
projectId: 0
|
|
});
|
|
|
|
// 打开新增表单
|
|
const openAddDrawer = () => {
|
|
addFormState.projectId = Number(projectId.value); // 关联当前项目
|
|
addDrawerVisible.value = true;
|
|
};
|
|
|
|
// 提交新增请求
|
|
const handleAddSubmit = async () => {
|
|
try {
|
|
const storedToken = localStorage.getItem('token');
|
|
const res:any = await myAxios.post(
|
|
"/projectDetail/add",
|
|
{
|
|
projectDetailName: addFormState.projectDetailName,
|
|
projectSettlementPrice: addFormState.projectSettlementPrice,
|
|
projectMinSettlementPrice: addFormState.projectMinSettlementPrice, // 字段映射
|
|
maxCommissionRate: addFormState.maxCommissionRate,
|
|
projectId: addFormState.projectId
|
|
},
|
|
{
|
|
headers: {
|
|
Authorization: storedToken,
|
|
"Content-Type": "application/json"
|
|
}
|
|
}
|
|
);
|
|
|
|
if (res.code === 1) {
|
|
message.success('新增成功');
|
|
addDrawerVisible.value = false;
|
|
await getMoneyDetail(projectId.value); // 刷新列表
|
|
// 重置表单
|
|
Object.assign(addFormState, {
|
|
projectDetailName: '',
|
|
projectSettlementPrice: 0,
|
|
projectMinSettlementPrice: 0,
|
|
maxCommissionRate: 0,
|
|
projectId: Number(projectId.value)
|
|
});
|
|
} else {
|
|
message.error(res.message || '新增失败');
|
|
}
|
|
} catch (error) {
|
|
message.error('新增请求失败');
|
|
}
|
|
};
|
|
|
|
// 修改模板按钮绑定
|
|
const goAddProject = () => {
|
|
openAddDrawer();
|
|
};
|
|
|
|
// 修改handleSubmit方法
|
|
const handleSubmit = async () => {
|
|
try {
|
|
const storedToken = localStorage.getItem('token');
|
|
const res:any = await myAxios.post(
|
|
"/projectDetail/update",
|
|
{
|
|
// 根据接口文档调整字段映射
|
|
id: formState.id,
|
|
projectDetailName: formState.projectDetailName,
|
|
projectSettlementPrice: formState.projectSettlementPrice,
|
|
projectMinSettlementPrice: formState.projectMinSettlementPrice,
|
|
maxCommissionRate: formState.maxCommissionRate,
|
|
projectId: formState.projectId
|
|
},
|
|
{
|
|
headers: {
|
|
Authorization: storedToken,
|
|
"Content-Type": "application/json"
|
|
}
|
|
}
|
|
);
|
|
|
|
console.log('接口响应:', res); // 添加详细日志
|
|
|
|
if (res.code === 1) { // 注意响应结构层级
|
|
message.success('更新成功');
|
|
drawerVisible.value = false;
|
|
// 根据当前查看模式刷新
|
|
if (searchId.value) {
|
|
await queryDetailById(formState.id);
|
|
} else {
|
|
await getMoneyDetail(projectId.value);
|
|
}
|
|
} else {
|
|
message.error(res.message || `更新失败,错误码:${res.code}`);
|
|
}
|
|
} catch (error) {
|
|
console.error('完整错误信息:', error); // 输出完整错误对象
|
|
message.error(`更新失败'}`);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<!-- 搜索框 -->
|
|
<div class="search-box">
|
|
<a-form layout="inline">
|
|
<a-space>
|
|
<a-form-item label="ID">
|
|
<a-input-search
|
|
style="width: 300px"
|
|
placeholder="请输入项目明细ID"
|
|
enter-button
|
|
@search="handleIdSearch"
|
|
v-model:value="searchId"
|
|
/>
|
|
</a-form-item>
|
|
<a-button type="primary" @click="goAddProject">新增项目明细</a-button>
|
|
<a-button type="primary" @click="reset">重置搜索</a-button>
|
|
</a-space>
|
|
</a-form>
|
|
</div>
|
|
|
|
<!-- 数据表格 -->
|
|
<a-table
|
|
:columns="columns"
|
|
:data-source="tableData"
|
|
:scroll="{ x: 1500, y: 450 }"
|
|
:loading="loading"
|
|
bordered
|
|
rowKey="id"
|
|
>
|
|
<template #bodyCell="{ column, record }">
|
|
<!-- 格式化金额显示 -->
|
|
<template v-if="column.dataIndex === 'projectSettlementPrice'">
|
|
¥{{ record.projectSettlementPrice.toFixed(2) }}
|
|
</template>
|
|
|
|
<template v-if="column.dataIndex === 'projectWinSettlementPrice'">
|
|
¥{{ record.projectWinSettlementPrice.toFixed(2) }}
|
|
</template>
|
|
|
|
<!-- 操作列 -->
|
|
<template v-if="column.key === 'action'">
|
|
<a-space :size="8">
|
|
<a-button
|
|
size="small"
|
|
danger
|
|
@click="deleteMoneyDetail(record.id)"
|
|
>
|
|
删除
|
|
</a-button>
|
|
<a-button
|
|
size="small"
|
|
@click="updateMoneyDetail(record.id)"
|
|
>
|
|
编辑
|
|
</a-button>
|
|
</a-space>
|
|
</template>
|
|
</template>
|
|
</a-table>
|
|
|
|
<!-- 错误提示 -->
|
|
<div v-if="error" class="error-alert">
|
|
<span class="error-icon">!</span>
|
|
{{ error }}
|
|
</div>
|
|
|
|
<!-- 修改编辑抽屉的表单项 -->
|
|
<a-drawer
|
|
title="编辑项目明细"
|
|
placement="right"
|
|
:visible="drawerVisible"
|
|
@close="drawerVisible = false"
|
|
width="600"
|
|
>
|
|
<a-form
|
|
:model="formState"
|
|
layout="vertical"
|
|
@finish="handleSubmit"
|
|
>
|
|
<a-form-item label="项目明细名称">
|
|
<a-input v-model:value="formState.projectDetailName" />
|
|
</a-form-item>
|
|
|
|
<a-form-item label="项目结算价">
|
|
<a-input-number
|
|
v-model:value="formState.projectSettlementPrice"
|
|
style="width: 100%"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item label="项目最小结算价">
|
|
<a-input-number
|
|
v-model:value="formState.projectMinSettlementPrice"
|
|
style="width: 100%"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item label="最大抽成比例">
|
|
<a-input-number
|
|
v-model:value="formState.maxCommissionRate"
|
|
style="width: 100%"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<a-button type="primary" html-type="submit">提交</a-button>
|
|
<a-button style="margin-left: 10px" @click="drawerVisible = false">取消</a-button>
|
|
</a-form-item>
|
|
</a-form>
|
|
</a-drawer>
|
|
|
|
<!-- 修改新增抽屉的表单项 -->
|
|
<a-drawer
|
|
title="新增项目明细"
|
|
placement="right"
|
|
:visible="addDrawerVisible"
|
|
@close="addDrawerVisible = false"
|
|
width="600"
|
|
>
|
|
<a-form
|
|
:model="addFormState"
|
|
layout="vertical"
|
|
@finish="handleAddSubmit"
|
|
>
|
|
<a-form-item label="明细名称">
|
|
<a-input v-model:value="addFormState.projectDetailName" />
|
|
</a-form-item>
|
|
|
|
<a-form-item label="结算价">
|
|
<a-input-number
|
|
v-model:value="addFormState.projectSettlementPrice"
|
|
style="width: 100%"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item label="最小结算价">
|
|
<a-input-number
|
|
v-model:value="addFormState.projectMinSettlementPrice"
|
|
style="width: 100%"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item label="抽成比例">
|
|
<a-input-number
|
|
v-model:value="addFormState.maxCommissionRate"
|
|
style="width: 100%"
|
|
/>
|
|
</a-form-item>
|
|
|
|
<a-form-item>
|
|
<a-button type="primary" html-type="submit">提交</a-button>
|
|
<a-button style="margin-left: 10px" @click="addDrawerVisible = false">
|
|
取消
|
|
</a-button>
|
|
</a-form-item>
|
|
</a-form>
|
|
</a-drawer>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.search-box {
|
|
margin-bottom: 20px;
|
|
padding: 16px;
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.error-alert {
|
|
padding: 1rem;
|
|
background: #ffe3e3;
|
|
color: #ff4444;
|
|
border-radius: 6px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.8rem;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.error-icon {
|
|
display: inline-block;
|
|
width: 1.2rem;
|
|
height: 1.2rem;
|
|
border-radius: 50%;
|
|
background: #ff4444;
|
|
color: white;
|
|
text-align: center;
|
|
line-height: 1.2rem;
|
|
font-weight: bold;
|
|
}
|
|
|
|
:deep(.ant-table-thead) {
|
|
background-color: #fafafa !important;
|
|
font-weight: 600;
|
|
}
|
|
|
|
:deep(.ant-table-row:hover) {
|
|
background-color: #fafafa !important;
|
|
}
|
|
</style> |