123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- import { StudentCheckItem, AllCheckFilter } 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<StudentCheckItem[]> => {
- // if (!params.isCheck && !params.imageName) {
- // return Promise.resolve([]);
- // }
- const fname = params.isCheck ? `check-${params.menuKey}` : "success";
- const url = `${appStore.serverUrl}/${fname}.csv?${randomCode()}`;
- let students: StudentCheckItem[] = await fetchAndParseData(url).catch(
- () => []
- );
- if (params.imageName) {
- students = students.filter((item) => item.imageName === params.imageName);
- }
- // console.log(students);
- const cacheList = await fetchCacheList();
- const data = (students || []).map((item) => {
- return {
- ...item,
- checked: cacheList.includes(item.imageName),
- };
- });
- // console.log(data);
- return Promise.resolve(data);
- };
- export const getExamNumberInfo = async (
- imageName: string
- ): Promise<DataCheckListResult> => {
- 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) {
- return [];
- console.error("获取失败:", err);
- }
- };
- export const saveCheck = async (data: string[][], filename): Promise<any> => {
- const url = `${appStore.serverUrl}/upload?path=/cache`;
- return uploadCsvData(url, data, filename);
- };
- /**
- * 请求给定远程地址,获取文件流数据(CSV 或 JSON),并解析其内容。
- * @param remoteUrl 远程文件地址
- * @returns 解析后的数据
- */
- export const fetchAndParseData = async (remoteUrl: string): Promise<any> => {
- 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<any> => {
- try {
- // Convert data array to CSV string
- const csvString = Papa.unparse(data);
- // Send data to main process for upload
- // Assuming 'window.electron.ipcRenderer.invoke' is available for IPC
- // The channel name 'upload-csv' is an example; it should match the handler in the main process.
- const result = await window.electronApi.uploadCsvData({
- uploadUrl,
- csvString,
- filename,
- });
- if (!result.error) return result.data;
- throw new Error(result.message || "Failed to send CSV data for upload");
- } catch (error) {
- console.error("Error preparing or sending CSV data for upload:", error);
- // It's good practice to re-throw or handle the error appropriately
- // For instance, if the error is already an Error object with a message, just re-throw it
- if (error instanceof Error) {
- throw error;
- }
- throw new Error("Failed to prepare or send CSV data for upload");
- }
- };
|