You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 lines
14 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="订单编号" prop="projectCode">
<el-input v-model="queryParams.projectCode" placeholder="请输入订单编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="订单名称" prop="projectName">
<el-input v-model="queryParams.projectName" placeholder="请输入订单名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="合同编号" prop="contractCode">
<el-input v-model="queryParams.contractCode" placeholder="请输入合同编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="合同名称" prop="contractName">
<el-input v-model="queryParams.contractName" placeholder="请输入合同名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="订单状态" prop="projectStatus">
<el-select v-model="queryParams.projectStatus" placeholder="请选择订单状态" clearable>
<el-option v-for="dict in project_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<div class="mb-[10px] flex gap-[10px] flex-wrap">
<el-button :type="todoType === 'purchase' ? 'primary' : 'default'" @click="handleTodo('purchase')">待采购({{ todoCounts.purchase }}</el-button>
<el-button :type="todoType === 'shipping' ? 'primary' : 'default'" @click="handleTodo('shipping')">待发货({{ todoCounts.shipping }}</el-button>
<el-button :type="todoType === 'invoice' ? 'primary' : 'default'" @click="handleTodo('invoice')">待开票({{ todoCounts.invoice }}</el-button>
<el-button :type="todoType === 'payment' ? 'primary' : 'default'" @click="handleTodo('payment')">待回款({{ todoCounts.payment }}</el-button>
</div>
<el-card shadow="never">
<el-table v-loading="loading" border :data="tableList" class="data-table">
<el-table-column label="有无合同" align="center" prop="contractFlag" width="110">
<template #default="scope">
<dict-tag :options="contract_flag" :value="scope.row.contractFlag" />
</template>
</el-table-column>
<el-table-column label="订单编号" align="center" prop="projectCode" width="160" show-overflow-tooltip />
<el-table-column label="订单名称" align="center" prop="projectName" width="200">
<template #default="scope">
<el-link type="primary" underline @click="handleOrderLedger(scope.row)">
{{ scope.row.projectName }}
</el-link>
</template>
</el-table-column>
<el-table-column label="合同编号" align="center" prop="contractCode" width="160" />
<el-table-column label="合同名称" align="center" prop="contractName" width="220" show-overflow-tooltip />
<el-table-column label="业务方向" align="center" prop="businessDirection" width="120">
<template #default="scope">
<dict-tag :options="business_direction" :value="scope.row.businessDirection" />
</template>
</el-table-column>
<el-table-column label="订单类别" align="center" prop="projectCategory" width="150">
<template #default="scope">
<dict-tag :options="project_category" :value="scope.row.projectCategory" />
</template>
</el-table-column>
<el-table-column label="备件标识" align="center" prop="spareFlag" width="120">
<template #default="scope">
<dict-tag :options="spare_flag" :value="scope.row.spareFlag" />
</template>
</el-table-column>
<el-table-column label="付款方式" align="center" prop="paymentMethod" width="120" />
<el-table-column label="部门" align="center" prop="deptName" width="120" />
<el-table-column label="项目经理" align="center" prop="managerName" width="110" />
<el-table-column label="部门负责人" align="center" prop="chargeName" width="120" />
<el-table-column label="分管副总" align="center" prop="deputyName" width="110" />
<el-table-column label="金额" align="center" prop="amount" width="120">
<template #default="scope">
{{ scope.row.amount != null ? formatNumber(scope.row.amount) : '-' }}
</template>
</el-table-column>
<el-table-column label="订单状态" align="center" prop="projectStatus" width="120">
<template #default="scope">
<dict-tag :options="project_status" :value="scope.row.projectStatus" />
</template>
</el-table-column>
<el-table-column label="流程状态" align="center" prop="flowStatus" width="120">
<template #default="scope">
<dict-tag :options="wf_business_status" :value="scope.row.flowStatus" />
</template>
</el-table-column>
<el-table-column label="采购状态" align="center" prop="orderPurchaseStatus" width="120">
<template #default="scope">
<dict-tag :options="order_purchase_status" :value="scope.row.orderPurchaseStatus" />
</template>
</el-table-column>
<el-table-column label="发货状态" align="center" prop="orderDeliveryStatus" width="120">
<template #default="scope">
<dict-tag :options="order_delivery_status" :value="scope.row.orderDeliveryStatus" />
</template>
</el-table-column>
<el-table-column label="开票状态" align="center" prop="orderInvoiceStatus" width="120">
<template #default="scope">
<dict-tag :options="order_invoice_status" :value="scope.row.orderInvoiceStatus" />
</template>
</el-table-column>
<el-table-column label="回款百分比" align="center" prop="orderPaymentRate" width="130">
<template #default="scope">
{{ scope.row.orderPaymentRate != null ? scope.row.orderPaymentRate : 0 }}%
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" min-width="160" show-overflow-tooltip />
<el-table-column label="激活标识" align="center" prop="activeFlag" width="120">
<template #default="scope">
<dict-tag :options="active_flag" :value="scope.row.activeFlag" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="120" fixed="right">
<template #default="scope">
<el-tooltip content="修改" placement="top" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back'">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
</el-tooltip>
<el-tooltip content="查看详情" placement="top" v-if="scope.row.flowStatus !== 'draft'">
<el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
</div>
</template>
<script setup lang="ts" name="ContractOrderTodoIndex">
import { reactive, ref, getCurrentInstance, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { listContractOrder } from '@/api/oa/erp/contractOrder';
import { ProjectInfoVO, ProjectInfoQuery } from '@/api/oa/erp/projectInfo/types';
import type { FormInstance } from 'element-plus';
import { useUserStore } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const {
business_direction,
project_status,
active_flag,
contract_flag,
project_category,
spare_flag,
wf_business_status,
order_purchase_status,
order_delivery_status,
order_invoice_status
} = toRefs<any>(
proxy?.useDict('business_direction', 'project_status', 'active_flag', 'contract_flag', 'project_category', 'spare_flag', 'wf_business_status', 'order_purchase_status', 'order_delivery_status', 'order_invoice_status')
);
type TodoType = 'purchase' | 'shipping' | 'invoice' | 'payment';
const todoType = ref<TodoType>('purchase');
const loading = ref(true);
const tableList = ref<ProjectInfoVO[]>([]);
const total = ref(0);
const allList = ref<ProjectInfoVO[]>([]);
const todoCounts = reactive({
purchase: 0,
shipping: 0,
invoice: 0,
payment: 0
});
const showSearch = ref(true);
const queryFormRef = ref<FormInstance>();
const queryParams = reactive<any>({
pageNum: 1,
pageSize: 10,
// 检索框字段(仿照 contractOrderIndex
projectCode: undefined,
projectName: undefined,
contractCode: undefined,
contractName: undefined,
projectStatus: undefined
} as ProjectInfoQuery);
const formatNumber = (num: number) => {
// 保持与其它页面一致:显示到小数点后两位
return Number(num).toFixed(2);
};
const getCurrentUserId = () => String(userStore.userId ?? '').trim();
/** 字典:采购 4=已采购;发货 3=已发货;开票 3=已开票。待办 = 未完成态(不等于完成值,空值视为未完成) */
const norm = (v: unknown) => (v === null || v === undefined ? '' : String(v).trim());
const getTodoFilteredList = (type: TodoType, source: ProjectInfoVO[]) => {
if (type === 'purchase') {
return source.filter((item) => norm(item.orderPurchaseStatus) !== '4');
}
if (type === 'shipping') {
return source.filter((item) => norm(item.orderDeliveryStatus) !== '3');
}
if (type === 'invoice') {
return source.filter((item) => norm(item.orderInvoiceStatus) !== '3');
}
// 待回款:回款百分比未满 100%(与「未完成」一致)
return source.filter((item) => Number(item.orderPaymentRate ?? 0) < 100);
};
const applyCurrentTodoPage = () => {
const currentList = getTodoFilteredList(todoType.value, allList.value);
total.value = currentList.length;
const start = (queryParams.pageNum - 1) * queryParams.pageSize;
tableList.value = currentList.slice(start, start + queryParams.pageSize);
};
const applyTodoCounts = () => {
todoCounts.purchase = getTodoFilteredList('purchase', allList.value).length;
todoCounts.shipping = getTodoFilteredList('shipping', allList.value).length;
todoCounts.invoice = getTodoFilteredList('invoice', allList.value).length;
todoCounts.payment = getTodoFilteredList('payment', allList.value).length;
};
const getEditPathByCategory = () => {
// 该页面在现有合同订单列表中已固定为同一路径
return '/contract/contractInfo/orderActivate';
};
const handleOrderLedger = (row: ProjectInfoVO) => {
const _projectId = row?.projectId;
if (!_projectId) return;
proxy?.$tab.closePage(route);
router.push(`/oa/erp/orderLedger/${_projectId}`);
};
const handleView = (row?: ProjectInfoVO) => {
const _projectId = row?.projectId;
if (!_projectId) return;
proxy?.$tab.closePage(route);
router.push({
path: getEditPathByCategory(),
query: {
id: _projectId,
type: 'view'
}
});
};
const handleUpdate = (row?: ProjectInfoVO) => {
const _projectId = row?.projectId;
if (!_projectId) return;
proxy?.$tab.closePage(route);
router.push({
path: getEditPathByCategory(),
query: {
id: _projectId,
type: 'update'
}
});
};
const refreshAllList = async () => {
const userId = getCurrentUserId();
const res: any = await listContractOrder({
pageNum: 1,
pageSize: 9999,
// 查询参数用字符串传 LongSpring 可绑定为 Long且不会经 Number() 丢精度
createBy: userId || undefined,
projectCode: queryParams.projectCode,
projectName: queryParams.projectName,
contractCode: queryParams.contractCode,
contractName: queryParams.contractName,
projectStatus: queryParams.projectStatus
} as ProjectInfoQuery);
const rows: ProjectInfoVO[] = res.rows || [];
/**
* 合同订单列表 VOErpProjectInfoVo历史上未包含 createBy接口有数据时前端若再按 createBy 过滤会全部被剔除。
* 已传 createBy 时由后端过滤,直接使用 rows未登录用户 ID 时列表为空。
*/
if (userId) {
allList.value = rows;
} else {
allList.value = [];
}
};
const getList = async () => {
loading.value = true;
try {
await refreshAllList();
applyTodoCounts();
applyCurrentTodoPage();
} finally {
loading.value = false;
}
};
const handleTodo = async (type: TodoType) => {
todoType.value = type;
queryParams.pageNum = 1;
applyCurrentTodoPage();
};
const handleQuery = () => {
queryParams.pageNum = 1;
getList();
};
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
};
onMounted(() => {
getList();
});
</script>
<style scoped lang="scss">
.data-table {
:deep(.el-table__header) {
th {
font-weight: 600;
}
}
}
</style>