This commit is contained in:
zlwu committed 2026-07-02 12:25:00 +08:00
1 parent 038a60b09e
commit 3740a7dd80
45 files changed
+10945 -6192

No files matched your search

@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "label": "DonationFormDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1"}, {"id": "list_donationformdialog_createemptytransport", "label": "createEmptyTransport()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L804"}, {"id": "list_donationformdialog_fullfileurl", "label": "fullFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L822"}, {"id": "list_donationformdialog_loadethnicoptions", "label": "loadEthnicOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L829"}, {"id": "list_donationformdialog_ensureethnicoptioninlist", "label": "ensureEthnicOptionInList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L840"}, {"id": "list_donationformdialog_resetform", "label": "resetForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L941"}, {"id": "list_donationformdialog_scrolltosection", "label": "scrollToSection()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1000"}, {"id": "list_donationformdialog_normalizesamplerow", "label": "normalizeSampleRow()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1008"}, {"id": "list_donationformdialog_handleopenforadd", "label": "handleOpenForAdd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1032"}, {"id": "list_donationformdialog_applydonationbundletoform", "label": "applyDonationBundleToForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1079"}, {"id": "list_donationformdialog_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L2207"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_sample_transport_form_section_index_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L695", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L696", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L697", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_research_donation", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L708", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_business", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L714", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_composables_useattachmentdropzone", "relation": "imports_from", "cLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict_ts", "label": "void-type-dict.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L1"}, {"id": "utils_void_type_dict_buildfallbackoptions", "label": "buildFallbackOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L12"}, {"id": "utils_void_type_dict_getvoidtypeoptions", "label": "getVoidTypeOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L23"}, {"id": "utils_void_type_dict_loadvoidtypedict", "label": "loadVoidTypeDict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L27"}, {"id": "utils_void_type_dict_resolvevoidtypelabel", "label": "resolveVoidTypeLabel()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L50"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict_ts", "target": "vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict_ts", "target": "utils_void_type_dict_buildfallbackoptions", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict_ts", "target": "utils_void_type_dict_getvoidtypeoptions", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L23", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict_ts", "target": "utils_void_type_dict_loadvoidtypedict", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L27", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict_ts", "target": "utils_void_type_dict_resolvevoidtypelabel", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L50", "weight": 1.0}], "raw_calls": [{"caller_nid": "utils_void_type_dict_buildfallbackoptions", "callee": "map", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L13"}, {"caller_nid": "utils_void_type_dict_buildfallbackoptions", "callee": "entries", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L13"}, {"caller_nid": "utils_void_type_dict_loadvoidtypedict", "callee": "(async () => {\n try {\n const res = await fetchDictDataOptions(VOID_TYPE_DICT)\n voidTypeOptionsRef.value = res?.length ? res : buildFallbackOptions()\n labelMap = {\n ...FALLBACK_LABELS,\n ...Object.fromEntries(voidTypeOptionsRef.value.map((o) => [o.value, o.label]))\n }\n dictLoaded = true\n } catch (e) {\n console.error('\u52a0\u8f7d\u4f5c\u5e9f\u7c7b\u578b\u5b57\u5178\u5931\u8d25:', e)\n voidTypeOptionsRef.value = buildFallbackOptions()\n labelMap = { ...FALLBACK_LABELS }\n } finally {\n loadPromise = null\n }\n })", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L30"}, {"caller_nid": "utils_void_type_dict_resolvevoidtypelabel", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L51"}, {"caller_nid": "utils_void_type_dict_resolvevoidtypelabel", "callee": "String", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/void-type-dict.ts", "source_location": "L51"}]}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chinese_datetime_parse_ts", "label": "chinese-datetime-parse.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L1"}, {"id": "utils_chinese_datetime_parse_formatdatetimetominute", "label": "formatDatetimeToMinute()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L7"}, {"id": "utils_chinese_datetime_parse_parsechinesedatetimetext", "label": "parseChineseDatetimeText()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L14"}, {"id": "utils_chinese_datetime_parse_handlechinesedatetimepaste", "label": "handleChineseDatetimePaste()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L61"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chinese_datetime_parse_ts", "target": "utils_chinese_datetime_parse_formatdatetimetominute", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chinese_datetime_parse_ts", "target": "utils_chinese_datetime_parse_parsechinesedatetimetext", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L14", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chinese_datetime_parse_ts", "target": "utils_chinese_datetime_parse_handlechinesedatetimepaste", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L61", "weight": 1.0}, {"source": "utils_chinese_datetime_parse_formatdatetimetominute", "target": "utils_chinese_datetime_parse_parsechinesedatetimetext", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L10", "weight": 1.0}, {"source": "utils_chinese_datetime_parse_handlechinesedatetimepaste", "target": "utils_chinese_datetime_parse_parsechinesedatetimetext", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L68", "weight": 1.0}], "raw_calls": [{"caller_nid": "utils_chinese_datetime_parse_formatdatetimetominute", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L8"}, {"caller_nid": "utils_chinese_datetime_parse_formatdatetimetominute", "callee": "String", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L8"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L18"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "test", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L21"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "test", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L25"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "replace", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L26"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "slice", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L27"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "split", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L28"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "split", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L30"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "padStart", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-datetime-parse.ts", "source_location": "L31"}, {"caller_nid": "utils_chinese_datetime_parse_parsechinesedatetimetext", "callee": "padStart", "source_file": "/UsLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "label": "DonationFormDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1"}, {"id": "list_donationformdialog_createemptytransport", "label": "createEmptyTransport()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L804"}, {"id": "list_donationformdialog_fullfileurl", "label": "fullFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L822"}, {"id": "list_donationformdialog_loadethnicoptions", "label": "loadEthnicOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L829"}, {"id": "list_donationformdialog_ensureethnicoptioninlist", "label": "ensureEthnicOptionInList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L840"}, {"id": "list_donationformdialog_resetform", "label": "resetForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L941"}, {"id": "list_donationformdialog_scrolltosection", "label": "scrollToSection()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1000"}, {"id": "list_donationformdialog_normalizesamplerow", "label": "normalizeSampleRow()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1008"}, {"id": "list_donationformdialog_handleopenforadd", "label": "handleOpenForAdd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1032"}, {"id": "list_donationformdialog_applydonationbundletoform", "label": "applyDonationBundleToForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1079"}, {"id": "list_donationformdialog_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L2187"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_sample_transport_form_section_index_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L695", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L696", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L697", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_research_donation", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L708", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_business", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L714", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_composables_useattachmentdropzone", "relation": "imports_from", "cLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_donation_standard_import_parse_ts", "label": "donation-standard-import-parse.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L1"}, {"id": "utils_donation_standard_import_parse_normalizeline", "label": "normalizeLine()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L66"}, {"id": "utils_donation_standard_import_parse_splitkeyvalue", "label": "splitKeyValue()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L72"}, {"id": "utils_donation_standard_import_parse_resolvesamplecollecthint", "label": "resolveSampleCollectHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L78"}, {"id": "utils_donation_standard_import_parse_parsesex", "label": "parseSex()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L89"}, {"id": "utils_donation_standard_import_parse_parsedeliverymode", "label": "parseDeliveryMode()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L97"}, {"id": "utils_donation_standard_import_parse_parseweightgram", "label": "parseWeightGram()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L105"}, {"id": "utils_donation_standard_import_parse_parsescore", "label": "parseScore()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L114"}, {"id": "utils_donation_standard_import_parse_parsedatetime", "label": "parseDatetime()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L123"}, {"id": "utils_donation_standard_import_parse_ismaternalbloodempty", "label": "isMaternalBloodEmpty()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L134"}, {"id": "utils_donation_standard_import_parse_resolvetransporttype", "label": "resolveTransportType()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L141"}, {"id": "utils_donation_standard_import_parse_addsamplehint", "label": "addSampleHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L149"}, {"id": "utils_donation_standard_import_parse_earliestcollecttime", "label": "earliestCollectTime()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L158"}, {"id": "utils_donation_standard_import_parse_parsedonationstandardimporttext", "label": "parseDonationStandardImportText()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L166"}, {"id": "utils_donation_standard_import_parse_matchsampletypebyexactname", "label": "matchSampleTypeByExactName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L270"}, {"id": "utils_donation_standard_import_parse_matchcellsampletype", "label": "matchCellSampleType()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L289"}, {"id": "utils_donation_standard_import_parse_matchexpresscompany", "label": "matchExpressCompany()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L320"}, {"id": "utils_donation_standard_import_parse_isblankstring", "label": "isBlankString()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L342"}, {"id": "utils_donation_standard_import_parse_isemptynumber", "label": "isEmptyNumber()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L346"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_donation_standard_import_parse_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chineseLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_donation_standard_import_parse_ts", "label": "donation-standard-import-parse.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L1"}, {"id": "utils_donation_standard_import_parse_normalizeline", "label": "normalizeLine()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L66"}, {"id": "utils_donation_standard_import_parse_splitkeyvalue", "label": "splitKeyValue()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L72"}, {"id": "utils_donation_standard_import_parse_resolvesamplecollecthint", "label": "resolveSampleCollectHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L78"}, {"id": "utils_donation_standard_import_parse_parsesex", "label": "parseSex()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L89"}, {"id": "utils_donation_standard_import_parse_parsedeliverymode", "label": "parseDeliveryMode()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L97"}, {"id": "utils_donation_standard_import_parse_parseweightgram", "label": "parseWeightGram()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L105"}, {"id": "utils_donation_standard_import_parse_parsescore", "label": "parseScore()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L114"}, {"id": "utils_donation_standard_import_parse_parsedatetime", "label": "parseDatetime()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L123"}, {"id": "utils_donation_standard_import_parse_ismaternalbloodempty", "label": "isMaternalBloodEmpty()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L134"}, {"id": "utils_donation_standard_import_parse_resolvetransporttype", "label": "resolveTransportType()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L141"}, {"id": "utils_donation_standard_import_parse_addsamplehint", "label": "addSampleHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L151"}, {"id": "utils_donation_standard_import_parse_earliestcollecttime", "label": "earliestCollectTime()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L160"}, {"id": "utils_donation_standard_import_parse_parsedonationstandardimporttext", "label": "parseDonationStandardImportText()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L168"}, {"id": "utils_donation_standard_import_parse_matchsampletypebyexactname", "label": "matchSampleTypeByExactName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L272"}, {"id": "utils_donation_standard_import_parse_matchcellsampletype", "label": "matchCellSampleType()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L291"}, {"id": "utils_donation_standard_import_parse_matchexpresscompany", "label": "matchExpressCompany()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L322"}, {"id": "utils_donation_standard_import_parse_isblankstring", "label": "isBlankString()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L344"}, {"id": "utils_donation_standard_import_parse_isemptynumber", "label": "isEmptyNumber()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L348"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_donation_standard_import_parse_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chineseLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_material_index_vue", "label": "index.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1"}, {"id": "material_index_defaultoperatorname", "label": "defaultOperatorName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1307"}, {"id": "material_index_ensureoperatoroption", "label": "ensureOperatorOption()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1312"}, {"id": "material_index_initoperatorfield", "label": "initOperatorField()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1323"}, {"id": "material_index_ensuretabmounted", "label": "ensureTabMounted()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1340"}, {"id": "material_index_handletabchange", "label": "handleTabChange()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1345"}, {"id": "material_index_loaddictoptions", "label": "loadDictOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1818"}, {"id": "material_index_loaddata", "label": "loadData()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1827"}, {"id": "material_index_handlesearch", "label": "handleSearch()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1844"}, {"id": "material_index_handlereset", "label": "handleReset()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1849"}, {"id": "material_index_oneditpriceqtychange", "label": "onEditPriceQtyChange()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1857"}, {"id": "material_index_handleedit", "label": "handleEdit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1862"}, {"id": "material_index_handlesubmit", "label": "handleSubmit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1889"}, {"id": "material_index_handleview", "label": "handleView()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1922"}, {"id": "material_index_handledelete", "label": "handleDelete()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1943"}, {"id": "material_index_formattodaydate", "label": "formatTodayDate()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1962"}, {"id": "material_index_onstockinmaterialkeychange", "label": "onStockInMaterialKeyChange()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1968"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_material_index_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1263", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_material_index_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1264", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_material_index_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_system_view_dialog_index_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/material/index.vue", "source_location": "L1278", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storaLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chinese_numeral_parse_ts", "label": "chinese-numeral-parse.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L1"}, {"id": "utils_chinese_numeral_parse_parsechinesenumeral", "label": "parseChineseNumeral()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L19"}, {"id": "utils_chinese_numeral_parse_parsebirthorder", "label": "parseBirthOrder()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L55"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chinese_numeral_parse_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_numeric_input_parse", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chinese_numeral_parse_ts", "target": "utils_chinese_numeral_parse_parsechinesenumeral", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L19", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chinese_numeral_parse_ts", "target": "utils_chinese_numeral_parse_parsebirthorder", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L55", "weight": 1.0}, {"source": "utils_chinese_numeral_parse_parsebirthorder", "target": "utils_chinese_numeral_parse_parsechinesenumeral", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L67", "weight": 1.0}], "raw_calls": [{"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L20"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "test", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L23"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "Number", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L24"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "isFinite", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L25"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "startsWith", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L32"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "slice", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L33"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "endsWith", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L39"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "slice", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L40"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "indexOf", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L44"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "slice", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L46"}, {"caller_nid": "utils_chinese_numeral_parse_parsechinesenumeral", "callee": "slice", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L47"}, {"caller_nid": "utils_chinese_numeral_parse_parsebirthorder", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L56"}, {"caller_nid": "utils_chinese_numeral_parse_parsebirthorder", "callee": "extractNumericPart", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-numeral-parse.ts", "source_location": "L59"}, {"caller_nid": "utils_chinese_numeral_parse_parsebirthorder", "callee": "Number", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/chinese-nLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_standard_import_parse_ts", "label": "protocol-standard-import-parse.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L1"}, {"id": "utils_protocol_standard_import_parse_normalizeline", "label": "normalizeLine()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L84"}, {"id": "utils_protocol_standard_import_parse_splitkeyvalue", "label": "splitKeyValue()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L90"}, {"id": "utils_protocol_standard_import_parse_normalizechinesedatetimeliteral", "label": "normalizeChineseDatetimeLiteral()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L96"}, {"id": "utils_protocol_standard_import_parse_parsedatetime", "label": "parseDatetime()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L105"}, {"id": "utils_protocol_standard_import_parse_parsesex", "label": "parseSex()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L116"}, {"id": "utils_protocol_standard_import_parse_parsedeliverymode", "label": "parseDeliveryMode()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L124"}, {"id": "utils_protocol_standard_import_parse_parsemoney", "label": "parseMoney()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L132"}, {"id": "utils_protocol_standard_import_parse_parsescore", "label": "parseScore()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L139"}, {"id": "utils_protocol_standard_import_parse_ismaternalbloodempty", "label": "isMaternalBloodEmpty()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L143"}, {"id": "utils_protocol_standard_import_parse_resolvesamplecollecthint", "label": "resolveSampleCollectHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L149"}, {"id": "utils_protocol_standard_import_parse_resolvesamplecodehint", "label": "resolveSampleCodeHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L160"}, {"id": "utils_protocol_standard_import_parse_upsertsamplehint", "label": "upsertSampleHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L176"}, {"id": "utils_protocol_standard_import_parse_earliestcollecttime", "label": "earliestCollectTime()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L189"}, {"id": "utils_protocol_standard_import_parse_parsepaymodefromtext", "label": "parsePayModeFromText()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L196"}, {"id": "utils_protocol_standard_import_parse_parsepaymenttransfersegments", "label": "parsePaymentTransferSegments()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L209"}, {"id": "utils_protocol_standard_import_parse_resolvetransfertypecode", "label": "resolveTransferTypeCode()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L258"}, {"id": "utils_protocol_standard_import_parse_extractcarriernamefromtransport", "label": "extractCarrierNameFromTransport()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L287"}, {"id": "utils_protocol_standard_import_parse_parseprotocolstandardimporttext", "label": "parseProtocolStandardImportText()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-standard-import-parse.ts", "source_location": "L294"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_standard_imLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "label": "DonationFormDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1"}, {"id": "list_donationformdialog_createemptytransport", "label": "createEmptyTransport()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L804"}, {"id": "list_donationformdialog_fullfileurl", "label": "fullFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L822"}, {"id": "list_donationformdialog_loadethnicoptions", "label": "loadEthnicOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L829"}, {"id": "list_donationformdialog_ensureethnicoptioninlist", "label": "ensureEthnicOptionInList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L840"}, {"id": "list_donationformdialog_resetform", "label": "resetForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L941"}, {"id": "list_donationformdialog_scrolltosection", "label": "scrollToSection()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1000"}, {"id": "list_donationformdialog_normalizesamplerow", "label": "normalizeSampleRow()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1008"}, {"id": "list_donationformdialog_handleopenforadd", "label": "handleOpenForAdd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1032"}, {"id": "list_donationformdialog_applydonationbundletoform", "label": "applyDonationBundleToForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L1079"}, {"id": "list_donationformdialog_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L2248"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_components_business_sample_transport_form_section_index_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L695", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L696", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L697", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_research_donation", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L708", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_business", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue", "source_location": "L714", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_composables_useattachmentdropzone", "relation": "imports_from", "cLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "label": "DonationStatusChangeDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L1"}, {"id": "list_donationstatuschangedialog_resetform", "label": "resetForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L186"}, {"id": "list_donationstatuschangedialog_handlesubmit", "label": "handleSubmit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L193"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L79", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L80", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_research_donation", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L81", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_fullscreen_loading", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L82", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_doc_label", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L83", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L84", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "target": "list_donationstatuschangedialog_resetform", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L186", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_research_donation_list_donationstatuschangedialog_vue", "target": "list_donationstatuschangedialog_handlesubmit", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L193", "weight": 1.0}], "raw_calls": [{"caller_nid": "list_donationstatuschangedialog_resetform", "callee": "clearValidate", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L190"}, {"caller_nid": "list_donationstatuschangedialog_handlesubmit", "callee": "catch", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L194"}, {"caller_nid": "list_donationstatuschangedialog_handlesubmit", "callee": "validate", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue", "source_location": "L194"}, {"caller_nid": "list_donationstatuschangedialog_handlesubmit", "callee": "confirm", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusCLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "label": "ProtocolFormDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1"}, {"id": "protocol_protocolformdialog_ensuretransfertypeoptions", "label": "ensureTransferTypeOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1006"}, {"id": "protocol_protocolformdialog_fmtmoney", "label": "fmtMoney()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1012"}, {"id": "protocol_protocolformdialog_createemptytransport", "label": "createEmptyTransport()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1089"}, {"id": "protocol_protocolformdialog_fullfileurl", "label": "fullFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1107"}, {"id": "protocol_protocolformdialog_loadethnicoptions", "label": "loadEthnicOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1114"}, {"id": "protocol_protocolformdialog_ensureethnicoptioninlist", "label": "ensureEthnicOptionInList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1125"}, {"id": "protocol_protocolformdialog_initpaymentdetailexpandflags", "label": "initPaymentDetailExpandFlags()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1156"}, {"id": "protocol_protocolformdialog_paymentdetailsummary", "label": "paymentDetailSummary()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1162"}, {"id": "protocol_protocolformdialog_togglepaymentdetailexpand", "label": "togglePaymentDetailExpand()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1189"}, {"id": "protocol_protocolformdialog_resetform", "label": "resetForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1282"}, {"id": "protocol_protocolformdialog_scrolltosection", "label": "scrollToSection()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1358"}, {"id": "protocol_protocolformdialog_normalizesamplerow", "label": "normalizeSampleRow()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1366"}, {"id": "protocol_protocolformdialog_addpaymentdetail", "label": "addPaymentDetail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1389"}, {"id": "protocol_protocolformdialog_defaultinstallmentstartdateymd", "label": "defaultInstallmentStartDateYmd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1419"}, {"id": "protocol_protocolformdialog_datetimetoymd", "label": "datetimeToYmd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1429"}, {"id": "protocol_protocolformdialog_isfqnumericfieldempty", "label": "isFqNumericFieldEmpty()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1437"}, {"id": "protocol_protocolformdialog_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1886"}, {"id": "protocol_protocolformdialog_for", "label": "for()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1897"}, {"id": "protocol_protocolformdialog_pad", "label": "pad()", "file_type": "code", "source_file": "/Users/wuzilong/Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_donation_standard_import_parse_ts", "label": "donation-standard-import-parse.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L1"}, {"id": "utils_donation_standard_import_parse_normalizeline", "label": "normalizeLine()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L66"}, {"id": "utils_donation_standard_import_parse_splitkeyvalue", "label": "splitKeyValue()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L72"}, {"id": "utils_donation_standard_import_parse_resolvesamplecollecthint", "label": "resolveSampleCollectHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L78"}, {"id": "utils_donation_standard_import_parse_parsesex", "label": "parseSex()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L89"}, {"id": "utils_donation_standard_import_parse_parsedeliverymode", "label": "parseDeliveryMode()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L97"}, {"id": "utils_donation_standard_import_parse_parseweightgram", "label": "parseWeightGram()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L105"}, {"id": "utils_donation_standard_import_parse_parsescore", "label": "parseScore()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L114"}, {"id": "utils_donation_standard_import_parse_parsedatetime", "label": "parseDatetime()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L123"}, {"id": "utils_donation_standard_import_parse_ismaternalbloodempty", "label": "isMaternalBloodEmpty()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L134"}, {"id": "utils_donation_standard_import_parse_resolvetransporttype", "label": "resolveTransportType()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L141"}, {"id": "utils_donation_standard_import_parse_addsamplehint", "label": "addSampleHint()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L150"}, {"id": "utils_donation_standard_import_parse_earliestcollecttime", "label": "earliestCollectTime()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L159"}, {"id": "utils_donation_standard_import_parse_parsedonationstandardimporttext", "label": "parseDonationStandardImportText()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L167"}, {"id": "utils_donation_standard_import_parse_matchsampletypebyexactname", "label": "matchSampleTypeByExactName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L271"}, {"id": "utils_donation_standard_import_parse_matchcellsampletype", "label": "matchCellSampleType()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L290"}, {"id": "utils_donation_standard_import_parse_matchexpresscompany", "label": "matchExpressCompany()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L321"}, {"id": "utils_donation_standard_import_parse_isblankstring", "label": "isBlankString()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L343"}, {"id": "utils_donation_standard_import_parse_isemptynumber", "label": "isEmptyNumber()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/donation-standard-import-parse.ts", "source_location": "L347"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_donation_standard_import_parse_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_chineseLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "label": "ProtocolStatusChangeDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L1"}, {"id": "protocol_protocolstatuschangedialog_resetform", "label": "resetForm()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L186"}, {"id": "protocol_protocolstatuschangedialog_handlesubmit", "label": "handleSubmit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L193"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L79", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L80", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_collection_protocol", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L81", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_research_donation", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L82", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_fullscreen_loading", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L83", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_doc_label", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L84", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_void_type_dict", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L85", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "protocol_protocolstatuschangedialog_resetform", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L186", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolstatuschangedialog_vue", "target": "protocol_protocolstatuschangedialog_handlesubmit", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L193", "weight": 1.0}], "raw_calls": [{"caller_nid": "protocol_protocolstatuschangedialog_resetform", "callee": "clearValidate", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L190"}, {"caller_nid": "protocol_protocolstatuschangedialog_handlesubmit", "callee": "catch", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue", "source_location": "L194"}, {"caLine truncated
@@ -38,7 +38,7 @@ export function parseChineseDatetimeText(
}
const cnMatch = raw.match(
/^(\d{4})年(\d{1,2})月(\d{1,2})日(?:\s*(\d{1,2})[时::](\d{1,2})(?:[分::](\d{1,2})[秒]?)?)?/
/^(\d{4})年(\d{1,2})月(\d{1,2})日(?:\s*(\d{1,2})[时点::](\d{1,2})(?:[分::](\d{1,2})[秒]?)?)?/
)
if (!cnMatch) return null
@@ -0,0 +1,77 @@
import { extractNumericPart } from '@/utils/numeric-input-parse'
const CN_DIGIT: Record<string, number> = {
零: 0,
一: 1,
二: 2,
两: 2,
三: 3,
四: 4,
五: 5,
六: 6,
七: 7,
八: 8,
九: 9,
十: 10
}
/** 解析简单中文数字(一~十、十一等),无法解析返回 null */
export function parseChineseNumeral(text: string): number | null {
const v = (text || '').trim()
if (!v) return null
if (/^\d+$/.test(v)) {
const n = Number(v)
return Number.isFinite(n) ? n : null
}
if (v.length === 1 && CN_DIGIT[v] != null) {
return CN_DIGIT[v]
}
if (v.startsWith('十')) {
const rest = v.slice(1)
if (!rest) return 10
const tail = CN_DIGIT[rest]
return tail != null ? 10 + tail : null
}
if (v.endsWith('十')) {
const head = CN_DIGIT[v.slice(0, 1)]
return head != null ? head * 10 : null
}
const shiIdx = v.indexOf('十')
if (shiIdx > 0) {
const head = CN_DIGIT[v.slice(0, shiIdx)]
const tail = CN_DIGIT[v.slice(shiIdx + 1)] ?? 0
if (head != null) return head * 10 + tail
}
return null
}
/** 解析胎次:阿拉伯数字、中文数字、「N胎」 */
export function parseBirthOrder(value: string): number | null | undefined {
const v = (value || '').trim()
if (!v) return undefined
if (/头胎|第一胎/.test(v)) return 1
const num = extractNumericPart(v)
if (num != null && num !== '') {
const n = Number(num)
return Number.isFinite(n) ? n : undefined
}
const taiMatch = v.match(/([一二三四五六七八九十两]+)胎/)
if (taiMatch) {
const n = parseChineseNumeral(taiMatch[1])
if (n != null) return n
}
const cn = parseChineseNumeral(v)
if (cn != null) return cn
return undefined
}
@@ -1,13 +1,26 @@
import { parseChineseDatetimeText } from '@/utils/chinese-datetime-parse'
import { parseBirthOrder } from '@/utils/chinese-numeral-parse'
import { extractNumericPart } from '@/utils/numeric-input-parse'
import {
SAMPLE_TYPE_PERINATAL_HSC,
SAMPLE_TYPE_UC_MSC
} from '@/utils/sample-production-reception-fields'
export type DonationSampleImportHint = {
typeKey: 'hsc' | 'uc_msc'
typeName: string
collectTime: string
}
export type DonationStandardImportParsed = {
sampleTypeHeader: string
sampleHints: DonationSampleImportHint[]
motherName?: string
newbornSex?: '1' | '0'
newbornWeightGram?: number | null
apgarScore?: number | null
newbornDeliveryTime?: string
/** 协议级样本采集时间:多样本时为各 hint 最早时间 */
sampleCollectTime?: string
maternalBloodCollectTime?: string
maternalBloodExplicitEmpty?: boolean
@@ -15,11 +28,19 @@ export type DonationStandardImportParsed = {
birthOrder?: number | null
medicalStaff?: string
hospitalName?: string
/** @deprecated 使用 transportModeText */
transportExpressName?: string
transportModeText?: string
transportType?: 'kdys' | 'ryxd'
salesUserName?: string
}
const KEY_ALIASES: Record<string, keyof Omit<DonationStandardImportParsed, 'sampleTypeHeader'>> = {
type CommonFieldKey = keyof Omit<
DonationStandardImportParsed,
'sampleTypeHeader' | 'sampleHints' | 'transportExpressName' | 'transportModeText' | 'transportType'
>
const KEY_ALIASES: Record<string, CommonFieldKey> = {
产妇姓名: 'motherName',
母亲姓名: 'motherName',
新生儿性别: 'newbornSex',
@@ -30,14 +51,12 @@ const KEY_ALIASES: Record<string, keyof Omit<DonationStandardImportParsed, 'samp
'新生儿评分5分钟': 'apgarScore',
分娩时间: 'newbornDeliveryTime',
新生儿分娩时间: 'newbornDeliveryTime',
造血干细胞采集时间: 'sampleCollectTime',
样本采集时间: 'sampleCollectTime',
母血采集时间: 'maternalBloodCollectTime',
分娩方式: 'deliveryMode',
胎次: 'birthOrder',
采集医护: 'medicalStaff',
采集医院: 'hospitalName',
运输方式: 'transportExpressName',
运输方式: 'transportModeText',
销售人员: 'salesUserName',
采集专员: 'salesUserName'
}
@@ -56,18 +75,29 @@ function splitKeyValue(line: string): { key: string; value: string } | null {
return { key: match[1].trim(), value: match[2].trim() }
}
function resolveSampleCollectHint(key: string): Omit<DonationSampleImportHint, 'collectTime'> | null {
const k = key.trim()
if (/脐带采集时间/.test(k)) {
return { typeKey: 'uc_msc', typeName: SAMPLE_TYPE_UC_MSC }
}
if (/造血干细胞.*采集时间/.test(k) || k === '样本采集时间') {
return { typeKey: 'hsc', typeName: SAMPLE_TYPE_PERINATAL_HSC }
}
return null
}
function parseSex(value: string): '1' | '0' | undefined {
const v = value.trim()
if (!v) return undefined
if (/^男/.test(v)) return '1'
if (/^女/.test(v)) return '0'
if (/^男|^男孩/.test(v)) return '1'
if (/^女|^女孩/.test(v)) return '0'
return undefined
}
function parseDeliveryMode(value: string): string | undefined {
const v = value.trim()
if (!v) return undefined
if (/剖宫产|剖腹产/.test(v)) return 'pgc'
if (/剖宫产|剖腹产|刨宫产/.test(v)) return 'pgc'
if (/顺产|自然分娩/.test(v)) return 'sc'
return undefined
}
@@ -107,6 +137,33 @@ function isMaternalBloodEmpty(value: string): boolean {
return MATERNAL_BLOOD_EMPTY_MARKERS.some((m) => v === m || v.includes(m))
}
/** 运输方式文本 → 系统 transportType */
export function resolveTransportType(text: string): 'kdys' | 'ryxd' | null {
const v = (text || '').trim()
if (!v) return null
// 「顺丰车」为「顺风车」笔误,须先于「顺丰」快递匹配
if (/顺风车|顺丰车|自行携带|人员携带|自带|自送|亲自送|自驾/.test(v)) return 'ryxd'
if (/帮助|取样本|送到实验室|专人送|送到/.test(v)) return 'ryxd'
if (/快递|顺丰|圆通|中通|韵达|申通|EMS|邮政|极兔|京东|德邦/.test(v)) return 'kdys'
return null
}
function addSampleHint(
hints: DonationSampleImportHint[],
meta: Omit<DonationSampleImportHint, 'collectTime'>,
collectTime: string
) {
if (hints.some((h) => h.typeKey === meta.typeKey)) return
hints.push({ ...meta, collectTime })
}
function earliestCollectTime(hints: DonationSampleImportHint[]): string | undefined {
if (!hints.length) return undefined
return hints
.map((h) => h.collectTime)
.sort((a, b) => a.localeCompare(b))[0]
}
/** 解析捐赠协议单一键导入标准文本 */
export function parseDonationStandardImportText(text: string): DonationStandardImportParsed | null {
const raw = (text || '').trim()
@@ -120,13 +177,21 @@ export function parseDonationStandardImportText(text: string): DonationStandardI
if (!lines.length) return null
const result: DonationStandardImportParsed = {
sampleTypeHeader: lines[0]
sampleTypeHeader: lines[0],
sampleHints: []
}
for (let i = 1; i < lines.length; i++) {
const kv = splitKeyValue(lines[i])
if (!kv) continue
const sampleMeta = resolveSampleCollectHint(kv.key)
if (sampleMeta) {
const dt = parseDatetime(kv.value, true)
if (dt) addSampleHint(result.sampleHints, sampleMeta, dt)
continue
}
const field = KEY_ALIASES[kv.key]
if (!field) continue
@@ -154,11 +219,6 @@ export function parseDonationStandardImportText(text: string): DonationStandardI
if (dt) result.newbornDeliveryTime = dt
break
}
case 'sampleCollectTime': {
const dt = parseDatetime(kv.value, true)
if (dt) result.sampleCollectTime = dt
break
}
case 'maternalBloodCollectTime':
if (isMaternalBloodEmpty(kv.value)) {
result.maternalBloodExplicitEmpty = true
@@ -173,7 +233,7 @@ export function parseDonationStandardImportText(text: string): DonationStandardI
break
}
case 'birthOrder': {
const n = parseScore(kv.value)
const n = parseBirthOrder(kv.value)
if (n !== undefined) result.birthOrder = n
break
}
@@ -183,9 +243,12 @@ export function parseDonationStandardImportText(text: string): DonationStandardI
case 'hospitalName':
if (!result.hospitalName) result.hospitalName = kv.value
break
case 'transportExpressName':
case 'transportModeText': {
result.transportModeText = kv.value
result.transportExpressName = kv.value
result.transportType = resolveTransportType(kv.value) ?? undefined
break
}
case 'salesUserName':
result.salesUserName = kv.value
break
@@ -194,13 +257,36 @@ export function parseDonationStandardImportText(text: string): DonationStandardI
}
}
if (result.sampleHints.length) {
result.sampleCollectTime = earliestCollectTime(result.sampleHints)
}
return result
}
type CellSampleTypeOption = { id: string; typeName: string }
type CellSampleTypeOption = { id: string; typeName: string; storageYears?: number | null }
const SAMPLE_TYPE_SEGMENTS = ['围产期', '造血', '干细胞', '脐带', '间充质', '胎盘', '亚全能', '捐献']
/** 按类型名称精确或包含匹配 */
export function matchSampleTypeByExactName(
typeName: string,
types: CellSampleTypeOption[]
): CellSampleTypeOption | null {
const target = (typeName || '').trim()
if (!target || !types.length) return null
const exact = types.find((t) => t.typeName === target)
if (exact) return exact
const contains = types.filter(
(t) => t.typeName.includes(target) || target.includes(t.typeName)
)
if (contains.length === 1) return contains[0]
return matchCellSampleType(target, types)
}
/** 根据首行文本与细胞样本类型列表做语义匹配 */
export function matchCellSampleType(
headerLine: string,
@@ -0,0 +1,442 @@
import { parseChineseDatetimeText } from '@/utils/chinese-datetime-parse'
import { parseBirthOrder } from '@/utils/chinese-numeral-parse'
import {
isBlankString,
matchCellSampleType,
resolveTransportType
} from '@/utils/donation-standard-import-parse'
import { extractNumericPart } from '@/utils/numeric-input-parse'
import {
SAMPLE_TYPE_PERINATAL_HSC,
SAMPLE_TYPE_UC_MSC
} from '@/utils/sample-production-reception-fields'
export type ProtocolSampleImportHint = {
typeKey: 'hsc' | 'uc_msc'
typeName: string
sampleCode?: string
collectTime?: string
}
export type ProtocolPaymentTransferHint = {
transferAmount: number
transferTime: string
}
export type ProtocolStandardImportParsed = {
sampleTypeHeader: string
sampleHints: ProtocolSampleImportHint[]
motherName?: string
motherPhone?: string
newbornSex?: '1' | '0'
newbornWeightGram?: number | null
apgarScore?: number | null
newbornDeliveryTime?: string
sampleCollectTime?: string
maternalBloodCollectTime?: string
maternalBloodExplicitEmpty?: boolean
deliveryMode?: string
birthOrder?: number | null
medicalStaff?: string
hospitalName?: string
salesUserName?: string
payMode: 'dj' | 'fq'
contractAmount?: number | null
transferTypeLabel?: string
paymentTransfers: ProtocolPaymentTransferHint[]
transportModeText?: string
transportType?: 'kdys' | 'ryxd'
carrierName?: string
etaTime?: string
remark?: string
}
const MATERNAL_BLOOD_EMPTY_MARKERS = ['未采集', '无', '暂无', '—', '-', '未采']
const SAMPLE_CODE_RE = /^ZK[A-Z0-9]+$/i
const KEY_ALIASES: Record<string, string> = {
产妇姓名: 'motherName',
母亲姓名: 'motherName',
孕妇电话: 'motherPhone',
母亲联系电话: 'motherPhone',
新生儿性别: 'newbornSex',
新生儿体重: 'newbornWeightGram',
'新生儿体重(克)': 'newbornWeightGram',
新生儿评分: 'apgarScore',
分娩时间: 'newbornDeliveryTime',
新生儿分娩时间: 'newbornDeliveryTime',
母血采集时间: 'maternalBloodCollectTime',
分娩方式: 'deliveryMode',
胎次: 'birthOrder',
采集医护: 'medicalStaff',
采集医院: 'hospitalName',
销售人员: 'salesUserName',
采集专员: 'salesUserName',
缴费方式: 'payModeText',
转账方式: 'transferTypeText',
合同金额: 'contractAmount',
转账金额: 'transferAmount',
转账时间: 'transferTime',
运输方式: 'transportModeText',
预计送达时间: 'etaTime',
备注: 'remark'
}
function normalizeLine(line: string): string {
return line
.replace(/^[\s【】]+|[\s【】]+$/g, '')
.trim()
}
function splitKeyValue(line: string): { key: string; value: string } | null {
const match = line.match(/^([^::]+)[::]\s*(.*)$/)
if (!match) return null
return { key: match[1].trim(), value: match[2].trim() }
}
function normalizeChineseDatetimeLiteral(value: string): string {
let v = (value || '').trim()
v = v.replace(
/^(\d{4})年(\d{1,2})月(\d{1,2})日(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/,
(_, y, mo, d, h, mi, s) => `${y}年${Number(mo)}月${Number(d)}日${Number(h)}时${Number(mi)}分${s ? Number(s) + '秒' : ''}`
)
return v
}
function parseDatetime(value: string, minutePrecision = false): string | undefined {
const v = normalizeChineseDatetimeLiteral(value.trim())
if (!v) return undefined
if (MATERNAL_BLOOD_EMPTY_MARKERS.some((m) => v === m || v.includes(m))) {
return undefined
}
return (
parseChineseDatetimeText(v, minutePrecision ? 'datetime-minute' : 'datetime') || undefined
)
}
function parseSex(value: string): '1' | '0' | undefined {
const v = value.trim()
if (!v) return undefined
if (/^男|^男孩/.test(v)) return '1'
if (/^女|^女孩/.test(v)) return '0'
return undefined
}
function parseDeliveryMode(value: string): string | undefined {
const v = value.trim()
if (!v) return undefined
if (/剖宫产|剖腹产|刨宫产/.test(v)) return 'pgc'
if (/顺产|自然分娩/.test(v)) return 'sc'
return undefined
}
function parseMoney(value: string): number | null | undefined {
const num = extractNumericPart(value)
if (num == null || num === '') return undefined
const n = Number(num)
return Number.isFinite(n) ? n : undefined
}
function parseScore(value: string): number | null | undefined {
return parseMoney(value)
}
function isMaternalBloodEmpty(value: string): boolean {
const v = value.trim()
if (!v) return true
return MATERNAL_BLOOD_EMPTY_MARKERS.some((m) => v === m || v.includes(m))
}
function resolveSampleCollectHint(key: string): Pick<ProtocolSampleImportHint, 'typeKey' | 'typeName'> | null {
const k = key.trim()
if (/脐带间充质.*采集时间/.test(k) || k === '脐带采集时间') {
return { typeKey: 'uc_msc', typeName: SAMPLE_TYPE_UC_MSC }
}
if (/造血干细胞.*采集时间/.test(k) || k === '样本采集时间') {
return { typeKey: 'hsc', typeName: SAMPLE_TYPE_PERINATAL_HSC }
}
return null
}
function resolveSampleCodeHint(
key: string,
value: string
): (Pick<ProtocolSampleImportHint, 'typeKey' | 'typeName'> & { sampleCode: string }) | null {
const code = value.trim().toUpperCase()
if (!SAMPLE_CODE_RE.test(code)) return null
const k = key.trim()
if (/脐带间充质/.test(k)) {
return { typeKey: 'uc_msc', typeName: SAMPLE_TYPE_UC_MSC, sampleCode: code }
}
if (/造血干细胞/.test(k)) {
return { typeKey: 'hsc', typeName: SAMPLE_TYPE_PERINATAL_HSC, sampleCode: code }
}
return null
}
function upsertSampleHint(
hints: ProtocolSampleImportHint[],
partial: Partial<ProtocolSampleImportHint> & Pick<ProtocolSampleImportHint, 'typeKey' | 'typeName'>
) {
let hint = hints.find((h) => h.typeKey === partial.typeKey)
if (!hint) {
hint = { typeKey: partial.typeKey, typeName: partial.typeName }
hints.push(hint)
}
if (partial.sampleCode) hint.sampleCode = partial.sampleCode
if (partial.collectTime) hint.collectTime = partial.collectTime
}
function earliestCollectTime(hints: ProtocolSampleImportHint[]): string | undefined {
const times = hints.map((h) => h.collectTime).filter(Boolean) as string[]
if (!times.length) return undefined
return times.sort((a, b) => a.localeCompare(b))[0]
}
/** 缴费方式:仅「分期」为 fq,其余(含微信/趸交)均为 dj */
export function parsePayModeFromText(value: string): {
payMode: 'dj' | 'fq'
transferLabel?: string
} {
const v = (value || '').trim()
if (/分期/.test(v)) return { payMode: 'fq' }
if (/微信|支付宝|银行卡|银行|现金/.test(v)) {
return { payMode: 'dj', transferLabel: v }
}
return { payMode: 'dj' }
}
/** 解析转账时间行(支持多笔:…2000元,…付20880元) */
export function parsePaymentTransferSegments(
text: string,
fallbackAmount?: number | null
): ProtocolPaymentTransferHint[] {
const raw = (text || '').trim()
if (!raw) {
if (fallbackAmount != null && fallbackAmount > 0) {
return [{ transferAmount: fallbackAmount, transferTime: '' }]
}
return []
}
const segments = raw.split(/[,,]/).map((s) => s.trim()).filter(Boolean)
const results: ProtocolPaymentTransferHint[] = []
let defaultYear: number | undefined
for (const seg of segments) {
const amountMatch = seg.match(/(?:付)?(\d+(?:\.\d+)?)\s*元\s*$/)
if (!amountMatch) continue
const transferAmount = Number(amountMatch[1])
if (!Number.isFinite(transferAmount)) continue
let dtRaw = seg.slice(0, seg.length - amountMatch[0].length).trim()
dtRaw = normalizeChineseDatetimeLiteral(dtRaw)
if (/^\d{1,2}月/.test(dtRaw) && defaultYear) {
dtRaw = `${defaultYear}年${dtRaw}`
}
const transferTime = parseChineseDatetimeText(dtRaw, 'datetime')
if (transferTime) {
if (!defaultYear) defaultYear = Number(transferTime.slice(0, 4))
results.push({ transferAmount, transferTime })
}
}
if (results.length) return results
const transferTime = parseChineseDatetimeText(normalizeChineseDatetimeLiteral(raw), 'datetime')
if (fallbackAmount != null && fallbackAmount > 0) {
return [{ transferAmount: fallbackAmount, transferTime: transferTime || '' }]
}
if (transferTime) {
return [{ transferAmount: fallbackAmount ?? 0, transferTime }]
}
return []
}
/** 字典 label → transfer_type 值(wxzz 等) */
export function resolveTransferTypeCode(
label: string,
options: Array<{ value: string; label: string }>
): string {
const v = (label || '').trim()
if (!v || !options.length) return ''
const exact = options.find((o) => o.label === v || o.value === v)
if (exact) return exact.value
const contains = options.filter((o) => o.label.includes(v) || v.includes(o.label))
if (contains.length === 1) return contains[0].value
const keywordMap: Array<[RegExp, string]> = [
[/微信/, '微信'],
[/支付宝/, '支付宝'],
[/银行/, '银行'],
[/现金/, '现金']
]
for (const [re, kw] of keywordMap) {
if (!re.test(v)) continue
const hit = options.find((o) => o.label.includes(kw))
if (hit) return hit.value
}
return ''
}
/** 从运输描述中提取携带人姓名(如「露露帮助…」) */
export function extractCarrierNameFromTransport(text: string): string | undefined {
const v = (text || '').trim()
const m = v.match(/^([\u4e00-\u9fa5]{1,4})(?:帮助|协助|取)/)
return m?.[1]
}
/** 解析采集协议单一键导入标准文本 */
export function parseProtocolStandardImportText(text: string): ProtocolStandardImportParsed | null {
const raw = (text || '').trim()
if (!raw) return null
const lines = raw
.split(/\r?\n/)
.map(normalizeLine)
.filter(Boolean)
if (!lines.length) return null
const result: ProtocolStandardImportParsed = {
sampleTypeHeader: lines[0],
sampleHints: [],
payMode: 'dj',
paymentTransfers: []
}
let transferTimeRaw = ''
let transferAmountSingle: number | null | undefined
for (let i = 1; i < lines.length; i++) {
const kv = splitKeyValue(lines[i])
if (!kv) continue
const codeHint = resolveSampleCodeHint(kv.key, kv.value)
if (codeHint) {
upsertSampleHint(result.sampleHints, codeHint)
continue
}
const collectMeta = resolveSampleCollectHint(kv.key)
if (collectMeta) {
const dt = parseDatetime(kv.value, true)
if (dt) upsertSampleHint(result.sampleHints, { ...collectMeta, collectTime: dt })
continue
}
const field = KEY_ALIASES[kv.key]
if (!field) continue
switch (field) {
case 'motherName':
result.motherName = kv.value
break
case 'motherPhone':
result.motherPhone = kv.value.replace(/\s+/g, '')
break
case 'newbornSex': {
const sex = parseSex(kv.value)
if (sex) result.newbornSex = sex
break
}
case 'newbornWeightGram': {
const w = parseMoney(kv.value)
if (w !== undefined) result.newbornWeightGram = w
break
}
case 'apgarScore': {
const s = parseScore(kv.value)
if (s !== undefined) result.apgarScore = s
break
}
case 'newbornDeliveryTime': {
const dt = parseDatetime(kv.value)
if (dt) result.newbornDeliveryTime = dt
break
}
case 'maternalBloodCollectTime':
if (isMaternalBloodEmpty(kv.value)) {
result.maternalBloodExplicitEmpty = true
} else {
const dt = parseDatetime(kv.value, true)
if (dt) result.maternalBloodCollectTime = dt
}
break
case 'deliveryMode': {
const mode = parseDeliveryMode(kv.value)
if (mode) result.deliveryMode = mode
break
}
case 'birthOrder': {
const n = parseBirthOrder(kv.value)
if (n !== undefined) result.birthOrder = n
break
}
case 'medicalStaff':
result.medicalStaff = kv.value
break
case 'hospitalName':
if (!result.hospitalName) result.hospitalName = kv.value
break
case 'salesUserName':
result.salesUserName = kv.value
break
case 'payModeText': {
const pm = parsePayModeFromText(kv.value)
result.payMode = pm.payMode
if (pm.transferLabel && !result.transferTypeLabel) {
result.transferTypeLabel = pm.transferLabel
}
break
}
case 'transferTypeText':
result.transferTypeLabel = kv.value
break
case 'contractAmount': {
const amt = parseMoney(kv.value)
if (amt !== undefined) result.contractAmount = amt
break
}
case 'transferAmount': {
const amt = parseMoney(kv.value)
if (amt !== undefined) transferAmountSingle = amt
break
}
case 'transferTime':
transferTimeRaw = kv.value
break
case 'transportModeText': {
result.transportModeText = kv.value
result.transportType = resolveTransportType(kv.value) ?? undefined
result.carrierName = extractCarrierNameFromTransport(kv.value)
break
}
case 'etaTime': {
const dt = parseDatetime(kv.value)
if (dt) result.etaTime = dt
break
}
case 'remark':
result.remark = kv.value
break
default:
break
}
}
result.paymentTransfers = parsePaymentTransferSegments(transferTimeRaw, transferAmountSingle ?? null)
if (result.sampleHints.length) {
result.sampleCollectTime = earliestCollectTime(result.sampleHints)
}
return result
}
export { matchCellSampleType, isBlankString }
@@ -41,7 +41,17 @@ export type AttachmentZipExportResult = {
const PREPARING_MAX = 5
const DOWNLOADING_MAX = 85
function isInboundQcWorkOrder(row: QcWorkOrder) {
return (row.workOrderType || 'inbound') === 'inbound'
}
function workOrderFolderName(row: QcWorkOrder, used: Set<string>) {
if (isInboundQcWorkOrder(row)) {
const labCode = sanitizeZipPathSegment(row.labStorageCode || '', '未命名')
const workOrderNo = sanitizeZipPathSegment(row.workOrderNo || row.id, '工单')
const base = `入库${labCode}_${workOrderNo}`
return ensureUniqueZipEntryName(base, used)
}
const parts = [sanitizeZipPathSegment(row.workOrderNo || row.id, '工单')]
if (row.sampleCode) {
parts.push(`样本${sanitizeZipPathSegment(row.sampleCode)}`)
@@ -49,15 +59,34 @@ function workOrderFolderName(row: QcWorkOrder, used: Set<string>) {
return ensureUniqueZipEntryName(parts.join('_'), used)
}
function batchFolderName(batch: QcInspectionBatch, used: Set<string>) {
const no = sanitizeZipPathSegment(batch.batchNo || '', '')
function applyInboundLabStorageCodePrefix(code: string, workOrder: QcWorkOrder) {
if (!isInboundQcWorkOrder(workOrder)) return code
const raw = String(code || '').trim()
const workOrderNo = String(workOrder.workOrderNo || '').trim()
if (!raw || !workOrderNo || !raw.startsWith(workOrderNo)) return raw
const labCode = sanitizeZipPathSegment(workOrder.labStorageCode || '', '未命名')
return sanitizeZipPathSegment(`${labCode}${raw.slice(workOrderNo.length)}`, '')
}
function batchFolderName(batch: QcInspectionBatch, workOrder: QcWorkOrder, used: Set<string>) {
const no = sanitizeZipPathSegment(
applyInboundLabStorageCodePrefix(batch.batchNo || '', workOrder),
''
)
const name = sanitizeZipPathSegment(batch.batchName || '未命名批次')
const base = no ? `${no}_${name}` : name || `批次${batch.orderNum ?? 1}`
return ensureUniqueZipEntryName(base, used)
}
function taskFolderName(task: { taskNo?: string; itemName?: string }, used: Set<string>) {
const no = sanitizeZipPathSegment(task.taskNo || '', '')
function taskFolderName(
task: { taskNo?: string; itemName?: string },
workOrder: QcWorkOrder,
used: Set<string>
) {
const no = sanitizeZipPathSegment(
applyInboundLabStorageCodePrefix(task.taskNo || '', workOrder),
''
)
const name = sanitizeZipPathSegment(task.itemName || '未命名任务')
const base = no ? `${no}_${name}` : name
return ensureUniqueZipEntryName(base, used)
@@ -76,7 +105,7 @@ export function buildQcWorkOrderZipEntries(
const usedBatchFolders = new Set<string>()
for (const batch of batches) {
const batchFolder = batchFolderName(batch, usedBatchFolders)
const batchFolder = batchFolderName(batch, wo, usedBatchFolders)
const tasks = batch.tasks || []
const usedTaskFolders = new Set<string>()
@@ -84,7 +113,7 @@ export function buildQcWorkOrderZipEntries(
const files = task.attachmentFiles?.filter((f) => String(f.fileUrl || '').trim()) || []
if (!files.length) continue
const taskFolder = taskFolderName(task, usedTaskFolders)
const taskFolder = taskFolderName(task, wo, usedTaskFolders)
const usedFileNames = new Set<string>()
const contextHint = [wo.workOrderNo, batch.batchName, task.itemName]
.filter(Boolean)
@@ -200,6 +200,9 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="经办人" min-width="100" align="center" header-align="center">
<template #default="{ row }">{{ row.operatorName || '—' }}</template>
</el-table-column>
<el-table-column
v-if="!mineOnly"
label="领用人"
@@ -575,6 +578,10 @@
value: getSourceLabel(row.sourceType),
tagType: getSourceTagType(row.sourceType) as any
},
{
label: '经办人',
value: row.operatorName || '—'
},
{
label: '领用人',
value: displayReceiver(row) === '-' ? '—' : displayReceiver(row)
@@ -292,13 +292,13 @@
</el-select>
</el-form-item>
<el-form-item label="入库编号" prop="stockInNo">
<el-input v-model="formData.stockInNo" placeholder="请输入入库编号" />
<el-input v-model="formData.stockInNo" placeholder="可选" />
</el-form-item>
<el-form-item label="入库日期" prop="stockInDate">
<el-date-picker
v-model="formData.stockInDate"
type="date"
placeholder="选择入库日期"
placeholder="可选"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
@@ -307,19 +307,19 @@
<el-date-picker
v-model="formData.expireDate"
type="date"
placeholder="选择过期日期"
placeholder="可选"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="货号" prop="catalogNo">
<el-input v-model="formData.catalogNo" placeholder="请输入货号" />
<el-input v-model="formData.catalogNo" placeholder="可选" />
</el-form-item>
<el-form-item label="批号" prop="batchNo">
<el-input v-model="formData.batchNo" placeholder="请输入批号" />
<el-input v-model="formData.batchNo" placeholder="可选" />
</el-form-item>
<el-form-item label="厂家" prop="manufacturer">
<el-input v-model="formData.manufacturer" placeholder="请输入厂家" />
<el-input v-model="formData.manufacturer" placeholder="可选" />
</el-form-item>
<el-form-item label="单位" prop="unit">
<el-select
@@ -348,7 +348,7 @@
<AmountInput
v-model="formData.unitPrice"
:min="0"
placeholder="请输入单价"
placeholder="可选"
@change="onEditPriceQtyChange"
/>
</el-form-item>
@@ -356,7 +356,7 @@
<AmountInput
v-model="formData.amount"
:min="0"
placeholder="自动计算:单价 × 数量"
placeholder="可选,可自动计算:单价 × 数量"
@change="formData.amountManual = true"
/>
</el-form-item>
@@ -402,6 +402,28 @@
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
>
<div class="form-grid-3">
<el-form-item label="经办人" prop="operator">
<el-select
v-model="stockInForm.operator"
placeholder="请选择经办人"
clearable
filterable
remote
allow-create
default-first-option
reserve-keyword
:loading="receiverUserLoading"
:remote-method="searchReceiverUsers"
style="width: 100%"
>
<el-option
v-for="u in receiverUserOptions"
:key="u.id"
:label="formatReceiverUserLabel(u)"
:value="(u.nickName || '').trim()"
/>
</el-select>
</el-form-item>
<el-form-item label="物资" prop="materialKey">
<el-select
v-model="stockInForm.materialKey"
@@ -461,13 +483,13 @@
</el-select>
</el-form-item>
<el-form-item label="入库编号" prop="stockInNo">
<el-input v-model="stockInForm.stockInNo" placeholder="请输入入库编号" />
<el-input v-model="stockInForm.stockInNo" placeholder="可选" />
</el-form-item>
<el-form-item label="入库日期" prop="stockInDate">
<el-date-picker
v-model="stockInForm.stockInDate"
type="date"
placeholder="选择入库日期"
placeholder="可选"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
@@ -476,19 +498,19 @@
<el-date-picker
v-model="stockInForm.expireDate"
type="date"
placeholder="选择过期日期"
placeholder="可选"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="货号" prop="catalogNo">
<el-input v-model="stockInForm.catalogNo" placeholder="请输入货号" />
<el-input v-model="stockInForm.catalogNo" placeholder="可选" />
</el-form-item>
<el-form-item label="批号" prop="batchNo">
<el-input v-model="stockInForm.batchNo" placeholder="请输入批号" />
<el-input v-model="stockInForm.batchNo" placeholder="可选" />
</el-form-item>
<el-form-item label="厂家" prop="manufacturer">
<el-input v-model="stockInForm.manufacturer" placeholder="请输入厂家" />
<el-input v-model="stockInForm.manufacturer" placeholder="可选" />
</el-form-item>
<el-form-item label="单位">
<el-select
@@ -519,7 +541,7 @@
<el-form-item label="入库数量" prop="qty">
<DecimalInput
v-model="stockInForm.qty"
:min="0.01"
:min="0"
:precision="2"
style="width: 100%"
@change="onSingleStockInPriceQtyChange"
@@ -529,7 +551,7 @@
<AmountInput
v-model="stockInForm.unitPrice"
:min="0"
placeholder="请输入单价"
placeholder="可选"
@change="onSingleStockInPriceQtyChange"
/>
</el-form-item>
@@ -537,7 +559,7 @@
<AmountInput
v-model="stockInForm.amount"
:min="0"
placeholder="自动计算:单价 × 数量"
placeholder="可选,可自动计算:单价 × 数量"
@change="stockInForm.amountManual = true"
/>
</el-form-item>
@@ -584,6 +606,28 @@
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
>
<div class="form-grid-2 batch-stock-move-head">
<el-form-item label="经办人" prop="operator">
<el-select
v-model="batchStockInForm.operator"
placeholder="请选择经办人"
clearable
filterable
remote
allow-create
default-first-option
reserve-keyword
:loading="receiverUserLoading"
:remote-method="searchReceiverUsers"
style="width: 100%"
>
<el-option
v-for="u in receiverUserOptions"
:key="u.id"
:label="formatReceiverUserLabel(u)"
:value="(u.nickName || '').trim()"
/>
</el-select>
</el-form-item>
<el-form-item label="入库时间" prop="stockInTime">
<el-date-picker
v-model="batchStockInForm.stockInTime"
@@ -665,7 +709,7 @@
/>
</el-form-item>
<el-form-item label="入库编号">
<el-input v-model="row.stockInNo" size="small" placeholder="必填" />
<el-input v-model="row.stockInNo" size="small" placeholder="可选" />
</el-form-item>
<el-form-item label="入库日期">
<el-date-picker
@@ -673,7 +717,7 @@
size="small"
type="date"
value-format="YYYY-MM-DD"
placeholder="日期"
placeholder="可选"
style="width: 100%"
/>
</el-form-item>
@@ -683,24 +727,24 @@
size="small"
type="date"
value-format="YYYY-MM-DD"
placeholder="必填"
placeholder="可选"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="货号">
<el-input v-model="row.catalogNo" size="small" placeholder="必填" />
<el-input v-model="row.catalogNo" size="small" placeholder="可选" />
</el-form-item>
<el-form-item label="批号">
<el-input v-model="row.batchNo" size="small" placeholder="必填" />
<el-input v-model="row.batchNo" size="small" placeholder="可选" />
</el-form-item>
<el-form-item label="厂家">
<el-input v-model="row.manufacturer" size="small" placeholder="必填" />
<el-input v-model="row.manufacturer" size="small" placeholder="可选" />
</el-form-item>
<el-form-item label="数量">
<DecimalInput
v-model="row.qty"
size="small"
:min="0.01"
:min="0"
:precision="2"
style="width: 100%"
@change="() => onBatchInLinePriceQtyChange(row)"
@@ -767,6 +811,28 @@
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
>
<div class="form-grid-2 batch-stock-move-head">
<el-form-item label="经办人" prop="operator">
<el-select
v-model="batchStockOutForm.operator"
placeholder="请选择经办人"
clearable
filterable
remote
allow-create
default-first-option
reserve-keyword
:loading="receiverUserLoading"
:remote-method="searchReceiverUsers"
style="width: 100%"
>
<el-option
v-for="u in receiverUserOptions"
:key="u.id"
:label="formatReceiverUserLabel(u)"
:value="(u.nickName || '').trim()"
/>
</el-select>
</el-form-item>
<el-form-item label="出库时间" prop="stockOutTime">
<el-date-picker
v-model="batchStockOutForm.stockOutTime"
@@ -959,6 +1025,28 @@
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
>
<div class="form-grid-2 batch-stock-move-head">
<el-form-item label="经办人" prop="operator">
<el-select
v-model="batchDiscardForm.operator"
placeholder="请选择经办人"
clearable
filterable
remote
allow-create
default-first-option
reserve-keyword
:loading="receiverUserLoading"
:remote-method="searchReceiverUsers"
style="width: 100%"
>
<el-option
v-for="u in receiverUserOptions"
:key="u.id"
:label="formatReceiverUserLabel(u)"
:value="(u.nickName || '').trim()"
/>
</el-select>
</el-form-item>
<el-form-item label="废弃时间" prop="discardTime">
<el-date-picker
v-model="batchDiscardForm.discardTime"
@@ -1143,6 +1231,9 @@
<el-table-column label="领用人" min-width="90" align="center" header-align="center">
<template #default="{ row }">{{ row.receiver || '—' }}</template>
</el-table-column>
<el-table-column label="经办人" min-width="90" align="center" header-align="center">
<template #default="{ row }">{{ row.operatorName || '—' }}</template>
</el-table-column>
<el-table-column label="用途" min-width="120" align="center" header-align="center" show-overflow-tooltip>
<template #default="{ row }">{{ row.purpose || row.remark || '—' }}</template>
</el-table-column>
@@ -1204,12 +1295,37 @@
import { fetchMaterialUsageList, type MaterialUsage } from '@/api/material-usage'
import { MATERIAL_DISCARD_REASONS } from '@/constants/material-discard'
import { fetchAllPagedRecords } from '@/utils/fetch-paged-list'
import { useUserStore } from '@/store/modules/user'
import MaterialUsageTab from './MaterialUsageTab.vue'
import MaterialStockCheckTab from './MaterialStockCheckTab.vue'
defineOptions({ name: 'CellStorageMaterial' })
const route = useRoute()
const userStore = useUserStore()
function defaultOperatorName() {
const info = userStore.info as Record<string, unknown>
return String(info?.realName || info?.userName || info?.username || info?.nickName || '').trim()
}
function ensureOperatorOption(name: string) {
const v = name?.trim()
if (!v) return
if (!receiverUserOptions.value.some((u) => (u.nickName || '').trim() === v)) {
receiverUserOptions.value = [
{ id: `local-op-${v}`, nickName: v, userNo: '', phoneNo: '' } as Api.User.UserItem,
...receiverUserOptions.value
]
}
}
function initOperatorField(target: { operator: string }) {
const name = defaultOperatorName()
target.operator = name
ensureOperatorOption(name)
void searchReceiverUsers('')
}
const MATERIAL_TABS = [
{ name: 'list', label: '物料列表' },
@@ -1347,14 +1463,6 @@
})
const formRules = {
stockInNo: [{ required: true, message: '请输入入库编号', trigger: 'blur' }],
stockInDate: [{ required: true, message: '请选择入库日期', trigger: 'change' }],
expireDate: [{ required: true, message: '请选择过期日期', trigger: 'change' }],
catalogNo: [{ required: true, message: '请输入货号', trigger: 'blur' }],
batchNo: [{ required: true, message: '请输入批号', trigger: 'blur' }],
manufacturer: [{ required: true, message: '请输入厂家', trigger: 'blur' }],
unitPrice: [{ required: true, message: '请输入单价', trigger: 'change' }],
amount: [{ required: true, message: '请输入金额', trigger: 'change' }],
materialCode: [{ required: true, message: '请输入物料编码', trigger: 'blur' }],
materialName: [{ required: true, message: '请输入物料名称', trigger: 'blur' }]
}
@@ -1380,6 +1488,7 @@
amount: 0 as number | null,
amountManual: false,
qty: 1,
operator: '',
remark: ''
})
@@ -1408,15 +1517,7 @@
trigger: 'blur'
}
],
stockInNo: [{ required: true, message: '请输入入库编号', trigger: 'blur' }],
stockInDate: [{ required: true, message: '请选择入库日期', trigger: 'change' }],
expireDate: [{ required: true, message: '请选择过期日期', trigger: 'change' }],
catalogNo: [{ required: true, message: '请输入货号', trigger: 'blur' }],
batchNo: [{ required: true, message: '请输入批号', trigger: 'blur' }],
manufacturer: [{ required: true, message: '请输入厂家', trigger: 'blur' }],
unitPrice: [{ required: true, message: '请输入单价', trigger: 'change' }],
amount: [{ required: true, message: '请输入金额', trigger: 'change' }],
qty: [{ required: true, message: '请输入入库数量', trigger: 'blur' }]
operator: [{ required: true, message: '请选择经办人', trigger: 'change' }]
}
function formatReceiverUserLabel(u: Api.User.UserItem) {
@@ -1478,11 +1579,13 @@
const batchStockInLines = ref<BatchStockInLine[]>([])
const batchStockInForm = reactive({
stockInTime: '',
operator: '',
remark: ''
})
const batchStockInRules = {
stockInTime: [{ required: true, message: '请选择入库时间', trigger: 'change' }]
stockInTime: [{ required: true, message: '请选择入库时间', trigger: 'change' }],
operator: [{ required: true, message: '请选择经办人', trigger: 'change' }]
}
// 批量出库
@@ -1503,6 +1606,7 @@
const batchStockOutLines = ref<BatchStockOutLine[]>([])
const batchStockOutForm = reactive({
stockOutTime: '',
operator: '',
receiver: '',
purpose: '',
remark: ''
@@ -1513,6 +1617,7 @@
const batchStockOutRules = {
stockOutTime: [{ required: true, message: '请选择出库时间', trigger: 'change' }],
operator: [{ required: true, message: '请选择经办人', trigger: 'change' }],
receiver: [{ required: true, message: '请选择领用人', trigger: 'change' }]
}
@@ -1534,12 +1639,14 @@
const batchDiscardLines = ref<BatchDiscardLine[]>([])
const batchDiscardForm = reactive({
discardTime: '',
operator: '',
discardReason: '',
remark: ''
})
const batchDiscardRules = {
discardTime: [{ required: true, message: '请选择废弃时间', trigger: 'change' }],
operator: [{ required: true, message: '请选择经办人', trigger: 'change' }],
discardReason: [{ required: true, message: '请选择废弃原因', trigger: 'change' }],
remark: [
{
@@ -1906,6 +2013,7 @@
stockInForm.amount = null
stockInForm.amountManual = false
stockInForm.qty = 1
stockInForm.operator = defaultOperatorName()
stockInForm.remark = ''
}
@@ -1916,6 +2024,7 @@
function handleOpenStockIn() {
resetStockInForm()
initOperatorField(stockInForm)
stockInVisible.value = true
void searchMaterialOptions('')
stockInFormRef.value?.clearValidate?.()
@@ -1937,6 +2046,7 @@
amount: Number(stockInForm.amount) || 0,
qty: stockInForm.qty,
stockInTime: formatNowDatetime(),
operatorName: stockInForm.operator?.trim() || undefined,
remark: stockInForm.remark?.trim() || undefined
})
ElMessage.success('入库成功')
@@ -2081,6 +2191,7 @@
batchDiscardForm.discardTime = formatNowDatetime()
batchDiscardForm.discardReason = ''
batchDiscardForm.remark = ''
initOperatorField(batchDiscardForm)
batchDiscardVisible.value = true
void searchBatchOptions('')
void searchUnitOptions('')
@@ -2134,6 +2245,7 @@
remark: l.remark?.trim() || undefined
})),
discardReason: batchDiscardForm.discardReason?.trim() || '',
operatorName: batchDiscardForm.operator?.trim() || undefined,
remark: batchDiscardForm.remark?.trim() || undefined,
discardTime: batchDiscardForm.discardTime || undefined
})
@@ -2151,6 +2263,7 @@
batchStockInLines.value = [newBatchStockInLine()]
batchStockInForm.stockInTime = formatNowDatetime()
batchStockInForm.remark = ''
initOperatorField(batchStockInForm)
batchStockInVisible.value = true
void searchMaterialOptions('')
batchStockInFormRef.value?.clearValidate?.()
@@ -2167,30 +2280,6 @@
ElMessage.warning('请选择物资')
return
}
if (!line.stockInNo?.trim()) {
ElMessage.warning('请填写入库编号')
return
}
if (!line.stockInDate) {
ElMessage.warning('请选择入库日期')
return
}
if (!line.expireDate) {
ElMessage.warning('请选择过期日期')
return
}
if (!line.catalogNo?.trim() || !line.batchNo?.trim() || !line.manufacturer?.trim()) {
ElMessage.warning('请填写货号、批号、厂家')
return
}
if (line.unitPrice == null || line.amount == null) {
ElMessage.warning('请填写单价和金额')
return
}
if (!line.qty || line.qty <= 0) {
ElMessage.warning('入库数量必须大于 0')
return
}
}
try {
await ElMessageBox.confirm(
@@ -2218,6 +2307,7 @@
remark: l.remark?.trim() || undefined
})),
stockInTime: batchStockInForm.stockInTime || undefined,
operatorName: batchStockInForm.operator?.trim() || undefined,
remark: batchStockInForm.remark?.trim() || undefined
})
ElMessage.success(`批量入库成功,共 ${res.count ?? batchStockInLines.value.length} 项`)
@@ -2236,6 +2326,7 @@
batchStockOutForm.receiver = ''
batchStockOutForm.purpose = ''
batchStockOutForm.remark = ''
initOperatorField(batchStockOutForm)
batchStockOutVisible.value = true
void searchReceiverUsers('')
void searchBatchOptions('')
@@ -2286,6 +2377,7 @@
remark: l.remark?.trim() || undefined
})),
stockOutTime: batchStockOutForm.stockOutTime || undefined,
operatorName: batchStockOutForm.operator?.trim() || undefined,
receiver: batchStockOutForm.receiver?.trim() || undefined,
purpose: batchStockOutForm.purpose?.trim() || undefined,
remark: batchStockOutForm.remark?.trim() || undefined
@@ -34,13 +34,41 @@
scroll-to-error
class="protocol-form"
>
<!-- Tab 1: 基本信息 -->
<div id="form-section-basic" class="form-tab-pane">
<!-- Tab 1: 基本信息(新增时左侧一键导入、右侧基本信息) -->
<div
id="form-section-basic"
class="form-tab-pane"
:class="{ 'form-tab-pane--import-basic': !isEdit }"
>
<div v-if="!isEdit" class="section-card section-card--import">
<div class="section-title">
<div class="section-title-left"><h3>一键导入</h3></div>
</div>
<el-form-item label="标准信息">
<el-input
v-model="standardImportText"
type="textarea"
:rows="12"
placeholder="请粘贴标准格式信息,点击「一键导入」填充各 Tab 字段"
/>
</el-form-item>
<div class="import-actions">
<el-button
class="btn-main"
type="primary"
:loading="standardImportLoading"
@click="handleStandardImport"
>
<el-icon><Upload /></el-icon>
一键导入
</el-button>
</div>
</div>
<div class="section-card">
<div class="section-title">
<div class="section-title-left"><h3>基本信息</h3></div>
</div>
<div class="form-grid form-grid--col4">
<div class="form-grid" :class="isEdit ? 'form-grid--col4' : 'form-grid--col2'">
<el-form-item label="协议状态" prop="protocolStatus">
<el-select
v-model="formData.protocolStatus"
@@ -673,13 +701,12 @@
<div class="detail-body-inner">
<div class="form-grid form-grid--col4">
<el-form-item label="应缴费金额(元)">
<el-input
<AmountInput
v-model="detail.dueAmount"
type="number"
step="any"
:min="0"
disabled
style="width: 100%"
:disabled="isPayDetailLocked(detail)"
placeholder="请输入应缴费金额"
@change="onPaymentDetailDueAmountChange(dIdx)"
/>
</el-form-item>
<el-form-item label="转账方式">
@@ -891,7 +918,8 @@
Loading,
Download,
ArrowDown,
ArrowRight
ArrowRight,
Upload
} from '@element-plus/icons-vue'
import {
fetchCollectionProtocolDetail,
@@ -906,6 +934,17 @@
useIndexedAttachmentDropZone
} from '@/composables/useAttachmentDropZone'
import { formatDatetimeToMinute } from '@/utils/chinese-datetime-parse'
import {
matchExpressCompany,
matchSampleTypeByExactName
} from '@/utils/donation-standard-import-parse'
import {
parseProtocolStandardImportText,
resolveTransferTypeCode,
isBlankString,
matchCellSampleType,
type ProtocolStandardImportParsed
} from '@/utils/protocol-standard-import-parse'
import {
fetchCustomerList,
fetchUserList,
@@ -914,6 +953,7 @@
fetchItemUnitList,
fetchCollectionRegionList,
fetchHospitalList,
fetchSearchCollectionHospitals,
fetchSampleCodeList,
fetchExpressCompanyList,
fetchSiteList
@@ -1165,6 +1205,8 @@
const dialogFormLoading = ref(false)
const dialogTitle = ref('新增协议单')
const isEdit = ref(false)
const standardImportText = ref('')
const standardImportLoading = ref(false)
const submitLoading = ref(false)
const editingId = ref<string | null>(null)
const formRef = ref()
@@ -1302,6 +1344,7 @@
expressCompanyOptions.value = []
activeFormTab.value = 'basic'
lastConfirmedPayMode.value = 'dj'
standardImportText.value = ''
lastConfirmedFqParams.value = {
installmentCount: null,
installmentIntervalMonths: null,
@@ -1862,7 +1905,6 @@
submitLoading.value = true
try {
syncFqPaymentDetailRowCount(fqPaymentContext(), formData.paymentDetails)
syncPaymentDueAmounts()
const protocolAttachmentUrls = formData.attachments
.map((a) => a.fileUrl)
.filter(Boolean)
@@ -2246,6 +2288,527 @@
ensureSitesInOptions(formData.samples)
}
function formatNowDatetime(): string {
const now = new Date()
const pad = (n: number) => String(n).padStart(2, '0')
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
}
/** 一键导入前清空上次导入/手填的可覆盖字段(保留协议状态、登记日期、附件等) */
function clearFormBeforeStandardImport() {
customerId.value = null
customerSnapshot.value = null
customerOptions.value = []
formData.customerId = ''
formData.motherName = ''
formData.motherPhone = ''
formData.motherIdCard = ''
formData.motherBirthYm = ''
formData.motherEmail = ''
formData.motherAddress = ''
formData.fatherName = ''
formData.fatherPhone = ''
formData.fatherIdCard = ''
formData.newbornName = ''
formData.newbornIdCard = ''
formData.expectedDeliveryDate = ''
formData.newbornSex = ''
formData.newbornWeightGram = null
formData.apgar1min = null
formData.apgar5min = null
formData.newbornDeliveryTime = ''
formData.deliveryMode = ''
formData.birthOrder = null
formData.regionId = ''
formData.hospitalId = ''
formData.medicalStaff = ''
formData.sampleCollectTime = ''
formData.maternalBloodCollectTime = ''
regionOptions.value = []
hospitalOptions.value = []
collectorUserId.value = null
collectorSnapshot.value = null
collectorUserOptions.value = []
formData.collectorUserId = ''
salesUserId.value = null
salesSnapshot.value = null
salesUserOptions.value = []
formData.salesUserId = ''
formData.samples = []
sampleCodeOptions.value = []
siteOptions.value = []
expressCompanyOptions.value = []
formData.payMode = 'dj'
formData.contractAmount = null
formData.lumpSumDeadline = ''
formData.installmentCount = null
formData.installmentIntervalMonths = null
formData.installmentStartDate = ''
formData.installmentAdvanceDays = DEFAULT_INSTALLMENT_ADVANCE_DAYS
formData.installmentRatios = []
formData.paymentDetails = []
lastConfirmedPayMode.value = 'dj'
lastConfirmedFqParams.value = {
installmentCount: null,
installmentIntervalMonths: null,
installmentStartDate: '',
installmentAdvanceDays: DEFAULT_INSTALLMENT_ADVANCE_DAYS,
installmentRatios: [] as number[]
}
formData.remark = ''
}
async function applyMotherByName(name: string): Promise<'linked' | 'name-only' | 'skipped'> {
const keyword = (name || '').trim()
if (!keyword) return 'skipped'
if (!isBlankString(formData.customerId)) return 'skipped'
if (!isBlankString(formData.motherName)) return 'skipped'
try {
const res = await fetchCustomerList({ page: 1, pageSize: 50, keyword })
const list = res.list || []
const match =
list.find((c) => c.customerName === keyword) ||
list.find((c) => (c.customerName || '').includes(keyword))
if (match) {
customerOptions.value = [match, ...list.filter((c) => c.id !== match.id)]
onCustomerChange(match.id)
return 'linked'
}
formData.motherName = keyword
return 'name-only'
} catch {
formData.motherName = keyword
return 'name-only'
}
}
async function applyHospitalByName(name: string): Promise<boolean> {
const keyword = (name || '').trim()
if (!keyword || !isBlankString(formData.hospitalId)) return false
try {
const res = await fetchSearchCollectionHospitals({ keyword, limit: 20 })
const list = res.list || []
const match =
list.find((h) => h.hospitalName === keyword) ||
list.find((h) => (h.hospitalName || '').includes(keyword)) ||
list[0]
if (!match) return false
const regionStub: Api.BizCollectionRegion.RegionItem = {
id: match.regionId,
regionName: match.regionName || match.regionId,
hospitalNames: [],
tenantNo: match.tenantNo || '',
orderNum: 0,
remark: '',
createTime: '',
updateTime: ''
}
if (!regionOptions.value.some((r) => r.id === match.regionId)) {
regionOptions.value = [regionStub, ...regionOptions.value]
}
formData.regionId = match.regionId
await loadHospitalsByRegion(match.regionId, keyword)
if (!hospitalOptions.value.some((h) => h.id === match.id)) {
hospitalOptions.value = [match, ...hospitalOptions.value]
}
formData.hospitalId = match.id
return true
} catch {
return false
}
}
async function applySalesUserByName(name: string): Promise<boolean> {
const keyword = (name || '').trim()
if (!keyword) return false
try {
const res = await fetchUserList({
page: 1,
pageSize: 50,
keyword,
status: '1'
})
const list = res.list || []
const match =
list.find((u) => u.nickName === keyword) ||
list.find((u) => (u.nickName || '').includes(keyword))
if (!match) return false
applyUserToCollector(match)
applyUserToSales(match)
return true
} catch {
return false
}
}
function applyUserToCollector(u: Api.User.UserItem) {
collectorSnapshot.value = { ...u }
collectorUserId.value = u.id
formData.collectorUserId = u.id
if (!collectorUserOptions.value.some((x) => x.id === u.id)) {
collectorUserOptions.value = [u, ...collectorUserOptions.value]
}
}
function applyUserToSales(u: Api.User.UserItem) {
salesSnapshot.value = { ...u }
salesUserId.value = u.id
formData.salesUserId = u.id
if (!salesUserOptions.value.some((x) => x.id === u.id)) {
salesUserOptions.value = [u, ...salesUserOptions.value]
}
}
async function resolveSampleCodeByCode(code: string) {
const keyword = (code || '').trim()
if (!keyword) return null
const res = await fetchSampleCodeList({ page: 1, pageSize: 50, keyword })
const list = (res.list || []) as Api.BizSampleCode.SampleCodeItem[]
return (
list.find((sc) => sc.sampleCode === keyword) ||
list.find((sc) => String(sc.sampleCode || '').includes(keyword)) ||
null
)
}
function applyParsedTransportToSample(
sample: Record<string, any>,
parsed: ProtocolStandardImportParsed,
warnings: string[],
filledLabels: string[]
) {
if (!parsed.transportType) return
const transport = { ...(sample.transport || createEmptyTransport()) }
let transportFilled = false
if (isBlankString(transport.transportType)) {
transport.transportType = parsed.transportType
transportFilled = true
}
if (isBlankString(transport.destSiteId) && siteOptions.value.length) {
const site = siteOptions.value[0]
transport.destSiteId = site.id
transportFilled = true
}
if (parsed.etaTime && isBlankString(transport.etaTime)) {
transport.etaTime = parsed.etaTime
transportFilled = true
} else if (isBlankString(transport.etaTime)) {
transport.etaTime = formatNowDatetime()
transportFilled = true
}
if (parsed.transportType === 'kdys' && isBlankString(transport.expressCompanyId)) {
const ec = matchExpressCompany(
parsed.transportModeText || '顺丰快递',
expressCompanyOptions.value
)
if (ec) {
transport.expressCompanyId = ec.id
if (!expressCompanyOptions.value.some((x) => x.id === ec.id)) {
expressCompanyOptions.value = [ec, ...expressCompanyOptions.value]
}
transportFilled = true
} else {
warnings.push(`未找到快递公司「${parsed.transportModeText || ''}」`)
}
}
if (parsed.transportType === 'ryxd' && parsed.carrierName && isBlankString(transport.carrierName)) {
transport.carrierName = parsed.carrierName
transportFilled = true
}
sample.transport = transport
if (transportFilled) filledLabels.push('运输信息')
}
async function applySampleHintsFromImport(
parsed: ProtocolStandardImportParsed,
warnings: string[],
filledLabels: string[]
) {
let hints = parsed.sampleHints
if (!hints.length) {
const matched = matchCellSampleType(parsed.sampleTypeHeader, sampleTypeOptions.value)
if (matched) {
hints = [{ typeKey: 'hsc', typeName: matched.typeName }]
}
}
for (const hint of hints) {
const matchedType = matchSampleTypeByExactName(hint.typeName, sampleTypeOptions.value)
const sample = normalizeSampleRow({ sampleTypeId: '', sampleStatus: 'ycj' }, formData.samples.length)
formData.samples.push(sample)
if (matchedType) {
sample.sampleTypeId = matchedType.id
sample.storageYears = matchedType.storageYears ?? null
sample.originalPrice = matchedType.storagePrice ?? null
sample.price = matchedType.storagePrice ?? null
if (!sampleTypeOptions.value.some((x) => x.id === matchedType.id)) {
sampleTypeOptions.value = [matchedType, ...sampleTypeOptions.value]
}
filledLabels.push(hint.typeName)
} else {
warnings.push(`无法匹配样本类型「${hint.typeName}」`)
}
if (hint.sampleCode) {
const sc = await resolveSampleCodeByCode(hint.sampleCode)
if (sc) {
sample.sampleCodeId = sc.id
sample.sampleCode = sc.sampleCode
if (!sampleCodeOptions.value.some((x) => x.id === sc.id)) {
sampleCodeOptions.value = [sc, ...sampleCodeOptions.value]
}
filledLabels.push('样本编码')
} else {
warnings.push(`未找到样本编码「${hint.sampleCode}」`)
}
}
applyParsedTransportToSample(sample, parsed, warnings, filledLabels)
}
}
function syncFormSamplesAfterImport() {
formData.samples = formData.samples.map((s, i) =>
normalizeSampleRow(
{
...s,
transport: s.transport ? { ...s.transport } : undefined
},
i
)
)
hydrateSampleLookupOptions()
}
function applyPaymentFromImport(parsed: ProtocolStandardImportParsed, warnings: string[]) {
formData.payMode = parsed.payMode || 'dj'
lastConfirmedPayMode.value = formData.payMode as PayMode
if (parsed.payMode === 'fq') {
applyFqPaymentDefaults()
}
if (parsed.contractAmount != null) {
formData.contractAmount = parsed.contractAmount
}
const transferTypeCode = resolveTransferTypeCode(
parsed.transferTypeLabel || '',
transferTypeOptions.value
)
if (parsed.transferTypeLabel && !transferTypeCode) {
warnings.push(`无法匹配转账方式「${parsed.transferTypeLabel}」`)
}
const now = new Date()
const pad = (n: number) => String(n).padStart(2, '0')
const defaultTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
formData.paymentDetails = []
const transfers = parsed.paymentTransfers.filter((t) => t.transferAmount > 0)
if (transfers.length) {
transfers.forEach((t, i) => {
formData.paymentDetails.push({
transferType: transferTypeCode,
dueAmount: t.transferAmount,
transferAmount: t.transferAmount,
transferTime: t.transferTime || defaultTime,
payStatus: 'dfj',
installmentDueDate: formData.payMode === 'dj' ? formData.lumpSumDeadline : '',
_expanded: i === 0,
attachments: []
})
})
} else if (formData.payMode === 'dj' && formData.contractAmount != null) {
addPaymentDetail()
const detail = formData.paymentDetails[0]
if (detail) {
detail.transferType = transferTypeCode
detail.dueAmount = formData.contractAmount
detail.transferAmount = formData.contractAmount
}
}
initPaymentDetailExpandFlags(formData.paymentDetails)
markPayDetailLocks(formData.paymentDetails)
if (!transfers.length && !(formData.payMode === 'dj' && formData.contractAmount != null)) {
syncPaymentDueAmounts()
}
if (parsed.contractAmount != null && transfers.length) {
const sum = transfers.reduce((acc, t) => acc + Number(t.transferAmount || 0), 0)
if (Math.abs(sum - Number(parsed.contractAmount)) > 0.01) {
warnings.push(
`转账合计 ${sum} 与合同金额 ${parsed.contractAmount} 不一致,请核对缴费明细`
)
}
}
}
async function handleStandardImport() {
const parsed = parseProtocolStandardImportText(standardImportText.value)
if (!parsed) {
ElMessage.warning('请粘贴有效的标准信息')
return
}
standardImportLoading.value = true
const warnings: string[] = []
const filledLabels: string[] = []
try {
clearFormBeforeStandardImport()
await ensureTransferTypeOptions()
await remoteSearchSampleTypes('')
const tasks: Promise<void>[] = []
if (parsed.motherName) {
tasks.push(
applyMotherByName(parsed.motherName).then((result) => {
if (result === 'linked') filledLabels.push('母亲信息(已关联客户)')
else if (result === 'name-only') filledLabels.push('母亲姓名')
})
)
}
if (parsed.hospitalName) {
tasks.push(
applyHospitalByName(parsed.hospitalName).then((ok) => {
if (ok) filledLabels.push('采集地区/采集医院')
else if (isBlankString(formData.hospitalId)) {
warnings.push(`未找到采集医院「${parsed.hospitalName}」`)
}
})
)
}
if (parsed.salesUserName) {
tasks.push(
applySalesUserByName(parsed.salesUserName).then((ok) => {
if (ok) filledLabels.push('采集专员/销售人员')
else warnings.push(`未找到销售人员「${parsed.salesUserName}」`)
})
)
}
const needsTransport = !!parsed.transportType
if (needsTransport) {
tasks.push(remoteSearchSites('').then(() => undefined))
if (parsed.transportType === 'kdys') {
tasks.push(
remoteSearchExpressCompanies(
(parsed.transportModeText || '').replace(/快递$/, '') || '顺丰'
).then(() => undefined)
)
}
}
await Promise.all(tasks)
if (parsed.motherPhone) {
formData.motherPhone = parsed.motherPhone
filledLabels.push('孕妇电话')
}
if (parsed.newbornSex) {
formData.newbornSex = parsed.newbornSex
filledLabels.push('新生儿性别')
}
if (parsed.newbornWeightGram != null) {
formData.newbornWeightGram = parsed.newbornWeightGram
filledLabels.push('新生儿体重')
}
if (parsed.apgarScore != null) {
formData.apgar1min = parsed.apgarScore
filledLabels.push('新生儿评分')
}
if (parsed.newbornDeliveryTime) {
formData.newbornDeliveryTime = parsed.newbornDeliveryTime
filledLabels.push('新生儿分娩时间')
}
if (parsed.sampleCollectTime) {
formData.sampleCollectTime = formatDatetimeToMinute(parsed.sampleCollectTime)
filledLabels.push('样本采集时间')
}
if (parsed.maternalBloodExplicitEmpty) {
formData.maternalBloodCollectTime = ''
filledLabels.push('母血采集时间')
} else if (parsed.maternalBloodCollectTime) {
formData.maternalBloodCollectTime = formatDatetimeToMinute(parsed.maternalBloodCollectTime)
filledLabels.push('母血采集时间')
}
if (parsed.deliveryMode) {
formData.deliveryMode = parsed.deliveryMode
filledLabels.push('分娩方式')
}
if (parsed.birthOrder != null) {
formData.birthOrder = parsed.birthOrder
filledLabels.push('胎次')
}
if (parsed.medicalStaff) {
formData.medicalStaff = parsed.medicalStaff
filledLabels.push('采集医护')
}
if (parsed.remark) {
formData.remark = parsed.remark
filledLabels.push('备注')
}
await applySampleHintsFromImport(parsed, warnings, filledLabels)
if (formData.samples.length) {
syncFormSamplesAfterImport()
}
applyPaymentFromImport(parsed, warnings)
if (parsed.contractAmount != null) {
filledLabels.push('合同金额')
const sampleTotal = formData.samples.reduce(
(sum, s) => sum + (Number(s.price) || 0),
0
)
if (sampleTotal > 0 && Math.abs(sampleTotal - Number(parsed.contractAmount)) > 0.01) {
warnings.push(
`样本优惠价合计 ${sampleTotal} 与合同金额 ${parsed.contractAmount} 不一致,请核对样本价格`
)
}
}
if (parsed.transportModeText && !parsed.transportType) {
warnings.push(`无法识别运输方式「${parsed.transportModeText}」`)
}
const uniqueFilled = [...new Set(filledLabels)]
if (uniqueFilled.length) {
ElMessage.success(`已填充:${uniqueFilled.join('、')}`)
} else if (!warnings.length) {
ElMessage.info('没有可填充的字段')
}
if (warnings.length) {
ElMessage.warning(warnings.join(';'))
}
} catch {
ElMessage.error('导入失败,请检查标准信息格式')
} finally {
standardImportLoading.value = false
}
}
/* ====== 客户检索(母亲信息) ====== */
function formatCustomerLabel(c: { customerName: string; phoneNo: string; idCardNo: string }) {
const parts = [c.customerName || '']
@@ -2554,6 +3117,20 @@
handleFqParamsChange()
}
/** 缴费明细应缴金额变更:分期模式下回写分期金额,保持与主表一致 */
function onPaymentDetailDueAmountChange(dIdx: number) {
if (formData.payMode !== 'fq') return
const detail = formData.paymentDetails[dIdx]
if (!detail || isPayDetailLocked(detail)) return
const installmentNo = Number(detail.installmentNo)
const ratioIdx = installmentNo >= 1 ? installmentNo - 1 : dIdx
if (!formData.installmentRatios) formData.installmentRatios = []
while (formData.installmentRatios.length <= ratioIdx) {
formData.installmentRatios.push(0)
}
formData.installmentRatios[ratioIdx] = Number(detail.dueAmount) || 0
}
const installmentAmountsError = computed(() => {
const amounts = formData.installmentRatios || []
if (!amounts.length || formData.contractAmount == null) return ''
@@ -2867,6 +3444,29 @@
&--green {
background: #f0fdf4;
}
&--import {
margin-bottom: 0;
}
}
.import-actions {
display: flex;
justify-content: flex-end;
padding: 0 0 8px;
}
.form-tab-pane--import-basic {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 16px;
align-items: stretch;
margin-bottom: 28px;
.section-card {
margin-bottom: 0;
height: 100%;
}
}
.section-title {
@@ -3318,6 +3918,10 @@
RESPONSIVE
═══════════════════════════════════════════ */
@media (max-width: 900px) {
.form-tab-pane--import-basic {
grid-template-columns: 1fr;
}
.form-grid {
grid-template-columns: repeat(2, 1fr);
@@ -97,7 +97,7 @@
<el-dropdown-item v-if="hasPrimaryTaskActions(row)" command="view">
<el-icon><View /></el-icon>查看
</el-dropdown-item>
<el-dropdown-item v-if="canDeleteTask(row)" command="delete" divided>
<el-dropdown-item command="delete" divided>
<el-icon><Delete /></el-icon>删除
</el-dropdown-item>
</el-dropdown-menu>
@@ -763,17 +763,9 @@
return base
}
/** 待执行时可删除(仅工单管理视图) */
function canDeleteTask(row: QcTask) {
return listMode.value === 'workOrder' && row.taskStatus === 'dzx'
}
/** 更多菜单是否展示 */
function hasMoreTaskActions(row: QcTask) {
if (hasPrimaryTaskActions(row)) {
return true
}
return canDeleteTask(row)
/** 更多菜单是否展示(删除始终可用,故始终展示) */
function hasMoreTaskActions(_row: QcTask) {
return true
}
function handleDropdownCommand(command: string, row: QcTask) {
@@ -719,9 +719,11 @@
import {
parseDonationStandardImportText,
matchCellSampleType,
matchSampleTypeByExactName,
matchExpressCompany,
isBlankString,
isEmptyNumber
isEmptyNumber,
type DonationStandardImportParsed
} from '@/utils/donation-standard-import-parse'
import {
fetchCustomerList,
@@ -1987,6 +1989,152 @@
}
}
/** 一键导入前清空上次导入/手填的可覆盖字段(保留捐赠状态、日期、附件等) */
function clearFormBeforeStandardImport() {
customerId.value = null
customerSnapshot.value = null
formData.customerId = ''
formData.motherName = ''
formData.motherPhone = ''
formData.motherIdCard = ''
formData.motherBirthYm = ''
formData.motherEmail = ''
formData.motherAddress = ''
formData.newbornSex = ''
formData.newbornWeightGram = null
formData.apgar1min = null
formData.apgar5min = null
formData.newbornDeliveryTime = ''
formData.deliveryMode = ''
formData.birthOrder = null
formData.regionId = ''
formData.hospitalId = ''
formData.medicalStaff = ''
formData.sampleCollectTime = ''
formData.maternalBloodCollectTime = ''
collectorUserId.value = null
collectorSnapshot.value = null
collectorUserOptions.value = []
formData.collectorUserId = ''
salesUserId.value = null
salesSnapshot.value = null
salesUserOptions.value = []
formData.salesUserId = ''
formData.samples = []
sampleCodeOptions.value = []
}
function applyParsedTransportToSample(
sample: Record<string, any>,
parsed: DonationStandardImportParsed,
warnings: string[],
filledLabels: string[]
) {
if (!parsed.transportType) return
const transport = { ...(sample.transport || createEmptyTransport()) }
let transportFilled = false
if (isBlankString(transport.transportType)) {
transport.transportType = parsed.transportType
transportFilled = true
}
if (isBlankString(transport.destSiteId) && siteOptions.value.length) {
const site = siteOptions.value[0]
transport.destSiteId = site.id
transport.destSiteName = site.siteName || ''
transportFilled = true
}
if (isBlankString(transport.etaTime)) {
transport.etaTime = formatNowDatetime()
transportFilled = true
}
if (parsed.transportType === 'kdys' && isBlankString(transport.expressCompanyId)) {
const ec = matchExpressCompany(
parsed.transportModeText || '顺丰快递',
expressCompanyOptions.value
)
if (ec) {
transport.expressCompanyId = ec.id
if (!expressCompanyOptions.value.some((x) => x.id === ec.id)) {
expressCompanyOptions.value = [ec, ...expressCompanyOptions.value]
}
transportFilled = true
} else {
warnings.push(`未找到快递公司「${parsed.transportModeText || ''}」`)
}
}
sample.transport = transport
if (transportFilled) filledLabels.push('运输信息')
}
async function applySampleHintsFromImport(
parsed: DonationStandardImportParsed,
warnings: string[],
filledLabels: string[]
) {
for (const hint of parsed.sampleHints) {
const matchedType = matchSampleTypeByExactName(hint.typeName, sampleTypeOptions.value)
let sample = matchedType
? formData.samples.find((s) => s.sampleTypeId === matchedType.id)
: undefined
if (!sample) {
sample = formData.samples.find((s) => isBlankString(s.sampleTypeId))
}
if (!sample) {
sample = normalizeSampleRow({ sampleTypeId: '', sampleStatus: 'ycj' })
formData.samples.push(sample)
}
if (matchedType && isBlankString(sample.sampleTypeId)) {
sample.sampleTypeId = matchedType.id
sample.storageYears = matchedType.storageYears ?? null
if (!sampleTypeOptions.value.some((x) => x.id === matchedType.id)) {
sampleTypeOptions.value = [matchedType, ...sampleTypeOptions.value]
}
filledLabels.push(hint.typeName)
} else if (!matchedType && isBlankString(sample.sampleTypeId)) {
warnings.push(`无法匹配样本类型「${hint.typeName}」`)
}
try {
await assignDonationSampleCodeIfMissing(sample)
if (String(sample.sampleCode || '').trim()) {
filledLabels.push('样本编码')
}
} catch {
warnings.push('样本编码自动生成失败')
}
applyParsedTransportToSample(sample, parsed, warnings, filledLabels)
}
}
/** 导入后重建样本行引用,确保样本及运输列表列刷新(与编辑样本弹窗确定逻辑一致) */
function syncFormSamplesAfterImport() {
formData.samples = formData.samples.map((s) => {
const row = normalizeSampleRow({
...s,
transport: s.transport ? { ...s.transport } : undefined
})
const destSiteId = String(row.transport?.destSiteId || '')
if (destSiteId && isBlankString(row.transport?.destSiteName)) {
const site = siteOptions.value.find((x) => x.id === destSiteId)
if (site?.siteName && site.siteName !== site.id) {
row.transport.destSiteName = site.siteName
}
}
return row
})
hydrateSampleLookupOptions()
}
async function handleStandardImport() {
const parsed = parseDonationStandardImportText(standardImportText.value)
if (!parsed) {
@@ -1999,6 +2147,7 @@
const filledLabels: string[] = []
try {
clearFormBeforeStandardImport()
await remoteSearchSampleTypes('')
const tasks: Promise<void>[] = []
@@ -2032,14 +2181,16 @@
)
}
const needsTransport = !!parsed.transportExpressName
const needsTransport = !!parsed.transportType
if (needsTransport) {
tasks.push(
remoteSearchSites('').then(() => undefined),
remoteSearchExpressCompanies(
(parsed.transportExpressName || '').replace(/快递$/, '') || '顺丰'
).then(() => undefined)
)
tasks.push(remoteSearchSites('').then(() => undefined))
if (parsed.transportType === 'kdys') {
tasks.push(
remoteSearchExpressCompanies(
(parsed.transportModeText || '').replace(/快递$/, '') || '顺丰'
).then(() => undefined)
)
}
}
await Promise.all(tasks)
@@ -2087,78 +2238,62 @@
filledLabels.push('采集医护')
}
const matchedType = matchCellSampleType(parsed.sampleTypeHeader, sampleTypeOptions.value)
const needsSampleRow = !!matchedType || needsTransport
if (parsed.sampleHints.length > 0) {
await applySampleHintsFromImport(parsed, warnings, filledLabels)
} else {
const matchedType = matchCellSampleType(parsed.sampleTypeHeader, sampleTypeOptions.value)
const needsSampleRow = !!matchedType || needsTransport
if (needsSampleRow) {
if (!formData.samples.length) {
formData.samples = [normalizeSampleRow({ sampleTypeId: '', sampleStatus: 'ycj' })]
}
const sample = formData.samples[0]
if (needsSampleRow) {
if (!formData.samples.length) {
formData.samples = [normalizeSampleRow({ sampleTypeId: '', sampleStatus: 'ycj' })]
}
const sample = formData.samples[0]
if (matchedType && isBlankString(sample.sampleTypeId)) {
sample.sampleTypeId = matchedType.id
sample.storageYears = matchedType.storageYears ?? null
if (!sampleTypeOptions.value.some((x) => x.id === matchedType.id)) {
sampleTypeOptions.value = [matchedType, ...sampleTypeOptions.value]
}
filledLabels.push('样本类型')
} else if (parsed.sampleTypeHeader && !matchedType && isBlankString(sample.sampleTypeId)) {
warnings.push(`无法匹配样本类型「${parsed.sampleTypeHeader}」`)
}
if (needsTransport) {
const transport = { ...(sample.transport || createEmptyTransport()) }
let transportFilled = false
if (isBlankString(transport.transportType)) {
transport.transportType = 'kdys'
transportFilled = true
}
if (isBlankString(transport.destSiteId) && siteOptions.value.length) {
transport.destSiteId = siteOptions.value[0].id
transportFilled = true
}
if (isBlankString(transport.etaTime)) {
transport.etaTime = formatNowDatetime()
transportFilled = true
}
if (isBlankString(transport.expressCompanyId)) {
const ec = matchExpressCompany(
parsed.transportExpressName || '顺丰快递',
expressCompanyOptions.value
)
if (ec) {
transport.expressCompanyId = ec.id
if (!expressCompanyOptions.value.some((x) => x.id === ec.id)) {
expressCompanyOptions.value = [ec, ...expressCompanyOptions.value]
}
transportFilled = true
} else {
warnings.push(`未找到快递公司「${parsed.transportExpressName}」`)
if (matchedType && isBlankString(sample.sampleTypeId)) {
sample.sampleTypeId = matchedType.id
sample.storageYears = matchedType.storageYears ?? null
if (!sampleTypeOptions.value.some((x) => x.id === matchedType.id)) {
sampleTypeOptions.value = [matchedType, ...sampleTypeOptions.value]
}
filledLabels.push('样本类型')
} else if (
parsed.sampleTypeHeader &&
!matchedType &&
isBlankString(sample.sampleTypeId)
) {
warnings.push(`无法匹配样本类型「${parsed.sampleTypeHeader}」`)
}
sample.transport = transport
if (transportFilled) filledLabels.push('运输信息')
}
try {
await assignDonationSampleCodeIfMissing(sample)
if (String(sample.sampleCode || '').trim()) {
filledLabels.push('样本编码')
if (needsTransport) {
applyParsedTransportToSample(sample, parsed, warnings, filledLabels)
}
} catch {
warnings.push('样本编码自动生成失败')
}
hydrateSampleLookupOptions()
} else if (parsed.sampleTypeHeader) {
const sample = formData.samples[0]
const matched = matchCellSampleType(parsed.sampleTypeHeader, sampleTypeOptions.value)
if (!matched && (!sample || isBlankString(sample.sampleTypeId))) {
warnings.push(`无法匹配样本类型「${parsed.sampleTypeHeader}」`)
try {
await assignDonationSampleCodeIfMissing(sample)
if (String(sample.sampleCode || '').trim()) {
filledLabels.push('样本编码')
}
} catch {
warnings.push('样本编码自动生成失败')
}
} else if (parsed.sampleTypeHeader) {
const sample = formData.samples[0]
const matched = matchCellSampleType(parsed.sampleTypeHeader, sampleTypeOptions.value)
if (!matched && (!sample || isBlankString(sample.sampleTypeId))) {
warnings.push(`无法匹配样本类型「${parsed.sampleTypeHeader}」`)
}
}
}
if (formData.samples.length) {
syncFormSamplesAfterImport()
}
if (parsed.transportModeText && !parsed.transportType) {
warnings.push(`无法识别运输方式「${parsed.transportModeText}」`)
}
const uniqueFilled = [...new Set(filledLabels)]
if (uniqueFilled.length) {
ElMessage.success(`已填充:${uniqueFilled.join('、')}`)