2 lines
9.9 KiB
JavaScript
2 lines
9.9 KiB
JavaScript
import { d as R, o as T, a, c as n, b as j, B as z, e as s, F as k, r as U, t as i, f as C, n as b, w as I, v as x, g as d, h as W, i as D, E as o, j as q, k as J, l as L, m as O, p as G, _ as Q, q as X, s as Y } from "./pywebview-BnpJyyGZ.js"; const Z = { class: "page-shell module-page" }, ee = { class: "main-content" }, se = { class: "left-panel" }, le = { class: "upload-zone" }, te = { class: "selected-files clean-placeholder" }, ae = { key: 0, class: "more-line" }, ne = { key: 1 }, oe = { class: "option-group column-option-group" }, re = { class: "column-toolbar" }, ie = { class: "column-count" }, ue = { key: 0, class: "column-grid" }, ce = ["value"], de = { key: 1, class: "empty-column-state" }, ve = { class: "option-group" }, pe = { class: "run-row" }, fe = ["disabled"], _e = { class: "loading-msg" }, me = { class: "right-panel" }, ge = { class: "task-list-wrap" }, ye = { class: "clean-result-summary" }, he = { class: "summary-card" }, be = { class: "summary-card" }, we = { class: "summary-card" }, ke = { class: "result-list-wrap" }, Ce = { key: 0, class: "empty-tasks" }, Ie = { key: 1, class: "task-list clean-result-list" }, xe = { class: "left" }, De = ["title"], Ee = { key: 0, class: "files" }, Fe = { key: 1, class: "files" }, Ue = { class: "task-right" }, Se = ["onClick"], Be = ["onClick"], $e = R({ __name: "BrandDedupeTab", setup(Ve) { const v = d([]), c = d([]), p = d([]), f = d([]), _ = d(!1), m = d(!0), g = d(!0), y = d(!1), w = d([]), h = d({ total: 0, successCount: 0, failedCount: 0, items: [] }), E = W(() => p.value.slice(0, 8)); function B() { c.value = [...v.value] } function $() { c.value = [] } async function H(t) { const e = D(); if (!e?.upload_file_to_java) throw new Error("当前桌面端未提供文件上传桥接能力"); const l = []; for (const r of t) { const u = await e.upload_file_to_java(r); if (!u?.success || !u.data) throw new Error(u?.error || u?.message || `上传失败:${r}`); l.push(u.data) } return l } async function V(t) { const e = await G(t); if (!e.headers?.length) { o.error("读取 Excel 表头失败"), v.value = [], c.value = []; return } const l = ["id", "ASIN", "国家", "价格", "卖家名称"], r = [...l.filter(u => e.headers?.includes(u)), ...(e.headers || []).filter(u => !l.includes(u))]; v.value = r, c.value = l.filter(u => r.includes(u)) } async function S(t, e) { p.value = t, f.value = await H(t), f.value.length > 0 && await V(f.value[0].fileKey), o.success(e) } async function A() { const t = D(); if (!t?.select_brand_xlsx_files) { o.warning("当前环境不支持文件选择,请在本机客户端中打开"); return } try { const e = await t.select_brand_xlsx_files(); if (!e?.length) return; await S(e, `已选择 ${e.length} 个待清洗文件`) } catch (e) { o.error(e instanceof Error ? e.message : "选择失败") } } async function K() { const t = D(); if (!t?.select_brand_folder) { o.warning("当前环境不支持文件夹选择,请在本机客户端中打开"); return } try { const e = await t.select_brand_folder(); if (!e) return; const l = await q(e); if (l.success && l.paths?.length) { await S(l.paths, `已选择文件夹内 ${l.paths.length} 个 xlsx 文件`); return } o.warning(l.error || "该文件夹下没有 xlsx 文件") } catch (e) { o.error(e instanceof Error ? e.message : "选择失败") } } async function N() { if (!f.value.length) { o.warning("请先选择待清洗 Excel 文件或文件夹"); return } if (!c.value.length) { o.warning("请至少选择一列保留列"); return } if (!_.value && !m.value && !g.value) { o.warning("请至少选择一种 ID 保留规则"); return } try { y.value = !0; const t = await J({ files: f.value.map(e => ({ fileKey: e.fileKey, originalFilename: e.originalFilename })), selectedColumns: c.value, keepIntegerIds: _.value, keepUnderscoreIds: m.value, keepIntegerMainIdsWhenNoSubIds: g.value }); h.value = t, w.value = t.items || [], await F(), o.success("数据去重完成") } catch (t) { o.error(t instanceof Error ? t.message : "去重失败") } finally { y.value = !1 } } async function F() { try { const t = await L(); w.value = t.items || [], h.value = { total: t.items?.length || 0, successCount: t.items?.filter(e => e.success).length || 0, failedCount: t.items?.filter(e => !e.success).length || 0, items: t.items || [] } } catch { } } async function M(t) { try { await O(t), await F(), o.success("已删除") } catch (e) { o.error(e instanceof Error ? e.message : "删除失败") } } async function P(t) { const e = D(); if (!t.downloadUrl) { o.warning("当前结果没有下载地址"); return } const l = t.outputFilename || `${new Date().toISOString().slice(0, 10).replace(/-/g, "")}_cleaned.xlsx`; if (e?.save_file_from_url) { const r = await e.save_file_from_url(t.downloadUrl, l); r.success ? o.success(`已保存:${r.path || l}`) : r.error && r.error !== "用户取消" && o.error(r.error); return } window.open(t.downloadUrl, "_blank") } return T(() => { F().catch(() => { }) }), (t, e) => (a(), n("div", Z, [j(z, { active: "dedupe" }), s("div", ee, [s("aside", se, [e[9] || (e[9] = s("div", { class: "section-title" }, "选择文件", -1)), s("div", le, [e[4] || (e[4] = s("div", { class: "hint" }, "选择需要清洗的 Excel 文件或文件夹,后续将按所选规则输出处理结果。", -1)), s("div", { class: "btns" }, [s("button", { type: "button", class: "opt-btn", onClick: A }, "选择 Excel 文件"), s("button", { type: "button", class: "opt-btn", onClick: K }, "选择文件夹")]), s("div", te, [p.value.length ? (a(), n(k, { key: 0 }, [(a(!0), n(k, null, U(E.value, l => (a(), n("span", { key: l }, i(l), 1))), 128)), p.value.length > E.value.length ? (a(), n("span", ae, " 还有 " + i(p.value.length - E.value.length) + " 个文件未展开显示 ", 1)) : C("", !0)], 64)) : (a(), n("span", ne, "暂未选择待清洗文件"))])]), e[10] || (e[10] = s("div", { class: "section-title" }, "保留列设置", -1)), s("div", oe, [s("div", re, [s("span", ie, "已选择 " + i(c.value.length) + " / " + i(v.value.length) + " 列", 1), s("div", { class: "column-actions" }, [s("button", { type: "button", class: "opt-btn small", onClick: B }, "全选"), s("button", { type: "button", class: "opt-btn small", onClick: $ }, "清空")])]), v.value.length ? (a(), n("div", ue, [(a(!0), n(k, null, U(v.value, l => (a(), n("label", { key: l, class: b(["column-item", { active: c.value.includes(l) }]) }, [I(s("input", { "onUpdate:modelValue": e[0] || (e[0] = r => c.value = r), type: "checkbox", value: l }, null, 8, ce), [[x, c.value]]), s("span", null, i(l), 1)], 2))), 128))])) : (a(), n("div", de, "请选择 Excel 文件后读取表头并填充可保留列")), e[5] || (e[5] = s("div", { class: "desc" }, "读取首个 Excel 文件的第一行作为表头,用于动态选择需要保留的列。", -1))]), e[11] || (e[11] = s("div", { class: "section-title" }, "ID 保留规则", -1)), s("div", ve, [s("label", { class: b(["radio-item", { active: _.value }]) }, [I(s("input", { "onUpdate:modelValue": e[1] || (e[1] = l => _.value = l), type: "checkbox" }, null, 512), [[x, _.value]]), e[6] || (e[6] = s("div", null, [s("span", { class: "label" }, "保留主链接"), s("div", { class: "desc" }, "例如 1、2、3 这种纯数字 ID")], -1))], 2), s("label", { class: b(["radio-item", { active: m.value }]) }, [I(s("input", { "onUpdate:modelValue": e[2] || (e[2] = l => m.value = l), type: "checkbox" }, null, 512), [[x, m.value]]), e[7] || (e[7] = s("div", null, [s("span", { class: "label" }, "保留子链接"), s("div", { class: "desc" }, "例如 1_1、2_3 这种带下划线的子项 ID")], -1))], 2), s("label", { class: b(["radio-item", { active: g.value }]) }, [I(s("input", { "onUpdate:modelValue": e[3] || (e[3] = l => g.value = l), type: "checkbox" }, null, 512), [[x, g.value]]), e[8] || (e[8] = s("div", null, [s("span", { class: "label" }, "仅剩主链接无子链接"), s("div", { class: "desc" }, "当某个主链接只有 13 这类主 ID、没有 13_1 这类对应子 ID 时,自动保留该主 ID")], -1))], 2)]), s("div", pe, [s("button", { type: "button", class: "btn-run", disabled: y.value, onClick: N }, i(y.value ? "清洗中..." : "开始清洗"), 9, fe), s("span", _e, i(y.value ? "正在处理文件并上传结果,请稍候…" : "选择文件、列和 ID 规则后即可执行清洗,结果会显示在右侧供下载"), 1)])]), s("section", me, [e[16] || (e[16] = s("div", { class: "panel-header" }, "去重结果", -1)), s("div", ge, [s("div", ye, [s("div", he, [e[12] || (e[12] = s("span", { class: "summary-label" }, "已处理文件", -1)), s("strong", null, i(h.value.total), 1)]), s("div", be, [e[13] || (e[13] = s("span", { class: "summary-label" }, "成功结果", -1)), s("strong", null, i(h.value.successCount), 1)]), s("div", we, [e[14] || (e[14] = s("span", { class: "summary-label" }, "失败文件", -1)), s("strong", null, i(h.value.failedCount), 1)])]), s("div", ke, [e[15] || (e[15] = s("div", { class: "result-list-header" }, [s("span", null, "处理后的 Excel 列表")], -1)), w.value.length === 0 ? (a(), n("div", Ce, " 暂无去重结果,完成数据去重后会在这里展示输出文件 ")) : (a(), n("ul", Ie, [(a(!0), n(k, null, U(w.value, l => (a(), n("li", { key: `${l.resultId || l.outputFilename || l.sourceFilename}`, class: "task-item" }, [s("div", xe, [s("span", { class: "id", title: l.sourceFilename }, i(l.sourceFilename || "-"), 9, De), l.outputFilename ? (a(), n("div", Ee, "输出文件:" + i(l.outputFilename), 1)) : l.error ? (a(), n("div", Fe, "错误信息:" + i(l.error), 1)) : C("", !0)]), s("div", Ue, [s("span", { class: b(["status", l.success ? "success" : "failed"]) }, i(l.success ? "已完成" : "失败"), 3), l.success && l.downloadUrl ? (a(), n("button", { key: 0, type: "button", class: "download", onClick: r => P(l) }, " 下载文件 ", 8, Se)) : C("", !0), l.resultId ? (a(), n("button", { key: 1, type: "button", class: "btn-delete", onClick: r => M(l.resultId) }, " 删除 ", 8, Be)) : C("", !0)])]))), 128))]))])])])])])) } }), He = Q($e, [["__scopeId", "data-v-0ae0e1da"]]); X(He).use(Y).mount("#app");
|