import { StudentCheckItem } from "./types"; import { useAppStore } from "@/store"; import { randomCode } from "@/utils/tool"; import axios from "axios"; import Papa from "papaparse"; const appStore = useAppStore(); export const allCheckList = async ( params: AllCheckFilter ): Promise => { // if (!params.isCheck && !params.imageName) { // return Promise.resolve([]); // } const fname = params.isCheck ? "check" : "success"; const url = `${appStore.serverUrl}/${fname}.csv?${randomCode()}`; let students: StudentCheckItem[] = await fetchAndParseData(url); if (params.imageName) { students = students.filter((item) => item.imageName === params.imageName); } const cacheList = await fetchCacheList(); const data = (students || []).map((item) => { return { ...item, checked: cacheList.includes(item.imageName), }; }); return Promise.resolve(data); }; export const getExamNumberInfo = async ( imageName: string ): Promise => { const url = `${appStore.serverUrl}/cache/${imageName}.csv?${randomCode()}`; const students = await fetchAndParseData(url).catch(() => []); if (!students || students.length === 0) { return Promise.resolve(null); } const item = students[0]; const questions = (item.smda ? item.smda.split("|") : []).map((item) => item.trim().replace(/[\.\?]/g, "") ); return Promise.resolve({ ...students[0], questions }); }; export const fetchCacheList = async () => { try { const res = await axios.get(`${appStore.serverUrl}/cache/`); const parser = new DOMParser(); const doc = parser.parseFromString(res.data, "text/html"); const links = Array.from(doc.querySelectorAll("a")) .map((a) => a.getAttribute("href")) .filter((href) => href && /\/cache\/.*\.csv$/.test(href)) .map((href) => { // Extract filename without extension const parts = href.split("/"); const filenameWithExtension = parts[parts.length - 1]; return filenameWithExtension.replace(".csv", ""); }); // console.log("缓存文件列表:", links); return links; // Return the extracted list } catch (err) { console.error("获取失败:", err); } }; export const saveCheck = async (data: string[][], filename): Promise => { const url = `${appStore.serverUrl}/upload?path=/cache`; return uploadCsvData(url, data, filename); }; /** * 请求给定远程地址,获取文件流数据(CSV 或 JSON),并解析其内容。 * @param remoteUrl 远程文件地址 * @returns 解析后的数据 */ export const fetchAndParseData = async (remoteUrl: string): Promise => { try { const response = await axios.get(remoteUrl, { responseType: "text", // Fetch as text to handle both JSON and CSV }); const contentType = response.headers["content-type"]; let data; if (contentType && contentType.includes("application/json")) { // Try parsing as JSON try { data = JSON.parse(response.data); } catch (error) { console.error("Error parsing JSON:", error); throw new Error("Failed to parse JSON data"); } } else if (contentType && contentType.includes("text/csv")) { // Try parsing as CSV return new Promise((resolve, reject) => { Papa.parse(response.data, { header: true, // Assume header row skipEmptyLines: true, complete: (results) => { resolve(results.data); }, error: (error: any) => { console.error("Error parsing CSV:", error); reject(new Error("Failed to parse CSV data")); }, }); }); } else { // Attempt to guess format or throw error try { // Try JSON first data = JSON.parse(response.data); } catch (jsonError) { // If JSON fails, try CSV return new Promise((resolve, reject) => { Papa.parse(response.data, { header: true, skipEmptyLines: true, complete: (results) => { if (results.errors.length > 0) { console.error("CSV parsing errors:", results.errors); // If CSV parsing also has issues, reject reject( new Error( "Failed to parse data: Unknown format or invalid content" ) ); } else { resolve(results.data); } }, error: (csvError: any) => { console.error("Error parsing CSV:", csvError); reject( new Error( "Failed to parse data: Could not determine format or invalid content" ) ); }, }); }); } } return data; } catch (error) { console.error("Error fetching or parsing data:", error); throw new Error("Failed to fetch or parse data from the remote URL"); } }; /** * 构建 CSV 文件内容并上传到指定 URL。 * @param uploadUrl 上传的目标 URL * @param data 要转换为 CSV 并上传的数据数组 * @param filename 上传的文件名 * @returns 上传结果 */ export const uploadCsvData = async ( uploadUrl: string, data: string[][], filename: string = "upload.csv" ): Promise => { try { // Convert data array to CSV string const csvString = Papa.unparse(data); // Create a Blob from the CSV string const blob = new Blob([csvString], { type: "text/csv;charset=utf-8;" }); // Create FormData and append the Blob as a file const formData = new FormData(); formData.append("file", blob, filename); // 'file' is a common field name for uploads, adjust if needed // Upload the FormData using axios const response = await axios.post(uploadUrl, formData, { headers: { "Content-Type": "multipart/form-data", }, }); return response.data; // Return the response from the server } catch (error) { console.error("Error building or uploading CSV data:", error); throw new Error("Failed to build or upload CSV data"); } };