| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // @/API/admin.ts
- import { api8000 } from '@/utils/request';
- import { ElMessage } from 'element-plus';
- import 'element-plus/es/components/message/style/css';
- // 🔹 获取表格数据
- export const table = (params: { table: string }) => {
- return api8000({
- url: "/admin/table",
- method: "GET",
- params: params,
- })
- .then((res) => {
- // 适配后端返回的直接数组格式
- return { data: Array.isArray(res.data) ? res.data : [] };
- })
- .catch((err) => {
- if (err.response?.status === 401) throw err;
- throw new Error(err.message || "获取数据失败");
- });
- };
- // 🔹 新增数据
- export const addItem = (data: {
- table: string;
- item: Record<string, any>;
- }) => {
- return api8000({
- url: "/admin/add_item",
- method: "POST",
- params: { table: data.table },
- data: data.item,
- }).catch((error) => {
- if (error.response?.status === 400 && error.response.data.detail === "重复数据") {
- ElMessage.error("数据重复,请重新添加");
- }
- throw error;
- });
- };
- // 🔹 更新数据
- export const updateItem = (data: {
- table: string;
- id: number;
- update_data: Record<string, any>;
- }) => {
- return api8000({
- url: "/admin/update_item",
- method: "PUT",
- params: { table: data.table, id: data.id },
- data: data.update_data,
- }).catch((error) => {
- if (error.response?.status === 400 && error.response.data.detail === "重复数据") {
- ElMessage.error("数据重复,无法更新");
- }
- throw error;
- });
- };
- // 🔹 删除数据
- export const deleteItemApi = (params: {
- table: string;
- id: number;
- }) => {
- return api8000({
- url: "/admin/delete_item",
- method: "DELETE",
- params: params,
- });
- };
- // 🔹 导出数据
- export const exportData = (table: string, format: string = "xlsx") => {
- return api8000({
- url: "/admin/export_data",
- method: "GET",
- params: { table, fmt: format },
- responseType: "blob",
- })
- .then((response) => {
- const contentDisposition = response.headers["content-disposition"];
- if (!contentDisposition) {
- throw new Error("无法获取文件名");
- }
- const filenameMatch = contentDisposition.match(/filename=([^;]+)/);
- const filename = filenameMatch ? decodeURIComponent(filenameMatch[1]) : `${table}_data.${format === "xlsx" ? "xlsx" : "csv"}`;
- const blob = new Blob([response.data], {
- type: format === "xlsx"
- ? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
- : "text/csv",
- });
- const url = window.URL.createObjectURL(blob);
- const link = document.createElement("a");
- link.href = url;
- link.download = filename;
- link.click();
- window.URL.revokeObjectURL(url);
- })
- .catch((error) => {
- console.error("❌ 导出数据失败:", error);
- throw error;
- });
- };
- // 🔹 导入数据
- export const importData = (table: string, file: File) => {
- // 1. 前置校验提示(文件为空/格式错误)
- if (!file || file.size === 0) {
- const errorMsg = "❌ 请选择非空的Excel/CSV文件,空文件无法导入";
- console.error(errorMsg);
- throw new Error(errorMsg);
- }
- const validExtensions = ['xlsx', 'csv'];
- const fileExtension = file.name.split('.').pop()?.toLowerCase();
- if (!fileExtension || !validExtensions.includes(fileExtension)) {
- const errorMsg = `❌ 仅支持 .xlsx 和 .csv 格式文件,当前文件格式为 .${fileExtension || '未知'}`;
- console.error(errorMsg);
- throw new Error(errorMsg);
- }
- // 2. 创建FormData(与后端参数名对齐)
- const formData = new FormData();
- formData.append('table', table);
- formData.append('file', file);
- return api8000({
- url: "/admin/import_data",
- method: "POST",
- data: formData,
- headers: {
- 'Content-Type': 'multipart/form-data'
- }
- })
- .then((response) => {
- const { total_data, new_data, duplicate_data } = response.data;
- let successMsg = "";
- if (total_data === 0) {
- successMsg = "✅ 文件导入成功,但文件中无有效数据(空内容)";
- } else {
- successMsg = `✅ 数据导入成功!共${total_data}条数据,新增${new_data}条,重复${duplicate_data}条`;
- }
- console.log(successMsg, "详情:", response.data);
- ElMessage.success(successMsg);
- return response.data;
- })
- .catch((error) => {
- let errorMsg = "❌ 导入失败,请稍后重试";
- if (error.response?.data) {
- const resData = error.response.data;
- if (resData.detail?.duplicate_count && resData.detail?.duplicates) {
- const { duplicate_count, duplicates, check_fields } = resData.detail;
- const duplicateDetails = duplicates.map((item: any) =>
- `第${item.row_number}行:${check_fields.map((f: string) => `${f}=${item.duplicate_fields[f] || '空值'}`).join(',')}`
- ).join('\n');
- errorMsg = `❌ 检测到${duplicate_count}条重复数据(基于${check_fields.join('、')}字段):\n${duplicateDetails}`;
- } else if (resData.detail) {
- errorMsg = `❌ ${resData.detail.message || resData.detail}`;
- } else if (resData.message) {
- errorMsg = `❌ ${resData.message}`;
- }
- } else if (!error.response) {
- errorMsg = "❌ 网络异常或服务器无响应,请检查网络连接后重试";
- } else {
- errorMsg = "❌ 未知错误,可能是文件损坏或服务器繁忙";
- }
- console.error(errorMsg, "错误详情:", error);
- ElMessage.error(errorMsg);
- throw new Error(errorMsg);
- });
- };
- // 🔹 下载模板
- export const downloadTemplate = (table: string, format: string = "excel") => {
- return api8000({
- url: "/admin/download_template",
- method: "GET",
- params: { table, format },
- responseType: "blob",
- })
- .then((response) => {
- const contentDisposition = response.headers["content-disposition"];
- if (!contentDisposition) {
- throw new Error("无法获取文件名");
- }
- const filenameMatch = contentDisposition.match(/filename=([^;]+)/);
- const filename = filenameMatch ? decodeURIComponent(filenameMatch[1]) : `${table}_template.${format === "excel" ? "xlsx" : "csv"}`;
- const blob = new Blob([response.data], {
- type: format === "excel"
- ? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
- : "text/csv",
- });
- const url = window.URL.createObjectURL(blob);
- const link = document.createElement("a");
- link.href = url;
- link.download = filename;
- link.click();
- window.URL.revokeObjectURL(url);
- })
- .catch((error) => {
- console.error("❌ 下载模板失败:", error);
- throw error;
- });
- };
|