<script setup lang="tsx">
import { DataTableSortState, NButton, NTag, SelectOption } from "naive-ui";
import {
fetchGetChangeLedgerList,
fetchBatchDeleteChange,
fetchDeleteChange,
} from "@/service/api";
import { generateZtUri } from "@/plugins";
import { $t } from "@/locales";
import { useAppStore } from "@/store/modules/app";
import { useTable, useTableOperate } from "@/hooks/common/table";
import { useAuth } from "@/hooks/business/auth";
import LedgerSearch from "./modules/ledger-search.vue";
import { useBoolean } from "@sa/hooks";
import { canUpgradeRecord } from "@/constants/business";
import { ref, onMounted, watch, h } from "vue";
// import {useDepartment} from "@/hooks/common/useDepartment"
// 导入嵌入模态框
import { getFullDeptOptions } from "@/service/api/"; // 导入完整部门选项服务
import { renderTooltip2, smartTextSplit } from "@/utils/other";
// 存储完整部门选项
const fullDeptOptions = ref<SelectOption[]>([]);
// 加载完整部门列表
onMounted(async () => {
fullDeptOptions.value = await getFullDeptOptions();
});
const appStore = useAppStore();
const {
columns,
columnChecks,
data,
getData,
loading,
mobilePagination,
searchParams,
resetSearchParams,
} = useTable({
apiFn: fetchGetChangeLedgerList,
showTotal: true,
apiParams: {
current: 1,
size: 10,
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
// the value can not be undefined, otherwise the property in Form will not be reactive
source: null,
pecoName: null,
peco: null,
softwareChange: null,
projectno: null,
dept: null,
canUpgrade: null,
softResponsiblePerson: null,
elecResponsiblePerson: null,
changeResponsiblePerson: null,
customerDemandTime: null,
softCompletionTime: null,
hardCompletionTime: null,
fmtCustomerDemandTime: null,
fmtSoftCompletionTime: null,
fmtHardCompletionTime: null,
orderList: [],
},
columns: () => [
{
type: "selection",
align: "center",
width: 48,
},
{
key: "index",
title: $t("common.index"),
align: "center",
width: 64,
sorter: false,
},
{
key: "hwswcoId",
title: $t("page.change.ledger.hwswcoId"),
align: "left",
minWidth: 50,
width: 80,
maxWidth: 200,
sorter: true,
fixed: "left",
resizable: true,
// render: (row) => (
// <div class="flex-center gap-8px">
// <a href={`${row?.hwswco_url}${row.hwswcoId}.html`} target='_blank' style='color:#646cff'>
// {row.hwswcoId}
// </a>
// </div>
// ),
render: (row) => {
//const href = `${row?.test_url}${row.testProcessId}?zentaosid=${appStore.zenTaoSid}`;
const contents: any[] = [];
contents.push(
`未填写${$t("page.change.ledger.hwswcoId")}, 无法跳转禅道`,
);
if (row.hwswcoId !== null) {
return h(
NButton,
{
strong: true,
secondary: true,
size: "small",
type: "info",
onClick: () => {
const href = generateZtUri(`${row?.hwswco_url}`);
window.open(href, "_blank");
},
},
{
default: () => row.hwswcoId,
},
);
} else {
return <NTag>{row.hwswcoId}</NTag>;
}
},
},
{
key: "source",
title: $t("page.change.ledger.source"),
align: "center",
width: 80,
sorter: true,
resizable: true,
},
{
key: "pecoName",
title: $t("page.change.ledger.pecoName"),
align: "center",
minWidth: 50,
width: 100,
maxWidth: 200,
sorter: true,
resizable: true,
render: (row) => {
const contents: any[] = smartTextSplit(row.pecoName, 50);
return row.pecoName
? renderTooltip2(row.pecoName.slice(0, 10), contents)
: null;
},
},
{
key: "peco",
title: $t("page.change.ledger.peco"),
align: "center",
minWidth: 50,
width: 100,
maxWidth: 200,
sorter: true,
resizable: true,
},
{
key: "softwareChange",
title: $t("page.change.ledger.softwareChange"),
align: "center",
minWidth: 50,
width: 100,
maxWidth: 200,
sorter: true,
resizable: true,
},
{
key: "projectno",
title: $t("page.change.ledger.projectno"),
align: "center",
minWidth: 40,
width: 80,
maxWidth: 100,
sorter: true,
resizable: true,
},
{
key: "dept",
title: $t("page.change.ledger.dept"),
align: "center",
width: 130,
sorter: true,
render: (row) => {
// 使用完整部门选项映射部门名称
if (row.dept && fullDeptOptions.value.length > 0) {
const dept = fullDeptOptions.value.find(
(option) => option.value === row.dept,
);
if (dept) {
return <spn>{dept.label}</spn>;
}
}
return null;
},
},
{
key: "softResponsiblePersonName",
title: $t("page.change.ledger.softResponsiblePersonName"),
align: "center",
minWidth: 50,
width: 110,
maxWidth: 200,
sorter: true,
resizable: true,
},
{
key: "elecResponsiblePersonName",
title: $t("page.change.ledger.elecResponsiblePersonName"),
align: "center",
minWidth: 50,
width: 110,
maxWidth: 200,
sorter: true,
resizable: true,
},
// {
// key: "changeResponsiblePerson",
// title: $t("page.change.ledger.changeResponsiblePerson"),
// align: "center",
// minWidth: 50,
// },
{
key: "canUpgrade",
title: $t("page.change.ledger.canUpgrade"),
align: "center",
minWidth: 50,
width: 80,
maxWidth: 100,
sorter: true,
resizable: true,
typeRecord: canUpgradeRecord,
render: (row) => {
console.log(row.canUpgrade);
if (row.canUpgrade) {
// console.log( row.canUpgrade, canUpgradeRecord[
// row.canUpgrade as Api.Change.canUpgrade
// ])
const label = $t(
canUpgradeRecord[row.canUpgrade as Api.Change.canUpgrade],
);
return <NTag type="default">{label}</NTag>;
}
return null;
},
},
{
key: "fmtCustomerDemandTime",
title: $t("page.change.ledger.customerDemandTime"),
align: "center",
width: 100,
sorter: true,
resizable: true,
render: (row) =>
row.fmtCustomerDemandTime === "1970-01-01"
? null
: row.fmtCustomerDemandTime,
},
{
key: "fmtSoftCompletionTime",
title: $t("page.change.ledger.softCompletionTime"),
align: "center",
width: 100,
sorter: true,
resizable: true,
render: (row) =>
row.fmtSoftCompletionTime === "1970-01-01"
? null
: row.fmtSoftCompletionTime,
},
{
key: "fmtHardCompletionTime",
title: $t("page.change.ledger.hardCompletionTime"),
align: "center",
width: 100,
sorter: true,
resizable: true,
render: (row) =>
row.fmtHardCompletionTime === "1970-01-01"
? null
: row.fmtHardCompletionTime,
},
{
key: "operate",
title: $t("common.operate"),
align: "center",
width: 130,
fixed: "right",
render: (row) => (
<div class="flex-center gap-8px">
{hasAuth("B_ChangeLedger_Upgrade") ? (
<NButton
type="primary"
ghost
size="small"
onClick={() => {
const href = generateZtUri(`${row?.hwswco_upgrade_url}`);
window.open(href, "_blank");
}}
>
{$t("common.upgrade")}
</NButton>
) : null}
{hasAuth("B_ChangeLedger_Assign") ? (
<NButton
type="primary"
ghost
size="small"
onClick={() => {
const href = generateZtUri(`${row?.hwswco_url}`);
window.open(href, "_blank");
}}
>
{$t("common.assign")}
</NButton>
) : null}
</div>
),
},
],
});
const {
drawerVisible,
operateType,
editingData,
handleAdd,
handleEdit,
handleClone,
checkedRowKeys,
onBatchDeleted,
onDeleted,
// closeDrawer
} = useTableOperate(data, getData);
// 定义排序器
// const sorter = ref<DataTableSortState | null>(null);
// // 使用自定义钩子
// const { sortTable } = useTableSort(data, sorter);
// 处理排序器变化
const handleSorterChange = (newSorter: DataTableSortState) => {
let columnKey = String(newSorter.columnKey);
// 移除fmt前缀(不区分大小写)
if (/^fmt/i.test(columnKey)) {
columnKey = columnKey.substring(3);
}
// 小驼峰转下划线命名(优化连续大写字母处理)
columnKey = columnKey
.replace(/([a-z])([A-Z])/g, "$1_$2")
.replace(/([A-Z])([A-Z][a-z])/g, "$1_$2")
.toLowerCase();
// 处理排序状态
if (newSorter.order === "ascend") {
searchParams.orderList = [columnKey];
} else if (newSorter.order === "descend") {
searchParams.orderList = ["-" + columnKey];
} else {
searchParams.orderList = [];
}
getData();
};
const { hasAuth } = useAuth();
const { bool: uploadVisible, setTrue: openModal } = useBoolean();
async function handleBatchDelete() {
// request
const { error } = await fetchBatchDeleteChange({
ids: checkedRowKeys.value,
});
if (!error) {
onBatchDeleted();
}
}
async function handleDelete(id: number) {
// request
const { error } = await fetchDeleteChange({ id });
if (!error) {
onDeleted();
}
}
function edit(id: number) {
handleEdit(id);
}
function clone(id: number) {
handleClone(id);
}
interface Emits {
(e: "update-total", payload: number | undefined): void;
}
const emit = defineEmits<Emits>();
watch(
() => mobilePagination.value.itemCount,
(newVal, oldVal) => {
emit("update-total", newVal);
},
{ deep: true },
);
// async function handleDownload() {
// // 请求cosnt {data, error } = await fetchGetProblemList({size:xxx,current:1})
// if (checkedRowKeys.value.length === 0) {
// window.$message?.warning('请选择需要导出的数据!');
// return;
// }
// const { data:responseData, error } = await fetchGetChangeLedgerList({
// size: checkedRowKeys.value.length,
// current: 1,
// ids: checkedRowKeys.value,
// });
// if (error) {
// console.error("获取数据时出错:", error);
// alert("获取数据时发生错误,请稍后再试。");
// return;
// }
// // 关键修改:将部门ID转换为部门名称
// const processedRecords = responseData.records.map(record => {
// // 查找匹配的部门选项
// const deptOption = fullDeptOptions.value.find(
// option => option.value === record.dept
// );
// // 转换canUpgrade数值为文本标签
// const upgradeLabel = canUpgradeRecord[record.canUpgrade as keyof typeof canUpgradeRecord]
// ? $t(canUpgradeRecord[record.canUpgrade as keyof typeof canUpgradeRecord])
// : record.canUpgrade; // 未匹配时保留原值
// // 返回新对象(保留原数据,替换dept和canUpgrade字段)
// return {
// ...record,
// dept: deptOption ? deptOption.label : record.dept,
// canUpgrade: upgradeLabel // 替换为转换后的文本
// };
// });
// // 翻译表头
// const titleMap = {
// hwswcoId: $t("page.change.ledger.hwswcoId"),
// source: $t("page.change.ledger.source"),
// pecoName: $t("page.change.ledger.pecoName"),
// peco: $t("page.change.ledger.peco"),
// softwareChange:$t("page.change.ledger.softwareChange"),
// projectno: $t("page.change.ledger.projectno"),
// dept: $t("page.change.ledger.dept"),
// softResponsiblePersonName: $t("page.change.ledger.softResponsiblePersonName"),
// elecResponsiblePersonName: $t("page.change.ledger.elecResponsiblePersonName"),
// canUpgrade: $t("page.change.ledger.canUpgrade"),
// // customerDemandTime: $t("page.change.ledger.customerDemandTime"),
// // softCompletionTime: $t("page.change.ledger.softCompletionTime"),
// // hardCompletionTime: $t("page.change.ledger.hardCompletionTime"),
// fmtCustomerDemandTime: $t("page.change.ledger.fmtCustomerDemandTime"),
// fmtSoftCompletionTime: $t("page.change.ledger.fmtSoftCompletionTime"),
// fmtHardCompletionTime: $t("page.change.ledger.fmtHardCompletionTime"),
// };
// const headers = Object.keys(titleMap).map((key) => titleMap[key]);
// const sheetData = [headers];
// processedRecords.forEach(record => {
// const row = Object.keys(titleMap).map(key => record[key]);
// sheetData.push(row);
// });
// const sheetName = $t("page.change.ledger.title");
// const sheets: SheetData[] = [
// {
// sheetName: sheetName,
// data: sheetData,
// },
// ];
// exportXlsx(sheets, `${sheetName}`);
// }
// 在页面加载时获取最新数据
getData();
</script>
<template>
<div
class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto"
>
<LedgerSearch
v-model:model="searchParams"
@reset="resetSearchParams"
@search="getData"
/>
<NCard :bordered="false" size="small" class="sm:flex-1-hidden card-wrapper">
<template #header
>{{ $t("page.change.ledger.title") }}
<span style="font-size: 10px"
>({{
$t("datatable.itemCount", {
total: mobilePagination?.itemCount,
})
}})</span
>
</template>
<template #header-extra>
<TableHeaderOperation
v-model:columns="columnChecks"
:disabled-delete="checkedRowKeys.length === 0"
:loading="loading"
table-id="api"
@add="handleAdd"
@delete="handleBatchDelete"
@refresh="getData"
>
<template #default>
<TableDownload
:size="checkedRowKeys.length"
:ids="checkedRowKeys"
:columns="columns"
:apiParams="searchParams"
:apiFn="fetchGetChangeLedgerList"
excelName="变更台账"
/>
</template>
</TableHeaderOperation>
</template>
<NDataTable
v-model:checked-row-keys="checkedRowKeys"
:columns="columns"
:data="data"
size="small"
:flex-height="!appStore.isMobile"
:scroll-x="2400"
:loading="loading"
remote
:row-key="(row) => row.id"
:pagination="mobilePagination"
class="sm:h-full"
@update:sorter="handleSorterChange"
/>
</NCard>
</div>
</template>
<style scoped></style>