提交
This commit is contained in:
1 parent
dd1acdc787
commit
4222eaa593
47 files changed
+1054350
-9663
No files matched your search
@@ -231,13 +231,13 @@
|
||||
"229": "useClientColumnFilters.ts",
|
||||
"230": "syncStatsColumnWidths",
|
||||
"231": "index.vue",
|
||||
"232": "handleExportPdf",
|
||||
"232": "price-letter.ts",
|
||||
"233": "Community 233",
|
||||
"234": "Community 234",
|
||||
"235": "index.js",
|
||||
"236": "pl-plan-contract-display.ts",
|
||||
"236": "loadData",
|
||||
"237": "DbPoundSlipQrcodeDialog.vue",
|
||||
"238": "error-handle.ts",
|
||||
"238": "formatYmd",
|
||||
"239": "Community 239",
|
||||
"240": "detail.vue",
|
||||
"241": "index.vue",
|
||||
@@ -248,33 +248,32 @@
|
||||
"246": "fetchData",
|
||||
"247": "Community 247",
|
||||
"248": "Community 248",
|
||||
"249": "syncStatsColumnWidths",
|
||||
"249": "index.vue",
|
||||
"250": "handleAdd",
|
||||
"251": "handleDisburse",
|
||||
"252": "index.js",
|
||||
"253": "Community 253",
|
||||
"254": "price-letter.ts",
|
||||
"254": "loading.ts",
|
||||
"255": "Community 255",
|
||||
"256": "index.vue",
|
||||
"256": "zh_CN.js",
|
||||
"257": "index.vue",
|
||||
"258": "loadUserOptions",
|
||||
"258": "index.vue",
|
||||
"259": "Community 259",
|
||||
"260": "Community 260",
|
||||
"261": "Community 261",
|
||||
"262": "index.vue",
|
||||
"263": "canDeleteByCreator",
|
||||
"262": "ensurePlanReadyForArrange",
|
||||
"263": "handleSearch",
|
||||
"264": "index.js",
|
||||
"265": "Community 265",
|
||||
"266": "fastEnter.ts",
|
||||
"266": "form.vue",
|
||||
"267": "index.vue",
|
||||
"268": "zh_CN.js",
|
||||
"269": "Community 269",
|
||||
"270": "Community 270",
|
||||
"271": "canBatchPrintSlip",
|
||||
"272": "index.vue",
|
||||
"273": "handleSearch",
|
||||
"274": "loadUserOptions",
|
||||
"276": "zh_CN.js",
|
||||
"272": "zh_CN.js",
|
||||
"275": "index.js",
|
||||
"278": "v2.4.2.1 - 2025-06-16",
|
||||
"280": "Community 280",
|
||||
"283": "Community 283",
|
||||
"284": "Community 284",
|
||||
@@ -515,7 +514,6 @@
|
||||
"1199": "index.js",
|
||||
"1200": "index.js",
|
||||
"1201": "index.js",
|
||||
"1202": "index.js",
|
||||
"1204": "plugin.js",
|
||||
"1205": "plugin.min.js",
|
||||
"1206": "index.js",
|
||||
@@ -593,7 +591,6 @@
|
||||
"1292": "index.js",
|
||||
"1293": "plugin.js",
|
||||
"1294": "plugin.min.js",
|
||||
"1295": "index.js",
|
||||
"1297": "plugin.js",
|
||||
"1298": "plugin.min.js",
|
||||
"1299": "content.js",
|
||||
|
||||
@@ -0,0 +1,828 @@
|
||||
{
|
||||
"0": "Community 0",
|
||||
"1": "Community 1",
|
||||
"2": "Community 2",
|
||||
"3": "Community 3",
|
||||
"4": "Community 4",
|
||||
"5": "Community 5",
|
||||
"6": "Community 6",
|
||||
"7": "Community 7",
|
||||
"8": "Community 8",
|
||||
"9": "Community 9",
|
||||
"10": "Community 10",
|
||||
"11": "Community 11",
|
||||
"12": "Community 12",
|
||||
"13": "Community 13",
|
||||
"14": "Community 14",
|
||||
"15": "Community 15",
|
||||
"16": "Community 16",
|
||||
"17": "Ha",
|
||||
"18": "Community 18",
|
||||
"19": "Community 19",
|
||||
"20": "Community 20",
|
||||
"21": "Community 21",
|
||||
"22": "Community 22",
|
||||
"23": "Community 23",
|
||||
"24": "Community 24",
|
||||
"25": "Community 25",
|
||||
"26": "theme.min.js",
|
||||
"27": "Community 27",
|
||||
"28": "useCommon",
|
||||
"29": "Community 29",
|
||||
"30": "loader.ts",
|
||||
"31": "RenewDialog.vue",
|
||||
"32": "index.vue",
|
||||
"33": "Community 33",
|
||||
"34": "main.ts",
|
||||
"35": "Community 35",
|
||||
"36": "VoidDialog.vue",
|
||||
"37": "pl-batch-print.ts",
|
||||
"38": "view-fields.ts",
|
||||
"39": "Community 39",
|
||||
"40": "Community 40",
|
||||
"41": "colors.ts",
|
||||
"42": "Community 42",
|
||||
"43": "Community 43",
|
||||
"44": "Community 44",
|
||||
"45": "Community 45",
|
||||
"46": "Community 46",
|
||||
"47": "fetchCustomerDetail",
|
||||
"48": "Community 48",
|
||||
"49": "Community 49",
|
||||
"50": "Community 50",
|
||||
"51": "price-letter-template.ts",
|
||||
"52": "Community 52",
|
||||
"53": "Community 53",
|
||||
"54": "Community 54",
|
||||
"55": "Community 55",
|
||||
"56": "Community 56",
|
||||
"57": "Community 57",
|
||||
"58": "Community 58",
|
||||
"59": "fetchData",
|
||||
"60": "index.vue",
|
||||
"61": "Community 61",
|
||||
"62": "highlight.ts",
|
||||
"63": "price-letter.ts",
|
||||
"64": "Community 64",
|
||||
"65": "detail.vue",
|
||||
"66": "Community 66",
|
||||
"67": "index.vue",
|
||||
"68": "Community 68",
|
||||
"69": "Community 69",
|
||||
"70": "Community 70",
|
||||
"71": "Community 71",
|
||||
"72": "Community 72",
|
||||
"73": "Community 73",
|
||||
"74": "Community 74",
|
||||
"75": "openEdit",
|
||||
"76": "handleSearch",
|
||||
"77": "loadUserOptions",
|
||||
"78": "customerPool.ts",
|
||||
"79": "Community 79",
|
||||
"80": "product.ts",
|
||||
"81": "Community 81",
|
||||
"82": "Community 82",
|
||||
"83": "useDictStore",
|
||||
"84": "Community 84",
|
||||
"85": "index.vue",
|
||||
"86": "Community 86",
|
||||
"87": "canDeleteByCreator",
|
||||
"88": "index.vue",
|
||||
"89": "detail.vue",
|
||||
"90": "theme.min.js",
|
||||
"91": "Community 91",
|
||||
"92": "Community 92",
|
||||
"93": "ArtUserMenu.vue",
|
||||
"94": "formatYmd",
|
||||
"95": "Community 95",
|
||||
"96": "Community 96",
|
||||
"97": "stringifyBody",
|
||||
"98": "index.vue",
|
||||
"99": "stringifyBody",
|
||||
"100": "v2.4.2.1 - 2025-06-16",
|
||||
"101": "price-letter.ts",
|
||||
"102": "price-letter-template.ts",
|
||||
"103": "SettingDrawer.vue",
|
||||
"104": "contractType.ts",
|
||||
"105": "index.vue",
|
||||
"106": "Community 106",
|
||||
"107": "Community 107",
|
||||
"108": "Community 108",
|
||||
"109": "Community 109",
|
||||
"110": "Community 110",
|
||||
"111": "format.ts",
|
||||
"112": "inventory.ts",
|
||||
"113": "Community 113",
|
||||
"114": "index.vue",
|
||||
"115": "useDictStore",
|
||||
"116": "Community 116",
|
||||
"117": "Community 117",
|
||||
"118": "zh_CN.js",
|
||||
"119": "Community 119",
|
||||
"120": "Community 120",
|
||||
"121": "chart.ts",
|
||||
"122": "handleDisburse",
|
||||
"123": "detail.vue",
|
||||
"124": "index.vue",
|
||||
"125": "Community 125",
|
||||
"126": "Community 126",
|
||||
"127": "selectContractRow",
|
||||
"128": "Community 128",
|
||||
"129": "Community 129",
|
||||
"130": "system.ts",
|
||||
"131": "index.vue",
|
||||
"132": "Community 132",
|
||||
"133": "Community 133",
|
||||
"134": "index.vue",
|
||||
"135": "detail.vue",
|
||||
"136": "Community 136",
|
||||
"137": "Community 137",
|
||||
"138": "FollowDialog.vue",
|
||||
"139": "RenewDialog.vue",
|
||||
"140": "Community 140",
|
||||
"141": "Community 141",
|
||||
"142": "Community 142",
|
||||
"143": "index.js",
|
||||
"144": "Community 144",
|
||||
"145": "api",
|
||||
"146": "price-letter-template.ts",
|
||||
"147": "index.vue",
|
||||
"148": "Community 148",
|
||||
"149": "fetchCustomerDetail",
|
||||
"150": "Community 150",
|
||||
"151": "Community 151",
|
||||
"152": "SettingDrawer.vue",
|
||||
"153": "index.vue",
|
||||
"154": "index.vue",
|
||||
"155": "error.ts",
|
||||
"156": "v2.4.2.1 - 2025-06-16",
|
||||
"157": "form.vue",
|
||||
"158": "removeProductsNotAllowedByHazard",
|
||||
"159": "detail.vue",
|
||||
"160": "index.vue",
|
||||
"161": "Community 161",
|
||||
"162": "Community 162",
|
||||
"163": "system.ts",
|
||||
"164": "Community 164",
|
||||
"165": "handleDisburse",
|
||||
"166": "Community 166",
|
||||
"167": "Community 167",
|
||||
"168": "crypto.ts",
|
||||
"169": "Community 169",
|
||||
"170": "Community 170",
|
||||
"171": "index.vue",
|
||||
"172": "index.js",
|
||||
"173": "index.vue",
|
||||
"174": "Community 174",
|
||||
"175": "handleEdit",
|
||||
"176": "fetchData",
|
||||
"177": "fetchCustomerDetail",
|
||||
"178": "Community 178",
|
||||
"179": "Community 179",
|
||||
"180": "index.vue",
|
||||
"181": "Community 181",
|
||||
"182": "Community 182",
|
||||
"183": "Ha",
|
||||
"184": "highlight.ts",
|
||||
"185": "handleConfirmApproval",
|
||||
"186": "StorageKeyManager",
|
||||
"187": "Community 187",
|
||||
"188": "Community 188",
|
||||
"189": "Community 189",
|
||||
"190": "error-handle.ts",
|
||||
"191": "formatYmd",
|
||||
"192": "prepareLineAliasAndBrandForSubmit",
|
||||
"193": "crm-product-display.ts",
|
||||
"194": "index.ts",
|
||||
"195": "Community 195",
|
||||
"196": "Community 196",
|
||||
"197": "v2.4.2.1 - 2025-06-16",
|
||||
"198": "fetchRoleOptions",
|
||||
"199": "colors.ts",
|
||||
"200": "index.js",
|
||||
"201": "Ha",
|
||||
"202": "Community 202",
|
||||
"203": "customerPool.ts",
|
||||
"204": "DbCrmCustomerSelect.vue",
|
||||
"205": "loadDefaultCustomerOptions",
|
||||
"206": "onDrop",
|
||||
"207": "SettingDrawer.vue",
|
||||
"208": "index.vue",
|
||||
"209": "Community 209",
|
||||
"210": "Community 210",
|
||||
"211": "loadUserOptions",
|
||||
"212": "index.js",
|
||||
"213": "Community 213",
|
||||
"214": "Community 214",
|
||||
"215": "SettingActions.vue",
|
||||
"216": "VoidDialog.vue",
|
||||
"217": "index.js",
|
||||
"218": "index.js",
|
||||
"219": "applyBrandSelectChange",
|
||||
"220": "detail.vue",
|
||||
"221": "index.js",
|
||||
"222": "index.vue",
|
||||
"223": "Community 223",
|
||||
"224": "Community 224",
|
||||
"225": "theme.min.js",
|
||||
"226": "api",
|
||||
"227": "Community 227",
|
||||
"228": "Community 228",
|
||||
"229": "useClientColumnFilters.ts",
|
||||
"230": "syncStatsColumnWidths",
|
||||
"231": "index.vue",
|
||||
"232": "price-letter.ts",
|
||||
"233": "Community 233",
|
||||
"234": "Community 234",
|
||||
"235": "index.js",
|
||||
"236": "loadData",
|
||||
"237": "DbPoundSlipQrcodeDialog.vue",
|
||||
"238": "formatYmd",
|
||||
"239": "Community 239",
|
||||
"240": "detail.vue",
|
||||
"241": "index.vue",
|
||||
"242": "Community 242",
|
||||
"243": "Community 243",
|
||||
"244": "loadUserOptions",
|
||||
"245": "index.js",
|
||||
"246": "fetchData",
|
||||
"247": "Community 247",
|
||||
"248": "Community 248",
|
||||
"249": "index.vue",
|
||||
"250": "handleAdd",
|
||||
"251": "handleDisburse",
|
||||
"252": "index.js",
|
||||
"253": "Community 253",
|
||||
"254": "loading.ts",
|
||||
"255": "Community 255",
|
||||
"257": "index.vue",
|
||||
"259": "Community 259",
|
||||
"260": "Community 260",
|
||||
"261": "Community 261",
|
||||
"262": "index.vue",
|
||||
"264": "index.js",
|
||||
"265": "Community 265",
|
||||
"267": "index.vue",
|
||||
"269": "Community 269",
|
||||
"270": "Community 270",
|
||||
"274": "zh_CN.js",
|
||||
"275": "index.js",
|
||||
"278": "v2.4.2.1 - 2025-06-16",
|
||||
"280": "Community 280",
|
||||
"283": "Community 283",
|
||||
"284": "Community 284",
|
||||
"285": "Community 285",
|
||||
"286": "Community 286",
|
||||
"292": "Community 292",
|
||||
"295": "Community 295",
|
||||
"296": "Community 296",
|
||||
"302": "Community 302",
|
||||
"303": "Community 303",
|
||||
"304": "Community 304",
|
||||
"305": "isIoPlanFrozen",
|
||||
"306": "handleArrange",
|
||||
"307": "Community 307",
|
||||
"308": "Community 308",
|
||||
"309": "Community 309",
|
||||
"310": "Community 310",
|
||||
"315": "Community 315",
|
||||
"316": "Community 316",
|
||||
"317": "Community 317",
|
||||
"318": "Community 318",
|
||||
"319": "Community 319",
|
||||
"320": "Community 320",
|
||||
"321": "Community 321",
|
||||
"322": "Community 322",
|
||||
"323": "Community 323",
|
||||
"324": "Community 324",
|
||||
"325": "Community 325",
|
||||
"326": "Community 326",
|
||||
"327": "Community 327",
|
||||
"328": "Community 328",
|
||||
"329": "Community 329",
|
||||
"330": "Community 330",
|
||||
"331": "Community 331",
|
||||
"332": "Community 332",
|
||||
"333": "Community 333",
|
||||
"334": "Community 334",
|
||||
"335": "Community 335",
|
||||
"336": "Community 336",
|
||||
"337": "Community 337",
|
||||
"338": "Community 338",
|
||||
"339": "Community 339",
|
||||
"340": "Community 340",
|
||||
"341": "Community 341",
|
||||
"342": "error-handle.ts",
|
||||
"344": "ArtException.vue",
|
||||
"346": "Community 346",
|
||||
"347": "Community 347",
|
||||
"349": "Community 349",
|
||||
"350": "Community 350",
|
||||
"355": "Community 355",
|
||||
"362": "Community 362",
|
||||
"367": "Community 367",
|
||||
"372": "detail.vue",
|
||||
"377": "Community 377",
|
||||
"379": "Community 379",
|
||||
"380": "Community 380",
|
||||
"381": "Community 381",
|
||||
"391": "Community 391",
|
||||
"392": "Community 392",
|
||||
"393": "Community 393",
|
||||
"405": "zh_CN.js",
|
||||
"406": "Community 406",
|
||||
"408": "Community 408",
|
||||
"410": "Community 410",
|
||||
"412": "Community 412",
|
||||
"416": "Community 416",
|
||||
"417": "Community 417",
|
||||
"422": "Community 422",
|
||||
"423": "Community 423",
|
||||
"424": "Community 424",
|
||||
"425": "Community 425",
|
||||
"426": "Community 426",
|
||||
"427": "Community 427",
|
||||
"435": "index.vue",
|
||||
"443": "index.vue",
|
||||
"444": "index.vue",
|
||||
"445": "Community 445",
|
||||
"459": "Community 459",
|
||||
"460": "Community 460",
|
||||
"462": "Community 462",
|
||||
"471": "Community 471",
|
||||
"472": "Community 472",
|
||||
"474": "Community 474",
|
||||
"475": "Community 475",
|
||||
"476": "Community 476",
|
||||
"487": "Community 487",
|
||||
"488": "Community 488",
|
||||
"496": "Community 496",
|
||||
"499": "Community 499",
|
||||
"521": "Community 521",
|
||||
"522": "Community 522",
|
||||
"528": "Community 528",
|
||||
"534": "Community 534",
|
||||
"535": "Community 535",
|
||||
"536": "Community 536",
|
||||
"537": "Community 537",
|
||||
"539": "Community 539",
|
||||
"540": "Community 540",
|
||||
"550": "Community 550",
|
||||
"551": "Community 551",
|
||||
"552": "Community 552",
|
||||
"553": "Community 553",
|
||||
"555": "Community 555",
|
||||
"556": "Community 556",
|
||||
"557": "Community 557",
|
||||
"559": "Community 559",
|
||||
"560": "Community 560",
|
||||
"561": "Community 561",
|
||||
"562": "Community 562",
|
||||
"571": "Community 571",
|
||||
"572": "Community 572",
|
||||
"573": "Community 573",
|
||||
"574": "Community 574",
|
||||
"575": "Community 575",
|
||||
"576": "Community 576",
|
||||
"580": "Community 580",
|
||||
"581": "Community 581",
|
||||
"582": "Community 582",
|
||||
"583": "Community 583",
|
||||
"584": "Community 584",
|
||||
"585": "Community 585",
|
||||
"586": "Community 586",
|
||||
"597": "Community 597",
|
||||
"598": "Community 598",
|
||||
"599": "Community 599",
|
||||
"600": "Community 600",
|
||||
"601": "Community 601",
|
||||
"602": "Community 602",
|
||||
"603": "Community 603",
|
||||
"604": "Community 604",
|
||||
"607": "Community 607",
|
||||
"608": "Community 608",
|
||||
"609": "Community 609",
|
||||
"610": "Community 610",
|
||||
"611": "Community 611",
|
||||
"612": "Community 612",
|
||||
"613": "Community 613",
|
||||
"614": "Community 614",
|
||||
"615": "Community 615",
|
||||
"630": "Community 630",
|
||||
"631": "Community 631",
|
||||
"632": "Community 632",
|
||||
"633": "Community 633",
|
||||
"634": "Community 634",
|
||||
"635": "Community 635",
|
||||
"636": "Community 636",
|
||||
"637": "Community 637",
|
||||
"638": "Community 638",
|
||||
"639": "Community 639",
|
||||
"640": "Community 640",
|
||||
"641": "Community 641",
|
||||
"642": "Community 642",
|
||||
"643": "Community 643",
|
||||
"644": "Community 644",
|
||||
"645": "Community 645",
|
||||
"650": "Community 650",
|
||||
"651": "Community 651",
|
||||
"652": "Community 652",
|
||||
"653": "Community 653",
|
||||
"654": "Community 654",
|
||||
"655": "Community 655",
|
||||
"658": "Community 658",
|
||||
"659": "Community 659",
|
||||
"660": "Community 660",
|
||||
"662": "Community 662",
|
||||
"663": "Community 663",
|
||||
"664": "Community 664",
|
||||
"665": "Community 665",
|
||||
"666": "Community 666",
|
||||
"667": "Community 667",
|
||||
"668": "Community 668",
|
||||
"669": "Community 669",
|
||||
"670": "Community 670",
|
||||
"671": "Community 671",
|
||||
"700": "Community 700",
|
||||
"701": "Fixed",
|
||||
"702": "Community 702",
|
||||
"703": "Community 703",
|
||||
"704": "Community 704",
|
||||
"705": "Community 705",
|
||||
"706": "Community 706",
|
||||
"707": "Community 707",
|
||||
"708": "Community 708",
|
||||
"709": "Community 709",
|
||||
"710": "Community 710",
|
||||
"711": "Community 711",
|
||||
"713": "Community 713",
|
||||
"715": "Community 715",
|
||||
"716": "Community 716",
|
||||
"717": "Community 717",
|
||||
"718": "Community 718",
|
||||
"720": "Community 720",
|
||||
"722": "Community 722",
|
||||
"723": "Community 723",
|
||||
"724": "Community 724",
|
||||
"725": "Community 725",
|
||||
"726": "Community 726",
|
||||
"727": "Community 727",
|
||||
"729": "Community 729",
|
||||
"730": "Community 730",
|
||||
"731": "Community 731",
|
||||
"732": "Community 732",
|
||||
"733": "Community 733",
|
||||
"734": "修复",
|
||||
"766": "新增",
|
||||
"770": "移除",
|
||||
"772": "重构",
|
||||
"779": "重构",
|
||||
"785": "⚠️ 重要提示",
|
||||
"786": "⚠️ 重要提示",
|
||||
"788": "⚠️ 重要提示",
|
||||
"796": "OpportunityForm.vue",
|
||||
"806": "index.vue",
|
||||
"836": "BxInvoiceFileSelect.vue",
|
||||
"838": "CustomerSelector.vue",
|
||||
"840": "index.vue",
|
||||
"857": "index.ts",
|
||||
"886": "index.vue",
|
||||
"889": "QuoteSelector.vue",
|
||||
"892": "index.vue",
|
||||
"896": "MarkWonDialog.vue",
|
||||
"924": "OpportunitySelector.vue",
|
||||
"950": "BatchUpdateStageDialog.vue",
|
||||
"1010": "BxApprovalFlowTabs.vue",
|
||||
"1015": "DealDialog.vue",
|
||||
"1016": "TransferDialog.vue",
|
||||
"1017": "BatchUpdateDateDialog.vue",
|
||||
"1027": "IntoPoolDialog.vue",
|
||||
"1115": "v2.4.2.7 - 2025-06-25",
|
||||
"1117": "v2.5.2 - 2025-07-13",
|
||||
"1118": "v2.4.2.2 - 2025-06-16",
|
||||
"1123": "v2.4.1.1 - 2025-06-07",
|
||||
"1126": "v2.4.2.1 - 2025-06-16",
|
||||
"1127": "v2.4.2.4 - 2025-06-18",
|
||||
"1197": "icons.js",
|
||||
"1198": "icons.min.js",
|
||||
"1199": "index.js",
|
||||
"1200": "index.js",
|
||||
"1201": "index.js",
|
||||
"1204": "plugin.js",
|
||||
"1205": "plugin.min.js",
|
||||
"1206": "index.js",
|
||||
"1207": "plugin.js",
|
||||
"1208": "plugin.min.js",
|
||||
"1209": "index.js",
|
||||
"1210": "plugin.js",
|
||||
"1211": "plugin.min.js",
|
||||
"1212": "index.js",
|
||||
"1213": "plugin.js",
|
||||
"1214": "plugin.min.js",
|
||||
"1215": "index.js",
|
||||
"1216": "index.js",
|
||||
"1217": "plugin.js",
|
||||
"1218": "plugin.min.js",
|
||||
"1219": "index.js",
|
||||
"1220": "index.js",
|
||||
"1222": "emojiimages.js",
|
||||
"1223": "emojiimages.min.js",
|
||||
"1224": "emojis.js",
|
||||
"1225": "emojis.min.js",
|
||||
"1228": "ar.js",
|
||||
"1229": "bg_BG.js",
|
||||
"1230": "ca.js",
|
||||
"1231": "cs.js",
|
||||
"1232": "da.js",
|
||||
"1233": "de.js",
|
||||
"1234": "el.js",
|
||||
"1235": "es.js",
|
||||
"1236": "eu.js",
|
||||
"1237": "fa.js",
|
||||
"1238": "fi.js",
|
||||
"1239": "fr_FR.js",
|
||||
"1240": "he_IL.js",
|
||||
"1241": "hi.js",
|
||||
"1242": "hr.js",
|
||||
"1243": "hu_HU.js",
|
||||
"1244": "id.js",
|
||||
"1245": "it.js",
|
||||
"1246": "ja.js",
|
||||
"1247": "kk.js",
|
||||
"1248": "ko_KR.js",
|
||||
"1249": "ms.js",
|
||||
"1250": "nb_NO.js",
|
||||
"1251": "nl.js",
|
||||
"1252": "pl.js",
|
||||
"1253": "pt_BR.js",
|
||||
"1254": "pt_PT.js",
|
||||
"1255": "ro.js",
|
||||
"1256": "ru.js",
|
||||
"1257": "sk.js",
|
||||
"1258": "sl_SI.js",
|
||||
"1259": "sv_SE.js",
|
||||
"1260": "th_TH.js",
|
||||
"1261": "tr.js",
|
||||
"1262": "uk.js",
|
||||
"1263": "vi.js",
|
||||
"1265": "zh_TW.js",
|
||||
"1266": "index.js",
|
||||
"1267": "index.js",
|
||||
"1268": "plugin.js",
|
||||
"1269": "_",
|
||||
"1271": "plugin.js",
|
||||
"1272": "plugin.min.js",
|
||||
"1277": "plugin.js",
|
||||
"1278": "plugin.min.js",
|
||||
"1280": "plugin.js",
|
||||
"1281": "plugin.min.js",
|
||||
"1283": "plugin.js",
|
||||
"1284": "plugin.min.js",
|
||||
"1287": "plugin.js",
|
||||
"1288": "plugin.min.js",
|
||||
"1290": "index.js",
|
||||
"1291": "index.js",
|
||||
"1292": "index.js",
|
||||
"1293": "plugin.js",
|
||||
"1294": "plugin.min.js",
|
||||
"1297": "plugin.js",
|
||||
"1298": "plugin.min.js",
|
||||
"1299": "content.js",
|
||||
"1300": "content.js",
|
||||
"1301": "content.js",
|
||||
"1302": "content.js",
|
||||
"1303": "content.js",
|
||||
"1304": "content.js",
|
||||
"1305": "content.inline.js",
|
||||
"1306": "content.js",
|
||||
"1307": "skin.js",
|
||||
"1308": "skin.shadowdom.js",
|
||||
"1309": "content.inline.js",
|
||||
"1310": "content.js",
|
||||
"1311": "skin.js",
|
||||
"1312": "skin.shadowdom.js",
|
||||
"1313": "content.inline.js",
|
||||
"1314": "content.js",
|
||||
"1315": "skin.js",
|
||||
"1316": "skin.shadowdom.js",
|
||||
"1317": "content.inline.js",
|
||||
"1318": "content.js",
|
||||
"1319": "skin.js",
|
||||
"1320": "skin.shadowdom.js",
|
||||
"1323": "index.vue",
|
||||
"1324": "index.vue",
|
||||
"1325": "index.vue",
|
||||
"1326": "route-parent.vue",
|
||||
"1327": "setupSubpackSlipEditorTypeCheckboxes",
|
||||
"1328": "修复",
|
||||
"1329": "优化",
|
||||
"1330": "新增",
|
||||
"1331": "⚠️ 重要提示",
|
||||
"1332": "重构",
|
||||
"1333": "优化",
|
||||
"1334": "修复",
|
||||
"1335": "新增",
|
||||
"1336": "升级",
|
||||
"1337": "⚠️ 重要提示",
|
||||
"1338": "修复",
|
||||
"1339": "优化",
|
||||
"1340": "新增",
|
||||
"1341": "优化",
|
||||
"1342": "修复",
|
||||
"1343": "⚠️ 重要提示",
|
||||
"1344": "升级",
|
||||
"1345": "修复",
|
||||
"1346": "优化",
|
||||
"1347": "⚠️ 重要提示",
|
||||
"1348": "新增",
|
||||
"1349": "修复",
|
||||
"1350": "优化",
|
||||
"1351": "新增",
|
||||
"1352": "优化",
|
||||
"1353": "修复",
|
||||
"1354": "新增",
|
||||
"1355": "重构",
|
||||
"1356": "优化",
|
||||
"1357": "修复",
|
||||
"1358": "移除",
|
||||
"1359": "新增",
|
||||
"1360": "优化",
|
||||
"1361": "修复",
|
||||
"1362": "新增",
|
||||
"1363": "重构",
|
||||
"1364": "升级",
|
||||
"1365": "优化",
|
||||
"1366": "修复",
|
||||
"1367": "新增",
|
||||
"1368": "优化",
|
||||
"1369": "修复",
|
||||
"1370": "优化",
|
||||
"1371": "修复",
|
||||
"1372": "新增",
|
||||
"1373": "重构",
|
||||
"1374": "升级",
|
||||
"1375": "移除",
|
||||
"1376": "修复",
|
||||
"1377": "⚠️ 重要提示",
|
||||
"1378": "重构",
|
||||
"1379": "优化",
|
||||
"1380": "修复",
|
||||
"1381": "修复",
|
||||
"1382": "新增",
|
||||
"1383": "优化",
|
||||
"1384": "修复",
|
||||
"1385": "重构",
|
||||
"1386": "优化",
|
||||
"1387": "新增",
|
||||
"1388": "重构",
|
||||
"1389": "重构",
|
||||
"1390": "优化",
|
||||
"1391": "重构",
|
||||
"1392": "优化",
|
||||
"1393": "重构",
|
||||
"1394": "重构",
|
||||
"1395": "修复",
|
||||
"1396": "重构",
|
||||
"1397": "新增",
|
||||
"1398": "优化",
|
||||
"1399": "修复",
|
||||
"1400": "⚠️ 重要提示",
|
||||
"1401": "优化",
|
||||
"1402": "修复",
|
||||
"1403": "新增",
|
||||
"1404": "优化",
|
||||
"1405": "修复",
|
||||
"1406": "重构",
|
||||
"1407": "新增",
|
||||
"1408": "优化",
|
||||
"1409": "⚠️ 重要提示",
|
||||
"1410": "code:block1 (crm/clue/)",
|
||||
"1411": "code:typescript ({)",
|
||||
"1412": "code:block3 (crm:clue:list # 线索列表查询)",
|
||||
"1413": "code:bash (mysql -u root -p your_database < crm/sql/crm/12-CRM字典数据汇总.md)",
|
||||
"9890": "README.md",
|
||||
"9959": "Fixed",
|
||||
"9960": "Fixed",
|
||||
"9961": "Fixed",
|
||||
"9962": "Fixed",
|
||||
"9963": "Fixed",
|
||||
"9964": "Fixed",
|
||||
"9965": "Fixed",
|
||||
"9966": "Fixed",
|
||||
"9967": "Fixed",
|
||||
"9968": "Fixed",
|
||||
"9969": "Fixed",
|
||||
"9970": "Fixed",
|
||||
"9971": "Fixed",
|
||||
"9972": "Fixed",
|
||||
"9973": "Fixed",
|
||||
"9974": "⚠️ Important Notice",
|
||||
"9975": "⚠️ Important Notice",
|
||||
"9976": "⚠️ Important Notice",
|
||||
"9977": "⚠️ Important Notice",
|
||||
"9978": "⚠️ Important Notice",
|
||||
"9979": "⚠️ Important Notice",
|
||||
"9980": "⚠️ Important Notice",
|
||||
"9981": "Optimized",
|
||||
"9982": "Optimized",
|
||||
"9983": "Optimized",
|
||||
"9984": "Optimized",
|
||||
"9985": "Optimized",
|
||||
"9986": "Optimized",
|
||||
"9987": "Optimized",
|
||||
"9988": "Optimized",
|
||||
"9989": "Optimized",
|
||||
"9990": "Optimized",
|
||||
"9991": "Optimized",
|
||||
"9992": "Optimized",
|
||||
"9993": "Optimized",
|
||||
"9994": "Optimized",
|
||||
"9995": "Optimized",
|
||||
"9996": "Optimized",
|
||||
"9997": "Optimized",
|
||||
"9998": "Optimized",
|
||||
"9999": "Optimized",
|
||||
"10000": "Optimized",
|
||||
"10001": "Refactored",
|
||||
"10002": "Refactored",
|
||||
"10003": "Refactored",
|
||||
"10004": "Refactored",
|
||||
"10005": "Refactored",
|
||||
"10006": "Refactored",
|
||||
"10007": "Refactored",
|
||||
"10008": "Refactored",
|
||||
"10009": "Refactored",
|
||||
"10010": "Refactored",
|
||||
"10011": "Refactored",
|
||||
"10012": "Refactored",
|
||||
"10013": "Removed",
|
||||
"10014": "Removed",
|
||||
"10015": "Upgraded",
|
||||
"10016": "Upgraded",
|
||||
"10017": "Upgraded",
|
||||
"10018": "Upgraded",
|
||||
"10019": "优化",
|
||||
"10020": "修复",
|
||||
"10021": "⚠️ 重要提示",
|
||||
"10022": "修复",
|
||||
"10023": "优化",
|
||||
"10024": "优化",
|
||||
"10025": "⚠️ 重要提示",
|
||||
"10026": "修复",
|
||||
"10027": "优化",
|
||||
"10028": "优化",
|
||||
"10029": "修复",
|
||||
"10030": "重构",
|
||||
"10031": "优化",
|
||||
"10032": "修复",
|
||||
"10033": "新增",
|
||||
"10034": "移除",
|
||||
"10035": "优化",
|
||||
"10036": "修复",
|
||||
"10037": "重构",
|
||||
"10038": "升级",
|
||||
"10039": "优化",
|
||||
"10040": "修复",
|
||||
"10041": "优化",
|
||||
"10042": "修复",
|
||||
"10043": "修复",
|
||||
"10044": "重构",
|
||||
"10045": "升级",
|
||||
"10046": "移除",
|
||||
"10047": "修复",
|
||||
"10048": "⚠️ 重要提示",
|
||||
"10049": "⚠️ 重要提示",
|
||||
"10050": "优化",
|
||||
"10051": "修复",
|
||||
"10052": "优化",
|
||||
"10053": "修复",
|
||||
"10054": "优化",
|
||||
"10055": "新增",
|
||||
"10056": "重构",
|
||||
"10057": "优化",
|
||||
"10058": "优化",
|
||||
"10059": "重构",
|
||||
"10060": "修复",
|
||||
"10061": "新增",
|
||||
"10062": "优化",
|
||||
"10063": "修复",
|
||||
"10064": "优化",
|
||||
"10065": "⚠️ 重要提示",
|
||||
"10066": "优化",
|
||||
"10067": "修复",
|
||||
"10068": "优化",
|
||||
"10069": "修复",
|
||||
"10070": "新增",
|
||||
"10071": "优化",
|
||||
"10072": "⚠️ 重要提示",
|
||||
"10073": "修复",
|
||||
"10074": "新增",
|
||||
"10075": "升级",
|
||||
"10076": "⚠️ 重要提示",
|
||||
"10077": "修复",
|
||||
"10078": "优化",
|
||||
"10079": "code:bash (# Install dependencies)",
|
||||
"10080": "code:bash (pnpm clean:dev)",
|
||||
"10081": "code:bash (# 安装依赖)",
|
||||
"10082": "code:bash (pnpm clean:dev)"
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,832 @@
|
||||
{
|
||||
"0": "Community 0",
|
||||
"1": "Community 1",
|
||||
"2": "Community 2",
|
||||
"3": "Community 3",
|
||||
"4": "Community 4",
|
||||
"5": "Community 5",
|
||||
"6": "Community 6",
|
||||
"7": "Community 7",
|
||||
"8": "Community 8",
|
||||
"9": "Community 9",
|
||||
"10": "Community 10",
|
||||
"11": "Community 11",
|
||||
"12": "Community 12",
|
||||
"13": "Community 13",
|
||||
"14": "Community 14",
|
||||
"15": "Community 15",
|
||||
"16": "Community 16",
|
||||
"17": "Ha",
|
||||
"18": "Community 18",
|
||||
"19": "Community 19",
|
||||
"20": "Community 20",
|
||||
"21": "Community 21",
|
||||
"22": "Community 22",
|
||||
"23": "Community 23",
|
||||
"24": "Community 24",
|
||||
"25": "Community 25",
|
||||
"26": "theme.min.js",
|
||||
"27": "Community 27",
|
||||
"28": "useCommon",
|
||||
"29": "Community 29",
|
||||
"30": "loader.ts",
|
||||
"31": "RenewDialog.vue",
|
||||
"32": "index.vue",
|
||||
"33": "Community 33",
|
||||
"34": "main.ts",
|
||||
"35": "Community 35",
|
||||
"36": "VoidDialog.vue",
|
||||
"37": "pl-batch-print.ts",
|
||||
"38": "view-fields.ts",
|
||||
"39": "Community 39",
|
||||
"40": "Community 40",
|
||||
"41": "colors.ts",
|
||||
"42": "Community 42",
|
||||
"43": "Community 43",
|
||||
"44": "Community 44",
|
||||
"45": "Community 45",
|
||||
"46": "Community 46",
|
||||
"47": "fetchCustomerDetail",
|
||||
"48": "Community 48",
|
||||
"49": "Community 49",
|
||||
"50": "Community 50",
|
||||
"51": "price-letter-template.ts",
|
||||
"52": "Community 52",
|
||||
"53": "Community 53",
|
||||
"54": "Community 54",
|
||||
"55": "Community 55",
|
||||
"56": "Community 56",
|
||||
"57": "Community 57",
|
||||
"58": "Community 58",
|
||||
"59": "fetchData",
|
||||
"60": "index.vue",
|
||||
"61": "Community 61",
|
||||
"62": "highlight.ts",
|
||||
"63": "price-letter.ts",
|
||||
"64": "Community 64",
|
||||
"65": "detail.vue",
|
||||
"66": "Community 66",
|
||||
"67": "index.vue",
|
||||
"68": "Community 68",
|
||||
"69": "Community 69",
|
||||
"70": "Community 70",
|
||||
"71": "Community 71",
|
||||
"72": "Community 72",
|
||||
"73": "Community 73",
|
||||
"74": "Community 74",
|
||||
"75": "openEdit",
|
||||
"76": "handleSearch",
|
||||
"77": "loadUserOptions",
|
||||
"78": "customerPool.ts",
|
||||
"79": "Community 79",
|
||||
"80": "product.ts",
|
||||
"81": "Community 81",
|
||||
"82": "Community 82",
|
||||
"83": "useDictStore",
|
||||
"84": "Community 84",
|
||||
"85": "index.vue",
|
||||
"86": "Community 86",
|
||||
"87": "canDeleteByCreator",
|
||||
"88": "index.vue",
|
||||
"89": "detail.vue",
|
||||
"90": "theme.min.js",
|
||||
"91": "Community 91",
|
||||
"92": "Community 92",
|
||||
"93": "ArtUserMenu.vue",
|
||||
"94": "formatYmd",
|
||||
"95": "Community 95",
|
||||
"96": "Community 96",
|
||||
"97": "stringifyBody",
|
||||
"98": "index.vue",
|
||||
"99": "stringifyBody",
|
||||
"100": "v2.4.2.1 - 2025-06-16",
|
||||
"101": "price-letter.ts",
|
||||
"102": "price-letter-template.ts",
|
||||
"103": "SettingDrawer.vue",
|
||||
"104": "contractType.ts",
|
||||
"105": "index.vue",
|
||||
"106": "Community 106",
|
||||
"107": "Community 107",
|
||||
"108": "Community 108",
|
||||
"109": "Community 109",
|
||||
"110": "Community 110",
|
||||
"111": "format.ts",
|
||||
"112": "inventory.ts",
|
||||
"113": "Community 113",
|
||||
"114": "index.vue",
|
||||
"115": "useDictStore",
|
||||
"116": "Community 116",
|
||||
"117": "Community 117",
|
||||
"118": "zh_CN.js",
|
||||
"119": "Community 119",
|
||||
"120": "Community 120",
|
||||
"121": "chart.ts",
|
||||
"122": "handleDisburse",
|
||||
"123": "detail.vue",
|
||||
"124": "index.vue",
|
||||
"125": "Community 125",
|
||||
"126": "Community 126",
|
||||
"127": "selectContractRow",
|
||||
"128": "Community 128",
|
||||
"129": "Community 129",
|
||||
"130": "system.ts",
|
||||
"131": "index.vue",
|
||||
"132": "Community 132",
|
||||
"133": "Community 133",
|
||||
"134": "index.vue",
|
||||
"135": "detail.vue",
|
||||
"136": "Community 136",
|
||||
"137": "Community 137",
|
||||
"138": "FollowDialog.vue",
|
||||
"139": "RenewDialog.vue",
|
||||
"140": "Community 140",
|
||||
"141": "Community 141",
|
||||
"142": "Community 142",
|
||||
"143": "index.js",
|
||||
"144": "Community 144",
|
||||
"145": "api",
|
||||
"146": "price-letter-template.ts",
|
||||
"147": "index.vue",
|
||||
"148": "Community 148",
|
||||
"149": "fetchCustomerDetail",
|
||||
"150": "Community 150",
|
||||
"151": "Community 151",
|
||||
"152": "SettingDrawer.vue",
|
||||
"153": "index.vue",
|
||||
"154": "index.vue",
|
||||
"155": "error.ts",
|
||||
"156": "v2.4.2.1 - 2025-06-16",
|
||||
"157": "form.vue",
|
||||
"158": "removeProductsNotAllowedByHazard",
|
||||
"159": "detail.vue",
|
||||
"160": "index.vue",
|
||||
"161": "Community 161",
|
||||
"162": "Community 162",
|
||||
"163": "system.ts",
|
||||
"164": "Community 164",
|
||||
"165": "handleDisburse",
|
||||
"166": "Community 166",
|
||||
"167": "Community 167",
|
||||
"168": "crypto.ts",
|
||||
"169": "Community 169",
|
||||
"170": "Community 170",
|
||||
"171": "index.vue",
|
||||
"172": "index.js",
|
||||
"173": "index.vue",
|
||||
"174": "Community 174",
|
||||
"175": "handleEdit",
|
||||
"176": "fetchData",
|
||||
"177": "fetchCustomerDetail",
|
||||
"178": "Community 178",
|
||||
"179": "Community 179",
|
||||
"180": "index.vue",
|
||||
"181": "Community 181",
|
||||
"182": "Community 182",
|
||||
"183": "Ha",
|
||||
"184": "highlight.ts",
|
||||
"185": "handleConfirmApproval",
|
||||
"186": "StorageKeyManager",
|
||||
"187": "Community 187",
|
||||
"188": "Community 188",
|
||||
"189": "Community 189",
|
||||
"190": "error-handle.ts",
|
||||
"191": "formatYmd",
|
||||
"192": "prepareLineAliasAndBrandForSubmit",
|
||||
"193": "crm-product-display.ts",
|
||||
"194": "index.ts",
|
||||
"195": "Community 195",
|
||||
"196": "Community 196",
|
||||
"197": "v2.4.2.1 - 2025-06-16",
|
||||
"198": "fetchRoleOptions",
|
||||
"199": "colors.ts",
|
||||
"200": "index.js",
|
||||
"201": "Ha",
|
||||
"202": "Community 202",
|
||||
"203": "customerPool.ts",
|
||||
"204": "DbCrmCustomerSelect.vue",
|
||||
"205": "loadDefaultCustomerOptions",
|
||||
"206": "onDrop",
|
||||
"207": "SettingDrawer.vue",
|
||||
"208": "index.vue",
|
||||
"209": "Community 209",
|
||||
"210": "Community 210",
|
||||
"211": "loadUserOptions",
|
||||
"212": "index.js",
|
||||
"213": "Community 213",
|
||||
"214": "Community 214",
|
||||
"215": "SettingActions.vue",
|
||||
"216": "VoidDialog.vue",
|
||||
"217": "index.js",
|
||||
"218": "index.js",
|
||||
"219": "applyBrandSelectChange",
|
||||
"220": "detail.vue",
|
||||
"221": "index.js",
|
||||
"222": "index.vue",
|
||||
"223": "Community 223",
|
||||
"224": "Community 224",
|
||||
"225": "theme.min.js",
|
||||
"226": "api",
|
||||
"227": "Community 227",
|
||||
"228": "Community 228",
|
||||
"229": "useClientColumnFilters.ts",
|
||||
"230": "syncStatsColumnWidths",
|
||||
"231": "index.vue",
|
||||
"232": "price-letter.ts",
|
||||
"233": "Community 233",
|
||||
"234": "Community 234",
|
||||
"235": "index.js",
|
||||
"236": "loadData",
|
||||
"237": "DbPoundSlipQrcodeDialog.vue",
|
||||
"238": "formatYmd",
|
||||
"239": "Community 239",
|
||||
"240": "detail.vue",
|
||||
"241": "index.vue",
|
||||
"242": "Community 242",
|
||||
"243": "Community 243",
|
||||
"244": "loadUserOptions",
|
||||
"245": "index.js",
|
||||
"246": "fetchData",
|
||||
"247": "Community 247",
|
||||
"248": "Community 248",
|
||||
"249": "index.vue",
|
||||
"250": "handleAdd",
|
||||
"251": "handleDisburse",
|
||||
"252": "index.js",
|
||||
"253": "Community 253",
|
||||
"254": "loading.ts",
|
||||
"255": "Community 255",
|
||||
"256": "zh_CN.js",
|
||||
"257": "index.vue",
|
||||
"258": "index.vue",
|
||||
"259": "Community 259",
|
||||
"260": "Community 260",
|
||||
"261": "Community 261",
|
||||
"262": "ensurePlanReadyForArrange",
|
||||
"263": "handleSearch",
|
||||
"264": "index.js",
|
||||
"265": "Community 265",
|
||||
"266": "form.vue",
|
||||
"267": "index.vue",
|
||||
"268": "zh_CN.js",
|
||||
"269": "Community 269",
|
||||
"270": "Community 270",
|
||||
"275": "index.js",
|
||||
"278": "v2.4.2.1 - 2025-06-16",
|
||||
"280": "Community 280",
|
||||
"283": "Community 283",
|
||||
"284": "Community 284",
|
||||
"285": "Community 285",
|
||||
"286": "Community 286",
|
||||
"292": "Community 292",
|
||||
"295": "Community 295",
|
||||
"296": "Community 296",
|
||||
"302": "Community 302",
|
||||
"303": "Community 303",
|
||||
"304": "Community 304",
|
||||
"305": "isIoPlanFrozen",
|
||||
"306": "handleArrange",
|
||||
"307": "Community 307",
|
||||
"308": "Community 308",
|
||||
"309": "Community 309",
|
||||
"310": "Community 310",
|
||||
"315": "Community 315",
|
||||
"316": "Community 316",
|
||||
"317": "Community 317",
|
||||
"318": "Community 318",
|
||||
"319": "Community 319",
|
||||
"320": "Community 320",
|
||||
"321": "Community 321",
|
||||
"322": "Community 322",
|
||||
"323": "Community 323",
|
||||
"324": "Community 324",
|
||||
"325": "Community 325",
|
||||
"326": "Community 326",
|
||||
"327": "Community 327",
|
||||
"328": "Community 328",
|
||||
"329": "Community 329",
|
||||
"330": "Community 330",
|
||||
"331": "Community 331",
|
||||
"332": "Community 332",
|
||||
"333": "Community 333",
|
||||
"334": "Community 334",
|
||||
"335": "Community 335",
|
||||
"336": "Community 336",
|
||||
"337": "Community 337",
|
||||
"338": "Community 338",
|
||||
"339": "Community 339",
|
||||
"340": "Community 340",
|
||||
"341": "Community 341",
|
||||
"342": "error-handle.ts",
|
||||
"344": "ArtException.vue",
|
||||
"346": "Community 346",
|
||||
"347": "Community 347",
|
||||
"349": "Community 349",
|
||||
"350": "Community 350",
|
||||
"355": "Community 355",
|
||||
"362": "Community 362",
|
||||
"367": "Community 367",
|
||||
"372": "detail.vue",
|
||||
"377": "Community 377",
|
||||
"379": "Community 379",
|
||||
"380": "Community 380",
|
||||
"381": "Community 381",
|
||||
"391": "Community 391",
|
||||
"392": "Community 392",
|
||||
"393": "Community 393",
|
||||
"405": "zh_CN.js",
|
||||
"406": "Community 406",
|
||||
"408": "Community 408",
|
||||
"410": "Community 410",
|
||||
"412": "Community 412",
|
||||
"416": "Community 416",
|
||||
"417": "Community 417",
|
||||
"422": "Community 422",
|
||||
"423": "Community 423",
|
||||
"424": "Community 424",
|
||||
"425": "Community 425",
|
||||
"426": "Community 426",
|
||||
"427": "Community 427",
|
||||
"435": "index.vue",
|
||||
"443": "index.vue",
|
||||
"444": "index.vue",
|
||||
"445": "Community 445",
|
||||
"459": "Community 459",
|
||||
"460": "Community 460",
|
||||
"462": "Community 462",
|
||||
"471": "Community 471",
|
||||
"472": "Community 472",
|
||||
"474": "Community 474",
|
||||
"475": "Community 475",
|
||||
"476": "Community 476",
|
||||
"487": "Community 487",
|
||||
"488": "Community 488",
|
||||
"496": "Community 496",
|
||||
"499": "Community 499",
|
||||
"521": "Community 521",
|
||||
"522": "Community 522",
|
||||
"528": "Community 528",
|
||||
"534": "Community 534",
|
||||
"535": "Community 535",
|
||||
"536": "Community 536",
|
||||
"537": "Community 537",
|
||||
"539": "Community 539",
|
||||
"540": "Community 540",
|
||||
"550": "Community 550",
|
||||
"551": "Community 551",
|
||||
"552": "Community 552",
|
||||
"553": "Community 553",
|
||||
"555": "Community 555",
|
||||
"556": "Community 556",
|
||||
"557": "Community 557",
|
||||
"559": "Community 559",
|
||||
"560": "Community 560",
|
||||
"561": "Community 561",
|
||||
"562": "Community 562",
|
||||
"571": "Community 571",
|
||||
"572": "Community 572",
|
||||
"573": "Community 573",
|
||||
"574": "Community 574",
|
||||
"575": "Community 575",
|
||||
"576": "Community 576",
|
||||
"580": "Community 580",
|
||||
"581": "Community 581",
|
||||
"582": "Community 582",
|
||||
"583": "Community 583",
|
||||
"584": "Community 584",
|
||||
"585": "Community 585",
|
||||
"586": "Community 586",
|
||||
"597": "Community 597",
|
||||
"598": "Community 598",
|
||||
"599": "Community 599",
|
||||
"600": "Community 600",
|
||||
"601": "Community 601",
|
||||
"602": "Community 602",
|
||||
"603": "Community 603",
|
||||
"604": "Community 604",
|
||||
"607": "Community 607",
|
||||
"608": "Community 608",
|
||||
"609": "Community 609",
|
||||
"610": "Community 610",
|
||||
"611": "Community 611",
|
||||
"612": "Community 612",
|
||||
"613": "Community 613",
|
||||
"614": "Community 614",
|
||||
"615": "Community 615",
|
||||
"630": "Community 630",
|
||||
"631": "Community 631",
|
||||
"632": "Community 632",
|
||||
"633": "Community 633",
|
||||
"634": "Community 634",
|
||||
"635": "Community 635",
|
||||
"636": "Community 636",
|
||||
"637": "Community 637",
|
||||
"638": "Community 638",
|
||||
"639": "Community 639",
|
||||
"640": "Community 640",
|
||||
"641": "Community 641",
|
||||
"642": "Community 642",
|
||||
"643": "Community 643",
|
||||
"644": "Community 644",
|
||||
"645": "Community 645",
|
||||
"650": "Community 650",
|
||||
"651": "Community 651",
|
||||
"652": "Community 652",
|
||||
"653": "Community 653",
|
||||
"654": "Community 654",
|
||||
"655": "Community 655",
|
||||
"658": "Community 658",
|
||||
"659": "Community 659",
|
||||
"660": "Community 660",
|
||||
"662": "Community 662",
|
||||
"663": "Community 663",
|
||||
"664": "Community 664",
|
||||
"665": "Community 665",
|
||||
"666": "Community 666",
|
||||
"667": "Community 667",
|
||||
"668": "Community 668",
|
||||
"669": "Community 669",
|
||||
"670": "Community 670",
|
||||
"671": "Community 671",
|
||||
"700": "Community 700",
|
||||
"701": "Fixed",
|
||||
"702": "Community 702",
|
||||
"703": "Community 703",
|
||||
"704": "Community 704",
|
||||
"705": "Community 705",
|
||||
"706": "Community 706",
|
||||
"707": "Community 707",
|
||||
"708": "Community 708",
|
||||
"709": "Community 709",
|
||||
"710": "Community 710",
|
||||
"711": "Community 711",
|
||||
"713": "Community 713",
|
||||
"715": "Community 715",
|
||||
"716": "Community 716",
|
||||
"717": "Community 717",
|
||||
"718": "Community 718",
|
||||
"720": "Community 720",
|
||||
"722": "Community 722",
|
||||
"723": "Community 723",
|
||||
"724": "Community 724",
|
||||
"725": "Community 725",
|
||||
"726": "Community 726",
|
||||
"727": "Community 727",
|
||||
"729": "Community 729",
|
||||
"730": "Community 730",
|
||||
"731": "Community 731",
|
||||
"732": "Community 732",
|
||||
"733": "Community 733",
|
||||
"734": "修复",
|
||||
"766": "新增",
|
||||
"770": "移除",
|
||||
"772": "重构",
|
||||
"779": "重构",
|
||||
"785": "⚠️ 重要提示",
|
||||
"786": "⚠️ 重要提示",
|
||||
"788": "⚠️ 重要提示",
|
||||
"796": "OpportunityForm.vue",
|
||||
"806": "index.vue",
|
||||
"836": "BxInvoiceFileSelect.vue",
|
||||
"838": "CustomerSelector.vue",
|
||||
"840": "index.vue",
|
||||
"857": "index.ts",
|
||||
"886": "index.vue",
|
||||
"889": "QuoteSelector.vue",
|
||||
"892": "index.vue",
|
||||
"896": "MarkWonDialog.vue",
|
||||
"924": "OpportunitySelector.vue",
|
||||
"950": "BatchUpdateStageDialog.vue",
|
||||
"1010": "BxApprovalFlowTabs.vue",
|
||||
"1015": "DealDialog.vue",
|
||||
"1016": "TransferDialog.vue",
|
||||
"1017": "BatchUpdateDateDialog.vue",
|
||||
"1027": "IntoPoolDialog.vue",
|
||||
"1115": "v2.4.2.7 - 2025-06-25",
|
||||
"1117": "v2.5.2 - 2025-07-13",
|
||||
"1118": "v2.4.2.2 - 2025-06-16",
|
||||
"1123": "v2.4.1.1 - 2025-06-07",
|
||||
"1126": "v2.4.2.1 - 2025-06-16",
|
||||
"1127": "v2.4.2.4 - 2025-06-18",
|
||||
"1197": "icons.js",
|
||||
"1198": "icons.min.js",
|
||||
"1199": "index.js",
|
||||
"1200": "index.js",
|
||||
"1201": "index.js",
|
||||
"1204": "plugin.js",
|
||||
"1205": "plugin.min.js",
|
||||
"1206": "index.js",
|
||||
"1207": "plugin.js",
|
||||
"1208": "plugin.min.js",
|
||||
"1209": "index.js",
|
||||
"1210": "plugin.js",
|
||||
"1211": "plugin.min.js",
|
||||
"1212": "index.js",
|
||||
"1213": "plugin.js",
|
||||
"1214": "plugin.min.js",
|
||||
"1215": "index.js",
|
||||
"1216": "index.js",
|
||||
"1217": "plugin.js",
|
||||
"1218": "plugin.min.js",
|
||||
"1219": "index.js",
|
||||
"1220": "index.js",
|
||||
"1222": "emojiimages.js",
|
||||
"1223": "emojiimages.min.js",
|
||||
"1224": "emojis.js",
|
||||
"1225": "emojis.min.js",
|
||||
"1228": "ar.js",
|
||||
"1229": "bg_BG.js",
|
||||
"1230": "ca.js",
|
||||
"1231": "cs.js",
|
||||
"1232": "da.js",
|
||||
"1233": "de.js",
|
||||
"1234": "el.js",
|
||||
"1235": "es.js",
|
||||
"1236": "eu.js",
|
||||
"1237": "fa.js",
|
||||
"1238": "fi.js",
|
||||
"1239": "fr_FR.js",
|
||||
"1240": "he_IL.js",
|
||||
"1241": "hi.js",
|
||||
"1242": "hr.js",
|
||||
"1243": "hu_HU.js",
|
||||
"1244": "id.js",
|
||||
"1245": "it.js",
|
||||
"1246": "ja.js",
|
||||
"1247": "kk.js",
|
||||
"1248": "ko_KR.js",
|
||||
"1249": "ms.js",
|
||||
"1250": "nb_NO.js",
|
||||
"1251": "nl.js",
|
||||
"1252": "pl.js",
|
||||
"1253": "pt_BR.js",
|
||||
"1254": "pt_PT.js",
|
||||
"1255": "ro.js",
|
||||
"1256": "ru.js",
|
||||
"1257": "sk.js",
|
||||
"1258": "sl_SI.js",
|
||||
"1259": "sv_SE.js",
|
||||
"1260": "th_TH.js",
|
||||
"1261": "tr.js",
|
||||
"1262": "uk.js",
|
||||
"1263": "vi.js",
|
||||
"1265": "zh_TW.js",
|
||||
"1266": "index.js",
|
||||
"1267": "index.js",
|
||||
"1268": "plugin.js",
|
||||
"1269": "_",
|
||||
"1271": "plugin.js",
|
||||
"1272": "plugin.min.js",
|
||||
"1277": "plugin.js",
|
||||
"1278": "plugin.min.js",
|
||||
"1280": "plugin.js",
|
||||
"1281": "plugin.min.js",
|
||||
"1283": "plugin.js",
|
||||
"1284": "plugin.min.js",
|
||||
"1287": "plugin.js",
|
||||
"1288": "plugin.min.js",
|
||||
"1290": "index.js",
|
||||
"1291": "index.js",
|
||||
"1292": "index.js",
|
||||
"1293": "plugin.js",
|
||||
"1294": "plugin.min.js",
|
||||
"1297": "plugin.js",
|
||||
"1298": "plugin.min.js",
|
||||
"1299": "content.js",
|
||||
"1300": "content.js",
|
||||
"1301": "content.js",
|
||||
"1302": "content.js",
|
||||
"1303": "content.js",
|
||||
"1304": "content.js",
|
||||
"1305": "content.inline.js",
|
||||
"1306": "content.js",
|
||||
"1307": "skin.js",
|
||||
"1308": "skin.shadowdom.js",
|
||||
"1309": "content.inline.js",
|
||||
"1310": "content.js",
|
||||
"1311": "skin.js",
|
||||
"1312": "skin.shadowdom.js",
|
||||
"1313": "content.inline.js",
|
||||
"1314": "content.js",
|
||||
"1315": "skin.js",
|
||||
"1316": "skin.shadowdom.js",
|
||||
"1317": "content.inline.js",
|
||||
"1318": "content.js",
|
||||
"1319": "skin.js",
|
||||
"1320": "skin.shadowdom.js",
|
||||
"1323": "index.vue",
|
||||
"1324": "index.vue",
|
||||
"1325": "index.vue",
|
||||
"1326": "route-parent.vue",
|
||||
"1327": "setupSubpackSlipEditorTypeCheckboxes",
|
||||
"1328": "修复",
|
||||
"1329": "优化",
|
||||
"1330": "新增",
|
||||
"1331": "⚠️ 重要提示",
|
||||
"1332": "重构",
|
||||
"1333": "优化",
|
||||
"1334": "修复",
|
||||
"1335": "新增",
|
||||
"1336": "升级",
|
||||
"1337": "⚠️ 重要提示",
|
||||
"1338": "修复",
|
||||
"1339": "优化",
|
||||
"1340": "新增",
|
||||
"1341": "优化",
|
||||
"1342": "修复",
|
||||
"1343": "⚠️ 重要提示",
|
||||
"1344": "升级",
|
||||
"1345": "修复",
|
||||
"1346": "优化",
|
||||
"1347": "⚠️ 重要提示",
|
||||
"1348": "新增",
|
||||
"1349": "修复",
|
||||
"1350": "优化",
|
||||
"1351": "新增",
|
||||
"1352": "优化",
|
||||
"1353": "修复",
|
||||
"1354": "新增",
|
||||
"1355": "重构",
|
||||
"1356": "优化",
|
||||
"1357": "修复",
|
||||
"1358": "移除",
|
||||
"1359": "新增",
|
||||
"1360": "优化",
|
||||
"1361": "修复",
|
||||
"1362": "新增",
|
||||
"1363": "重构",
|
||||
"1364": "升级",
|
||||
"1365": "优化",
|
||||
"1366": "修复",
|
||||
"1367": "新增",
|
||||
"1368": "优化",
|
||||
"1369": "修复",
|
||||
"1370": "优化",
|
||||
"1371": "修复",
|
||||
"1372": "新增",
|
||||
"1373": "重构",
|
||||
"1374": "升级",
|
||||
"1375": "移除",
|
||||
"1376": "修复",
|
||||
"1377": "⚠️ 重要提示",
|
||||
"1378": "重构",
|
||||
"1379": "优化",
|
||||
"1380": "修复",
|
||||
"1381": "修复",
|
||||
"1382": "新增",
|
||||
"1383": "优化",
|
||||
"1384": "修复",
|
||||
"1385": "重构",
|
||||
"1386": "优化",
|
||||
"1387": "新增",
|
||||
"1388": "重构",
|
||||
"1389": "重构",
|
||||
"1390": "优化",
|
||||
"1391": "重构",
|
||||
"1392": "优化",
|
||||
"1393": "重构",
|
||||
"1394": "重构",
|
||||
"1395": "修复",
|
||||
"1396": "重构",
|
||||
"1397": "新增",
|
||||
"1398": "优化",
|
||||
"1399": "修复",
|
||||
"1400": "⚠️ 重要提示",
|
||||
"1401": "优化",
|
||||
"1402": "修复",
|
||||
"1403": "新增",
|
||||
"1404": "优化",
|
||||
"1405": "修复",
|
||||
"1406": "重构",
|
||||
"1407": "新增",
|
||||
"1408": "优化",
|
||||
"1409": "⚠️ 重要提示",
|
||||
"1410": "code:block1 (crm/clue/)",
|
||||
"1411": "code:typescript ({)",
|
||||
"1412": "code:block3 (crm:clue:list # 线索列表查询)",
|
||||
"1413": "code:bash (mysql -u root -p your_database < crm/sql/crm/12-CRM字典数据汇总.md)",
|
||||
"9890": "README.md",
|
||||
"9959": "Fixed",
|
||||
"9960": "Fixed",
|
||||
"9961": "Fixed",
|
||||
"9962": "Fixed",
|
||||
"9963": "Fixed",
|
||||
"9964": "Fixed",
|
||||
"9965": "Fixed",
|
||||
"9966": "Fixed",
|
||||
"9967": "Fixed",
|
||||
"9968": "Fixed",
|
||||
"9969": "Fixed",
|
||||
"9970": "Fixed",
|
||||
"9971": "Fixed",
|
||||
"9972": "Fixed",
|
||||
"9973": "Fixed",
|
||||
"9974": "⚠️ Important Notice",
|
||||
"9975": "⚠️ Important Notice",
|
||||
"9976": "⚠️ Important Notice",
|
||||
"9977": "⚠️ Important Notice",
|
||||
"9978": "⚠️ Important Notice",
|
||||
"9979": "⚠️ Important Notice",
|
||||
"9980": "⚠️ Important Notice",
|
||||
"9981": "Optimized",
|
||||
"9982": "Optimized",
|
||||
"9983": "Optimized",
|
||||
"9984": "Optimized",
|
||||
"9985": "Optimized",
|
||||
"9986": "Optimized",
|
||||
"9987": "Optimized",
|
||||
"9988": "Optimized",
|
||||
"9989": "Optimized",
|
||||
"9990": "Optimized",
|
||||
"9991": "Optimized",
|
||||
"9992": "Optimized",
|
||||
"9993": "Optimized",
|
||||
"9994": "Optimized",
|
||||
"9995": "Optimized",
|
||||
"9996": "Optimized",
|
||||
"9997": "Optimized",
|
||||
"9998": "Optimized",
|
||||
"9999": "Optimized",
|
||||
"10000": "Optimized",
|
||||
"10001": "Refactored",
|
||||
"10002": "Refactored",
|
||||
"10003": "Refactored",
|
||||
"10004": "Refactored",
|
||||
"10005": "Refactored",
|
||||
"10006": "Refactored",
|
||||
"10007": "Refactored",
|
||||
"10008": "Refactored",
|
||||
"10009": "Refactored",
|
||||
"10010": "Refactored",
|
||||
"10011": "Refactored",
|
||||
"10012": "Refactored",
|
||||
"10013": "Removed",
|
||||
"10014": "Removed",
|
||||
"10015": "Upgraded",
|
||||
"10016": "Upgraded",
|
||||
"10017": "Upgraded",
|
||||
"10018": "Upgraded",
|
||||
"10019": "优化",
|
||||
"10020": "修复",
|
||||
"10021": "⚠️ 重要提示",
|
||||
"10022": "修复",
|
||||
"10023": "优化",
|
||||
"10024": "优化",
|
||||
"10025": "⚠️ 重要提示",
|
||||
"10026": "修复",
|
||||
"10027": "优化",
|
||||
"10028": "优化",
|
||||
"10029": "修复",
|
||||
"10030": "重构",
|
||||
"10031": "优化",
|
||||
"10032": "修复",
|
||||
"10033": "新增",
|
||||
"10034": "移除",
|
||||
"10035": "优化",
|
||||
"10036": "修复",
|
||||
"10037": "重构",
|
||||
"10038": "升级",
|
||||
"10039": "优化",
|
||||
"10040": "修复",
|
||||
"10041": "优化",
|
||||
"10042": "修复",
|
||||
"10043": "修复",
|
||||
"10044": "重构",
|
||||
"10045": "升级",
|
||||
"10046": "移除",
|
||||
"10047": "修复",
|
||||
"10048": "⚠️ 重要提示",
|
||||
"10049": "⚠️ 重要提示",
|
||||
"10050": "优化",
|
||||
"10051": "修复",
|
||||
"10052": "优化",
|
||||
"10053": "修复",
|
||||
"10054": "优化",
|
||||
"10055": "新增",
|
||||
"10056": "重构",
|
||||
"10057": "优化",
|
||||
"10058": "优化",
|
||||
"10059": "重构",
|
||||
"10060": "修复",
|
||||
"10061": "新增",
|
||||
"10062": "优化",
|
||||
"10063": "修复",
|
||||
"10064": "优化",
|
||||
"10065": "⚠️ 重要提示",
|
||||
"10066": "优化",
|
||||
"10067": "修复",
|
||||
"10068": "优化",
|
||||
"10069": "修复",
|
||||
"10070": "新增",
|
||||
"10071": "优化",
|
||||
"10072": "⚠️ 重要提示",
|
||||
"10073": "修复",
|
||||
"10074": "新增",
|
||||
"10075": "升级",
|
||||
"10076": "⚠️ 重要提示",
|
||||
"10077": "修复",
|
||||
"10078": "优化",
|
||||
"10079": "code:bash (# Install dependencies)",
|
||||
"10080": "code:bash (pnpm clean:dev)",
|
||||
"10081": "code:bash (# 安装依赖)",
|
||||
"10082": "code:bash (pnpm clean:dev)"
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+6242
-5487
File diff suppressed because it is too large.
Load diff
@@ -125,6 +125,7 @@
|
||||
hide-nav
|
||||
:tab="viewTab"
|
||||
show-archive-io-fields
|
||||
show-actual-qty-disclaimer
|
||||
feedback-editable
|
||||
:arrange-driver-url="driverUrl"
|
||||
:arrange-site-records="siteRecords"
|
||||
@@ -211,7 +212,7 @@
|
||||
const productRows = ref<PlanFormProductRow[]>([])
|
||||
|
||||
const formData = reactive({
|
||||
hasFreight: 0,
|
||||
hasFreight: 1,
|
||||
distanceKm: null as number | null,
|
||||
freightType: 'by_weight'
|
||||
})
|
||||
@@ -413,7 +414,7 @@
|
||||
plan.value = {}
|
||||
productRows.value = []
|
||||
Object.assign(formData, {
|
||||
hasFreight: 0,
|
||||
hasFreight: 1,
|
||||
distanceKm: null,
|
||||
freightType: 'by_weight'
|
||||
})
|
||||
@@ -422,7 +423,7 @@
|
||||
}
|
||||
|
||||
async function applyFreightPrefill(data: Plan) {
|
||||
formData.hasFreight = data.hasFreight ?? 0
|
||||
formData.hasFreight = isAdjustMode.value ? (data.hasFreight ?? 0) : 1
|
||||
freightCalc.resetFreightCalc()
|
||||
|
||||
if (data.freightAmount != null && data.hasFreight === 1) {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
:disabled="!isEdit"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -589,7 +590,11 @@ function resolveCurrentUserName() {
|
||||
}
|
||||
|
||||
function todayYmd(): string {
|
||||
return new Date().toISOString().split('T')[0]
|
||||
const d = new Date()
|
||||
const y = d.getFullYear()
|
||||
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
const isEdit = computed(() => !!props.planId)
|
||||
|
||||
@@ -24,10 +24,12 @@
|
||||
displayFeedbackTime || '—'
|
||||
}}</span>
|
||||
</div>
|
||||
<p v-if="!hasDriverFeedback" class="pl-plan-form-empty-hint pl-feedback-ticket-empty"
|
||||
<p
|
||||
v-if="!hasDriverFeedback && !driverImagesEditable"
|
||||
class="pl-plan-form-empty-hint pl-feedback-ticket-empty"
|
||||
>暂无司机回传</p
|
||||
>
|
||||
<template v-else>
|
||||
<template v-if="hasDriverFeedback">
|
||||
<div
|
||||
v-for="row in driverTicketQtyRows"
|
||||
:key="row.key"
|
||||
@@ -40,6 +42,9 @@
|
||||
<div>
|
||||
<div class="pl-feedback-ticket-lab">实际数量({{ feedbackQtyUnit }})</div>
|
||||
<div class="pl-feedback-ticket-val">{{ row.actualQty }}</div>
|
||||
<div v-if="showActualQtyDisclaimer" class="pl-feedback-ticket-val-tip"
|
||||
>(仅供参考,实际以附件中数量为准)</div
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<div class="pl-feedback-ticket-lab">品牌数量</div>
|
||||
@@ -55,18 +60,23 @@
|
||||
<span class="pl-feedback-ticket-text">{{ feedbackRemark || '—' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pl-feedback-ticket-foot">
|
||||
<span class="pl-feedback-ticket-lab">附件</span>
|
||||
<AttachmentUploadField
|
||||
v-if="feedbackImageCsv"
|
||||
class="pl-feedback-ticket-attach"
|
||||
:model-value="feedbackImageCsv"
|
||||
compact
|
||||
disabled
|
||||
/>
|
||||
<span v-else class="pl-plan-form-empty-hint">—</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="pl-feedback-ticket-foot">
|
||||
<span class="pl-feedback-ticket-lab">附件</span>
|
||||
<AttachmentUploadField
|
||||
v-if="driverImagesEditable || feedbackImageCsv"
|
||||
class="pl-feedback-ticket-attach"
|
||||
:class="{ 'pl-feedback-ticket-attach--editable': driverImagesEditable }"
|
||||
:model-value="feedbackImageCsv"
|
||||
:disabled="!driverImagesEditable"
|
||||
compact
|
||||
folder="pl/transport/feedback"
|
||||
accept="image/*,video/*,.pdf"
|
||||
:limit="15"
|
||||
@update:model-value="handleDriverImagesChange"
|
||||
/>
|
||||
<span v-else class="pl-plan-form-empty-hint">—</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="feedbackEditable" class="pl-plan-feedback-card-footer">
|
||||
@@ -106,6 +116,9 @@
|
||||
<div>
|
||||
<div class="pl-feedback-ticket-lab">实际数量({{ feedbackQtyUnit }})</div>
|
||||
<div class="pl-feedback-ticket-val">{{ row.actualQty }}</div>
|
||||
<div v-if="showActualQtyDisclaimer" class="pl-feedback-ticket-val-tip"
|
||||
>(仅供参考,实际以附件中数量为准)</div
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<div class="pl-feedback-ticket-lab">品牌数量</div>
|
||||
@@ -148,11 +161,16 @@
|
||||
<div class="pl-feedback-ticket-foot">
|
||||
<span class="pl-feedback-ticket-lab">附件</span>
|
||||
<AttachmentUploadField
|
||||
v-if="ioOrderImageCsv"
|
||||
v-if="ioOrderImagesEditable || ioOrderImageCsv"
|
||||
class="pl-feedback-ticket-attach"
|
||||
:class="{ 'pl-feedback-ticket-attach--editable': ioOrderImagesEditable }"
|
||||
:model-value="ioOrderImageCsv"
|
||||
:disabled="!ioOrderImagesEditable"
|
||||
compact
|
||||
disabled
|
||||
folder="pl/transport/site-feedback"
|
||||
accept="image/*,video/*,.pdf"
|
||||
:limit="15"
|
||||
@update:model-value="handleIoOrderImagesChange"
|
||||
/>
|
||||
<span v-else class="pl-plan-form-empty-hint">—</span>
|
||||
</div>
|
||||
@@ -386,8 +404,12 @@
|
||||
feedbackEditable?: boolean
|
||||
/** 仅运输计划归档:展示入库/出库单价与金额 */
|
||||
showArchiveIoFields?: boolean
|
||||
/** 司机/出库单回传「实际数量」后展示仅供参考说明 */
|
||||
showActualQtyDisclaimer?: boolean
|
||||
loading?: boolean
|
||||
canEditDriverFeedback?: boolean
|
||||
driverImagesEditable?: boolean
|
||||
ioOrderImagesEditable?: boolean
|
||||
hasDriverFeedback?: boolean
|
||||
arrangeDriverUrl?: string
|
||||
driverFeedbackTableRows?: DriverFeedbackTableRow[]
|
||||
@@ -407,8 +429,11 @@
|
||||
{
|
||||
feedbackEditable: false,
|
||||
showArchiveIoFields: false,
|
||||
showActualQtyDisclaimer: false,
|
||||
loading: false,
|
||||
canEditDriverFeedback: false,
|
||||
driverImagesEditable: false,
|
||||
ioOrderImagesEditable: false,
|
||||
hasDriverFeedback: false,
|
||||
arrangeDriverUrl: '',
|
||||
driverFeedbackTableRows: () => [],
|
||||
@@ -532,8 +557,20 @@
|
||||
'copy-site-url': [url?: string]
|
||||
'edit-site-feedback': [row: SiteFeedbackTableRow]
|
||||
'copy-site-summary': [row: SiteFeedbackTableRow]
|
||||
'save-driver-images': [csv: string]
|
||||
'save-io-order-images': [csv: string]
|
||||
}>()
|
||||
|
||||
function handleDriverImagesChange(csv: string) {
|
||||
if (!props.driverImagesEditable) return
|
||||
emit('save-driver-images', csv)
|
||||
}
|
||||
|
||||
function handleIoOrderImagesChange(csv: string) {
|
||||
if (!props.ioOrderImagesEditable) return
|
||||
emit('save-io-order-images', csv)
|
||||
}
|
||||
|
||||
const ioSectionTitle = computed(() => {
|
||||
if (!props.ioOrder) return '现场回传信息'
|
||||
return props.ioOrder.kind === 'inbound' ? '入库单回传' : '出库单回传'
|
||||
@@ -824,6 +861,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 可编辑:沿用紧凑上传卡片尺寸,与只读缩略图同排展示 */
|
||||
.pl-feedback-ticket-attach--editable {
|
||||
:deep(.attachment-item) {
|
||||
width: 88px;
|
||||
}
|
||||
|
||||
:deep(.attachment-preview) {
|
||||
height: 66px;
|
||||
}
|
||||
|
||||
:deep(.attachment-preview__icon) {
|
||||
width: 36px;
|
||||
min-height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.pl-feedback-ticket-band {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -875,6 +928,14 @@
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.pl-feedback-ticket-val-tip {
|
||||
margin-top: 4px;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
font-weight: 400;
|
||||
color: var(--mint-text-muted, #94a3b8);
|
||||
}
|
||||
|
||||
.pl-feedback-ticket-val {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
|
||||
@@ -392,6 +392,7 @@
|
||||
import {
|
||||
inboundOrderApi,
|
||||
outboundOrderApi,
|
||||
planApi,
|
||||
type PlIoOrder,
|
||||
type TransportSiteLink
|
||||
} from '@/api/pl'
|
||||
@@ -440,6 +441,8 @@
|
||||
tab?: string
|
||||
/** 仅运输计划归档:展示入库/出库单价与金额 */
|
||||
showArchiveIoFields?: boolean
|
||||
/** 司机/出库单回传「实际数量」后展示仅供参考说明 */
|
||||
showActualQtyDisclaimer?: boolean
|
||||
/** 计划概况产品表:展示入库/出库数量(不含单价与金额) */
|
||||
showInboundOutboundQty?: boolean
|
||||
}>(),
|
||||
@@ -453,6 +456,7 @@
|
||||
hideNav: false,
|
||||
tab: undefined,
|
||||
showArchiveIoFields: false,
|
||||
showActualQtyDisclaimer: false,
|
||||
showInboundOutboundQty: false
|
||||
}
|
||||
)
|
||||
@@ -580,6 +584,8 @@
|
||||
|
||||
const ioOrderEditVisible = ref(false)
|
||||
const ioOrderSaving = ref(false)
|
||||
const driverImagesSaving = ref(false)
|
||||
const ioOrderImagesSaving = ref(false)
|
||||
const ioOrderEditForm = ref<PlIoOrder | null>(null)
|
||||
const ioOrderEditImagesCsv = ref('')
|
||||
|
||||
@@ -1092,6 +1098,60 @@
|
||||
reload()
|
||||
}
|
||||
|
||||
async function saveDriverImagesInline(csv: string) {
|
||||
if (!props.planId || driverImagesSaving.value) return
|
||||
const nextList = csv
|
||||
? csv
|
||||
.split(',')
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean)
|
||||
: []
|
||||
if (nextList.join(',') === feedbackImageList.value.join(',')) return
|
||||
|
||||
driverImagesSaving.value = true
|
||||
try {
|
||||
await planApi.updateDriverFeedback(props.planId, {
|
||||
feedbackImages: nextList
|
||||
})
|
||||
ElMessage.success('司机回传附件已保存')
|
||||
reload()
|
||||
} catch (e) {
|
||||
ElMessage.error(e instanceof Error ? e.message : '保存失败')
|
||||
} finally {
|
||||
driverImagesSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function saveIoOrderImagesInline(csv: string) {
|
||||
const order = ioOrder.value
|
||||
if (!order || ioOrderImagesSaving.value || order.status === 'voided') return
|
||||
const nextList = csv
|
||||
? csv
|
||||
.split(',')
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean)
|
||||
: []
|
||||
const currentList = Array.isArray(order.siteFeedbackImages)
|
||||
? order.siteFeedbackImages.filter(Boolean)
|
||||
: []
|
||||
if (nextList.join(',') === currentList.join(',')) return
|
||||
|
||||
const api = order.kind === 'inbound' ? inboundOrderApi : outboundOrderApi
|
||||
const label = order.kind === 'inbound' ? '入库单' : '出库单'
|
||||
ioOrderImagesSaving.value = true
|
||||
try {
|
||||
await api.patch(order.id, {
|
||||
siteFeedbackImages: nextList
|
||||
})
|
||||
ElMessage.success(`${label}回传附件已保存`)
|
||||
reload()
|
||||
} catch (e) {
|
||||
ElMessage.error(e instanceof Error ? e.message : '保存失败')
|
||||
} finally {
|
||||
ioOrderImagesSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const hasArrangeSiteLinks = computed(
|
||||
() => props.showArrangeLinks && (props.arrangeSiteRecords?.length ?? 0) > 0
|
||||
)
|
||||
@@ -1149,8 +1209,13 @@
|
||||
const feedbackBlocksBind = computed(() => ({
|
||||
feedbackEditable: props.feedbackEditable,
|
||||
showArchiveIoFields: props.showArchiveIoFields,
|
||||
showActualQtyDisclaimer: props.showActualQtyDisclaimer,
|
||||
loading: loading.value,
|
||||
canEditDriverFeedback: canEditDriverFeedback.value,
|
||||
driverImagesEditable: props.feedbackEditable && canEditDriverFeedback.value,
|
||||
ioOrderImagesEditable: Boolean(
|
||||
props.feedbackEditable && ioOrder.value && ioOrder.value.status !== 'voided'
|
||||
),
|
||||
hasDriverFeedback: hasDriverFeedback.value,
|
||||
arrangeDriverUrl: props.arrangeDriverUrl,
|
||||
driverFeedbackTableRows: driverFeedbackTableRows.value,
|
||||
@@ -1172,6 +1237,12 @@
|
||||
'edit-driver': openDriverFeedbackDialog,
|
||||
'copy-driver-url': copyArrangeDriverUrl,
|
||||
'edit-io-order': openIoOrderEditDialog,
|
||||
'save-driver-images': (csv: string) => {
|
||||
void saveDriverImagesInline(csv)
|
||||
},
|
||||
'save-io-order-images': (csv: string) => {
|
||||
void saveIoOrderImagesInline(csv)
|
||||
},
|
||||
'copy-site-url': (url?: string) => {
|
||||
void copyArrangeSiteUrl(url)
|
||||
},
|
||||
|
||||
@@ -26,15 +26,13 @@ const LOGO_LEFT = 50
|
||||
const TITLE_STYLE = `${FONT_TITLE}font-weight:700 !important;letter-spacing:6px;line-height:1.35;`
|
||||
const TITLE_SUB_STYLE = `${TITLE_STYLE}margin-top:2px;letter-spacing:10px;`
|
||||
const TABLE_ROW_PADDING = '4px'
|
||||
/** 信息表列宽:收货单位(4) / 联系方式(1,略加宽) / 日期(2) */
|
||||
/** 信息表列宽:左栏 3/5(收货单位、收货联系方式)/ 右栏 2/5(单据编号、日期) */
|
||||
const INFO_COLGROUP = `<colgroup>
|
||||
<col style="width:12.75%;" />
|
||||
<col style="width:12.75%;" />
|
||||
<col style="width:12.75%;" />
|
||||
<col style="width:12.75%;" />
|
||||
<col style="width:22.5%;" />
|
||||
<col style="width:13.25%;" />
|
||||
<col style="width:13.25%;" />
|
||||
<col style="width:20%;" />
|
||||
<col style="width:20%;" />
|
||||
<col style="width:20%;" />
|
||||
<col style="width:20%;" />
|
||||
<col style="width:20%;" />
|
||||
</colgroup>`
|
||||
/**
|
||||
* 物料表列宽:单据编号 + 加宽编号/名称,收窄规格/单位;前 5 列合计供条款区使用。
|
||||
@@ -628,22 +626,30 @@ function buildDeliverySlipInfoTableHtml(): string {
|
||||
return `<table class="delivery-slip-info-table" style="width:100%;border-collapse:collapse;table-layout:fixed;border:none !important;">
|
||||
${INFO_COLGROUP}
|
||||
<tr>
|
||||
<td colspan="4" style="${INFO_CELL_LEFT}">
|
||||
<td colspan="3" style="${INFO_CELL_LEFT}">
|
||||
<div class="delivery-slip-info-row" style="${INFO_ROW}">
|
||||
<span class="delivery-slip-info-label" style="${INFO_LABEL}">收货单位:</span>
|
||||
<span class="delivery-slip-info-value-left" style="${INFO_VALUE_INLINE_LEFT}">{{receivingUnit}} </span>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="1" style="${INFO_CELL_LEFT}">
|
||||
<td colspan="2" style="${INFO_CELL_RIGHT}">
|
||||
${buildDeliverySlipTypeCheckboxesHtml()}
|
||||
<div class="delivery-slip-info-row" style="${INFO_ROW}">
|
||||
<span class="delivery-slip-info-label" style="${INFO_LABEL}">联系方式:</span>
|
||||
<span class="delivery-slip-info-label" style="${INFO_LABEL}">单据编号:</span>
|
||||
<span class="delivery-slip-info-value-center" style="${INFO_VALUE_INLINE_CENTER}">{{planNo}} </span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" style="${INFO_CELL_LEFT}">
|
||||
<div class="delivery-slip-info-row" style="${INFO_ROW}">
|
||||
<span class="delivery-slip-info-label" style="${INFO_LABEL}">收货联系方式:</span>
|
||||
<span class="delivery-slip-info-value-left" style="${INFO_VALUE_INLINE_LEFT}">{{receiveContact}} </span>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="2" style="${INFO_CELL_RIGHT}">
|
||||
${buildDeliverySlipTypeCheckboxesHtml()}
|
||||
<div class="delivery-slip-info-row" style="${INFO_ROW}">
|
||||
<span class="delivery-slip-info-label" style="${INFO_LABEL}">日 期:</span>
|
||||
<span class="delivery-slip-info-label" style="${INFO_LABEL}">日 期:</span>
|
||||
<span class="delivery-slip-info-value-center" style="${INFO_VALUE_INLINE_CENTER}">{{planDateChinese}} </span>
|
||||
</div>
|
||||
</td>
|
||||
@@ -1302,7 +1308,7 @@ function normalizeDeliverySlipGapBeforeProduct(html: string): string {
|
||||
|
||||
return html.replace(
|
||||
new RegExp(
|
||||
`(<span class="delivery-slip-info-label"[^>]*>日(?: )?期:<\\/span>[\\s\\S]*?<\\/tr>\\s*)(<!--\\s*中:产品明细表[\\s\\S]*?<tr[\\s\\S]*?<th[^>]*>${productHeader}|<tr[\\s\\S]*?<th[^>]*>${productHeader})`
|
||||
`(<span class="delivery-slip-info-label"[^>]*>日(?: )*期:<\\/span>[\\s\\S]*?<\\/tr>\\s*)(<!--\\s*中:产品明细表[\\s\\S]*?<tr[\\s\\S]*?<th[^>]*>${productHeader}|<tr[\\s\\S]*?<th[^>]*>${productHeader})`
|
||||
),
|
||||
`$1${gapRow}$2`
|
||||
)
|
||||
@@ -1419,34 +1425,39 @@ function normalizeDeliverySlipSignRow(html: string): string {
|
||||
return normalizeDeliverySlipSignLabelMarkup(result)
|
||||
}
|
||||
|
||||
/** 信息区:收货单位 / 联系方式 / 日期 同一行(兼容旧多行布局) */
|
||||
/** 信息区:收货单位+单据编号 / 收货联系方式+日期 两行 3/5+2/5(兼容旧单行布局) */
|
||||
function normalizeDeliverySlipInfoLayout(html: string): string {
|
||||
if (!html.includes('delivery-slip-info-table')) return html
|
||||
|
||||
let result = html.replace(/收货联系方式:/g, '联系方式:')
|
||||
let result = html.replace(/(收货)?联系方式:/g, '收货联系方式:')
|
||||
|
||||
const infoMatch = result.match(/<table class="delivery-slip-info-table"[^>]*>[\s\S]*?<\/table>/i)
|
||||
if (!infoMatch) return result
|
||||
|
||||
const infoHtml = infoMatch[0]
|
||||
const rowCount = (infoHtml.match(/<tr[\s>]/g) || []).length
|
||||
const hasPlanNoInInfo = infoHtml.includes('单据编号:')
|
||||
const layoutOk =
|
||||
rowCount === 1 &&
|
||||
rowCount === 2 &&
|
||||
infoHtml.includes('收货单位:') &&
|
||||
infoHtml.includes('联系方式:') &&
|
||||
/日(?: )?期:/.test(infoHtml) &&
|
||||
!hasPlanNoInInfo &&
|
||||
/<td[^>]*colspan="4"[^>]*>[\s\S]*?收货单位:/.test(infoHtml) &&
|
||||
/<td[^>]*colspan="1"[^>]*>[\s\S]*?联系方式:/.test(infoHtml) &&
|
||||
/<td[^>]*colspan="2"[^>]*>[\s\S]*?日(?: )?期:/.test(infoHtml) &&
|
||||
!/<td[^>]*colspan="[2-5]"[^>]*>[\s\S]*?联系方式:/.test(infoHtml)
|
||||
infoHtml.includes('单据编号:') &&
|
||||
infoHtml.includes('收货联系方式:') &&
|
||||
/日(?: )*期:/.test(infoHtml) &&
|
||||
/<td[^>]*colspan="3"[^>]*>[\s\S]*?收货单位:/.test(infoHtml) &&
|
||||
/<td[^>]*colspan="2"[^>]*>[\s\S]*?单据编号:/.test(infoHtml) &&
|
||||
/<td[^>]*colspan="3"[^>]*>[\s\S]*?收货联系方式:/.test(infoHtml) &&
|
||||
/<td[^>]*colspan="2"[^>]*>[\s\S]*?日(?: )*期:/.test(infoHtml)
|
||||
|
||||
if (layoutOk) {
|
||||
return result.replace(
|
||||
let next = result.replace(
|
||||
/(<table class="delivery-slip-info-table"[^>]*>\s*)(?:<colgroup>[\s\S]*?<\/colgroup>\s*)?/i,
|
||||
`$1${INFO_COLGROUP}`
|
||||
)
|
||||
// 单据编号值居中(兼容先前左对齐模板)
|
||||
next = next.replace(
|
||||
/(<span class="delivery-slip-info-label"[^>]*>单据编号:<\/span>\s*<span class=")delivery-slip-info-value-(?:left|center)(" style=")[^"]*("[^>]*>)/,
|
||||
`$1delivery-slip-info-value-center$2${INFO_VALUE_INLINE_CENTER}$3`
|
||||
)
|
||||
return next
|
||||
}
|
||||
|
||||
return result.replace(infoMatch[0], buildDeliverySlipInfoTableHtml())
|
||||
@@ -1621,7 +1632,7 @@ function normalizeDeliverySlipDocLayout(html: string): string {
|
||||
.replace(/top:4px;/g, `top:${DELIVERY_SLIP_SEAL_TOP}px;`)
|
||||
.replace(/top:-96px !important;/g, `top:${DELIVERY_SLIP_SEAL_TOP}px !important;`)
|
||||
.replace(/top:-96px;/g, `top:${DELIVERY_SLIP_SEAL_TOP}px;`)
|
||||
.replace(/>日期:</g, '>日 期:<')
|
||||
.replace(/>日(?: )*期:</g, '>日 期:<')
|
||||
.replace(/border-bottom:2px solid #000 !important;/g, `border-bottom:${INFO_UNDERLINE} !important;`)
|
||||
.replace(/border-bottom:1px solid #000 !important;/g, `border-bottom:${INFO_UNDERLINE} !important;`)
|
||||
.replace(/border:2px solid #000 !important;/g, `border:${PRODUCT_GRID_BORDER} !important;`)
|
||||
@@ -1708,38 +1719,38 @@ function normalizeDeliverySlipTypeCheckRow(html: string): string {
|
||||
if (!result.includes('delivery-slip-type-check-row')) {
|
||||
const checkRowHtml = buildDeliverySlipTypeCheckboxesHtml()
|
||||
|
||||
const withClass = result.replace(
|
||||
/(<td colspan="3"[^>]*style="[^"]*"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>日(?: )?期:)/,
|
||||
// 优先插在单据编号上方(当前布局:右栏 2/5)
|
||||
const withPlanNo = result.replace(
|
||||
/(<td colspan="2"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>单据编号:)/,
|
||||
`$1${checkRowHtml}\n $2`
|
||||
)
|
||||
if (withClass !== result) {
|
||||
result = withClass
|
||||
if (withPlanNo !== result) {
|
||||
result = withPlanNo
|
||||
} else {
|
||||
result = result.replace(
|
||||
/(<td colspan="3"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>日(?: )?期:)/,
|
||||
`$1${checkRowHtml}\n $2`
|
||||
)
|
||||
}
|
||||
// 兼容旧模板:日期在 colspan=2 / colspan=1 单元格时仍插多选
|
||||
if (!result.includes('delivery-slip-type-check-row')) {
|
||||
result = result.replace(
|
||||
/(<td colspan="2"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>日(?: )?期:)/,
|
||||
`$1${checkRowHtml}\n $2`
|
||||
)
|
||||
}
|
||||
if (!result.includes('delivery-slip-type-check-row')) {
|
||||
result = result.replace(
|
||||
/(<td colspan="1"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>日(?: )?期:)/,
|
||||
`$1${checkRowHtml}\n $2`
|
||||
)
|
||||
}
|
||||
// 兼容更旧模板:单据编号位置仍插多选,随后由 infoLayout 迁移
|
||||
if (!result.includes('delivery-slip-type-check-row')) {
|
||||
result = result.replace(
|
||||
/(<td colspan="3"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>单据编号:)/,
|
||||
`$1${checkRowHtml}\n $2`
|
||||
)
|
||||
}
|
||||
// 兼容旧模板:日期单元格仍插多选,随后由 infoLayout 迁移
|
||||
if (!result.includes('delivery-slip-type-check-row')) {
|
||||
result = result.replace(
|
||||
/(<td colspan="2"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>日(?: )*期:)/,
|
||||
`$1${checkRowHtml}\n $2`
|
||||
)
|
||||
}
|
||||
if (!result.includes('delivery-slip-type-check-row')) {
|
||||
result = result.replace(
|
||||
/(<td colspan="3"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>日(?: )*期:)/,
|
||||
`$1${checkRowHtml}\n $2`
|
||||
)
|
||||
}
|
||||
if (!result.includes('delivery-slip-type-check-row')) {
|
||||
result = result.replace(
|
||||
/(<td colspan="1"[^>]*>\s*)(<div class="delivery-slip-info-row"[^>]*>\s*<span class="delivery-slip-info-label"[^>]*>日(?: )*期:)/,
|
||||
`$1${checkRowHtml}\n $2`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return refreshDeliverySlipTypeCheckRowStyle(result)
|
||||
|
||||
@@ -103,6 +103,9 @@
|
||||
<el-button class="btn-main" type="primary" @click="handleAdd">
|
||||
<el-icon><Plus /></el-icon>新增
|
||||
</el-button>
|
||||
<el-button class="btn-ghost" :disabled="single" @click="handleCopy()">
|
||||
<el-icon><DocumentCopy /></el-icon>合同复制
|
||||
</el-button>
|
||||
<el-button class="btn-ghost" :disabled="!canSubmit" @click="handleSubmitBatch">
|
||||
<el-icon><Document /></el-icon>提交审批
|
||||
</el-button>
|
||||
@@ -516,13 +519,14 @@
|
||||
v-if="isManageMode"
|
||||
v-model:visible="formDialogVisible"
|
||||
:edit-id="formDialogEditId"
|
||||
:copy-source="formDialogCopySource"
|
||||
@success="handleFormSuccess"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ContractListPage">
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue';
|
||||
import {
|
||||
listContract,
|
||||
getContract as getContractDetail,
|
||||
@@ -536,6 +540,7 @@ import {
|
||||
Clock,
|
||||
Close,
|
||||
Document,
|
||||
DocumentCopy,
|
||||
Download,
|
||||
Plus,
|
||||
RefreshLeft,
|
||||
@@ -606,6 +611,7 @@ const resolveCurrentUserId = (): string => {
|
||||
// 合同表单对话框状态
|
||||
const formDialogVisible = ref(false)
|
||||
const formDialogEditId = ref<string | null>(null)
|
||||
const formDialogCopySource = ref<ContractVO | null>(null)
|
||||
|
||||
// 列配置
|
||||
const listColumnDefs = [
|
||||
@@ -1087,15 +1093,50 @@ const handleExpandChange = async (row: ContractVO, expandedRows: ContractVO[]) =
|
||||
}
|
||||
};
|
||||
|
||||
const resetFormDialogState = () => {
|
||||
formDialogEditId.value = null
|
||||
formDialogCopySource.value = null
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
formDialogEditId.value = null
|
||||
resetFormDialogState()
|
||||
formDialogVisible.value = true
|
||||
};
|
||||
}
|
||||
|
||||
/** 解析当前唯一选中的合同行(优先列表数据,保证含 products) */
|
||||
const resolveSingleSelectedContract = (row?: ContractVO): ContractVO | undefined => {
|
||||
if (row?.id != null && String(row.id) !== '') {
|
||||
return contractList.value.find((item) => String(item.id) === String(row.id)) || row
|
||||
}
|
||||
if (ids.value.length !== 1) return undefined
|
||||
const selectedId = ids.value[0]
|
||||
return (
|
||||
contractList.value.find((item) => String(item.id) === String(selectedId))
|
||||
|| selectedRows.value.find((item) => String(item.id) === String(selectedId))
|
||||
)
|
||||
}
|
||||
|
||||
/** 合同复制:选中一条后打开表单,仅带入产品明细 */
|
||||
const handleCopy = (row?: ContractVO) => {
|
||||
if (!row && ids.value.length !== 1) {
|
||||
$modal.msgWarning('请选择一条数据进行合同复制')
|
||||
return
|
||||
}
|
||||
const targetRow = resolveSingleSelectedContract(row)
|
||||
if (!targetRow?.id) {
|
||||
$modal.msgWarning('未找到选中的数据')
|
||||
return
|
||||
}
|
||||
formDialogEditId.value = null
|
||||
formDialogCopySource.value = targetRow
|
||||
formDialogVisible.value = true
|
||||
}
|
||||
|
||||
/** 表单对话框保存/提交成功回调 */
|
||||
const handleFormSuccess = () => {
|
||||
formDialogVisible.value = false
|
||||
resetFormDialogState()
|
||||
getList()
|
||||
}
|
||||
|
||||
@@ -1300,7 +1341,13 @@ onMounted(() => {
|
||||
} else {
|
||||
handleViewChange()
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
watch(formDialogVisible, (visible) => {
|
||||
if (!visible) {
|
||||
resetFormDialogState()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
>{{ dictStore.getLabel('crm_contract_status', detailContract?.status) }}</el-tag>
|
||||
</div>
|
||||
<div class="detail-actions">
|
||||
<el-button
|
||||
v-if="manageActions"
|
||||
class="btn-ghost"
|
||||
@click="handleDetailCopy()"
|
||||
>
|
||||
<el-icon><DocumentCopy /></el-icon>合同复制
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="manageActions && isContractEditableStatus(detailContract?.status)"
|
||||
class="btn-ghost"
|
||||
@@ -844,6 +851,7 @@
|
||||
<ContractFormDialog
|
||||
v-model:visible="formDialogVisible"
|
||||
:edit-id="formDialogEditId"
|
||||
:copy-source="formDialogCopySource"
|
||||
@success="handleFormSuccess"
|
||||
/>
|
||||
<CustomerDetailDialog v-if="customerDialogActive" ref="customerDetailRef" />
|
||||
@@ -853,10 +861,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, defineAsyncComponent, nextTick } from 'vue';
|
||||
import { ref, reactive, computed, onMounted, defineAsyncComponent, nextTick, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { isFrameworkContractType, isContractEditableStatus, getContractReeditConfirmMessage } from '../contractType'
|
||||
import { displayFrameworkMoney, displayFrameworkQuantity } from '../frameworkProductPricing'
|
||||
import {
|
||||
displayFrameworkMoney,
|
||||
displayFrameworkQuantity,
|
||||
formatFrameworkQuantityForPrint
|
||||
} from '../frameworkProductPricing'
|
||||
import {
|
||||
CircleCheck,
|
||||
CircleClose,
|
||||
@@ -865,6 +877,7 @@ import {
|
||||
Close,
|
||||
Delete,
|
||||
Document,
|
||||
DocumentCopy,
|
||||
DocumentChecked,
|
||||
Download,
|
||||
Edit,
|
||||
@@ -984,6 +997,18 @@ const currentContractId = ref<string | number>();
|
||||
|
||||
const formDialogVisible = ref(false);
|
||||
const formDialogEditId = ref<string | null>(null);
|
||||
const formDialogCopySource = ref<ContractVO | null>(null);
|
||||
|
||||
const resetFormDialogState = () => {
|
||||
formDialogEditId.value = null
|
||||
formDialogCopySource.value = null
|
||||
}
|
||||
|
||||
watch(formDialogVisible, (open) => {
|
||||
if (!open) {
|
||||
resetFormDialogState()
|
||||
}
|
||||
})
|
||||
|
||||
const approvalDialogRef = ref();
|
||||
const executeDialogRef = ref();
|
||||
@@ -1050,6 +1075,7 @@ function handleActionSuccess() {
|
||||
|
||||
function handleFormSuccess() {
|
||||
formDialogVisible.value = false;
|
||||
resetFormDialogState();
|
||||
loadDetailData();
|
||||
emit('success');
|
||||
}
|
||||
@@ -1258,6 +1284,18 @@ const handleDetailDrawerClose = () => {
|
||||
detailAttachmentFileList.value = [];
|
||||
};
|
||||
|
||||
/** 详情抽屉 - 合同复制 */
|
||||
const handleDetailCopy = () => {
|
||||
if (!detailContract.value?.id) {
|
||||
$modal.msgWarning('未找到合同数据')
|
||||
return
|
||||
}
|
||||
visible.value = false
|
||||
formDialogEditId.value = null
|
||||
formDialogCopySource.value = detailContract.value
|
||||
formDialogVisible.value = true
|
||||
}
|
||||
|
||||
/** 详情抽屉 - 编辑 */
|
||||
const handleDetailEdit = async () => {
|
||||
if (!detailContract.value?.id) return
|
||||
@@ -1274,7 +1312,8 @@ const handleDetailEdit = async () => {
|
||||
}
|
||||
}
|
||||
visible.value = false
|
||||
formDialogEditId.value = detailContract.value.id
|
||||
resetFormDialogState()
|
||||
formDialogEditId.value = String(detailContract.value.id)
|
||||
formDialogVisible.value = true
|
||||
}
|
||||
|
||||
@@ -1874,7 +1913,7 @@ const replacePlaceholders = (htmlContent: string, contractData: ContractVO | und
|
||||
<td style="padding: 4px 6px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${product.model || product.productModel || ''}</td>
|
||||
<td style="padding: 4px 6px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${formatBrandForPrint(product.brandMode, product.brandName)}</td>
|
||||
<td style="padding: 4px 6px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${getUnitLabel(product.unit)}</td>
|
||||
<td style="padding: 4px 3px; border: 0.3px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${product.quantity || 0}</td>
|
||||
<td style="padding: 4px 3px; border: 0.3px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${formatFrameworkQuantityForPrint(product, isFrameworkContract)}</td>
|
||||
<td style="padding: 4px 3px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${taxRateText}</td>
|
||||
${pricingCells}
|
||||
<td style="padding: 4px 6px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${product.packageSpec || ''}</td>
|
||||
@@ -2252,6 +2291,8 @@ const generateContractTemplate = (contractData: ContractVO | undefined): string
|
||||
return unitLabel || unitValue || '';
|
||||
};
|
||||
|
||||
const isFrameworkContract = isFrameworkContractType(contractData.contractType);
|
||||
|
||||
// 构建产品明细表格行(使用 0.3px 边框)
|
||||
const productRows =
|
||||
contractData.products
|
||||
@@ -2268,7 +2309,7 @@ const generateContractTemplate = (contractData: ContractVO | undefined): string
|
||||
<td style="padding: 4px 6px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${product.model || product.productModel || ''}</td>
|
||||
<td style="padding: 4px 6px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${formatBrandForPrint(product.brandMode, product.brandName)}</td>
|
||||
<td style="padding: 4px 6px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${getUnitLabel(product.unit)}</td>
|
||||
<td style="padding: 4px 3px; border: 0.3px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${product.quantity || 0}</td>
|
||||
<td style="padding: 4px 3px; border: 0.3px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${formatFrameworkQuantityForPrint(product, isFrameworkContract)}</td>
|
||||
<td style="padding: 4px 3px; border: 0.3px solid #000; text-align: center; font-size: 12px;">${taxRateText}</td>
|
||||
<td style="padding: 4px 3px; border: 0.3px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${formatNumber(product.price)}</td>
|
||||
<td style="padding: 4px 3px; border: 0.3px solid #000; text-align: right; font-size: 12px; overflow: hidden; word-break: break-all;">${formatNumber(beforeTax)}</td>
|
||||
|
||||
@@ -824,7 +824,8 @@ import {
|
||||
updateContract,
|
||||
type ContractForm,
|
||||
type ContractProductForm,
|
||||
type ContractProductPriceTierForm
|
||||
type ContractProductPriceTierForm,
|
||||
type ContractVO
|
||||
} from '@/api/crm/contract/index'
|
||||
import { isFrameworkContractType, isPurchaseLikeContractType } from '../contractType'
|
||||
import {
|
||||
@@ -936,6 +937,8 @@ type ExtendedContractProductForm = ContractProductForm & {
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
editId: string | null
|
||||
/** 复制来源合同(列表选中行,含 products) */
|
||||
copySource?: ContractVO | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -953,7 +956,9 @@ const userStore = useUserStore()
|
||||
|
||||
// 表单标题
|
||||
const formTitle = computed(() => {
|
||||
return form.value.id ? '编辑合同' : '新增合同'
|
||||
if (props.editId) return '编辑合同'
|
||||
if (props.copySource) return '复制合同'
|
||||
return '新增合同'
|
||||
})
|
||||
|
||||
// 合同期限日期范围
|
||||
@@ -1077,7 +1082,7 @@ const submitLoading = ref(false)
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible && props.editId) {
|
||||
if (visible && (props.editId || props.copySource)) {
|
||||
formLoading.value = true
|
||||
} else if (!visible) {
|
||||
formLoading.value = false
|
||||
@@ -1346,7 +1351,8 @@ interface QuoteVO {
|
||||
const handleOpened = async () => {
|
||||
resetPartyExpand()
|
||||
const isEdit = !!props.editId
|
||||
if (isEdit) {
|
||||
const isCopy = !!props.copySource
|
||||
if (isEdit || isCopy) {
|
||||
formLoading.value = true
|
||||
}
|
||||
try {
|
||||
@@ -1354,23 +1360,15 @@ const handleOpened = async () => {
|
||||
|
||||
if (props.editId) {
|
||||
await loadContractDetail(props.editId)
|
||||
} else if (props.copySource) {
|
||||
await loadContractForCopy(props.copySource)
|
||||
} else {
|
||||
resetForm()
|
||||
form.value.signDate = new Date().toISOString().split('T')[0]
|
||||
handleSignDateChange(form.value.signDate)
|
||||
applyDefaultOwnerUser()
|
||||
|
||||
// 设置默认供方主体为"SX"
|
||||
const defaultSupplier = supplierList.value.find((supplier) => supplier.supplierCode === 'SX')
|
||||
if (defaultSupplier) {
|
||||
form.value.supplierId = defaultSupplier.id
|
||||
await handleSupplierChange(defaultSupplier.id)
|
||||
}
|
||||
await initNewContractForm()
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('合同表单初始化失败:', error)
|
||||
$modal.msgError(error?.message || '加载合同数据失败')
|
||||
if (isEdit) {
|
||||
if (isEdit || isCopy) {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
} finally {
|
||||
@@ -1378,6 +1376,20 @@ const handleOpened = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
/** 新增合同表单默认值 */
|
||||
const initNewContractForm = async () => {
|
||||
resetForm()
|
||||
form.value.signDate = new Date().toISOString().split('T')[0]
|
||||
handleSignDateChange(form.value.signDate)
|
||||
applyDefaultOwnerUser()
|
||||
|
||||
const defaultSupplier = supplierList.value.find((supplier) => supplier.supplierCode === 'SX')
|
||||
if (defaultSupplier) {
|
||||
form.value.supplierId = defaultSupplier.id
|
||||
await handleSupplierChange(defaultSupplier.id)
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
form.value = {
|
||||
@@ -1446,6 +1458,104 @@ const resetForm = () => {
|
||||
selectedProducts.value = []
|
||||
}
|
||||
|
||||
/** 将源合同产品明细映射为表单行(复制时清除主键及数量/单价/备注) */
|
||||
const mapContractProductsFromSource = (products: any[], forCopy = false) =>
|
||||
products.map((product: any) => {
|
||||
const mapped: ExtendedContractProductForm = {
|
||||
...product,
|
||||
id: forCopy ? undefined : product.id,
|
||||
contractId: forCopy ? undefined : product.contractId,
|
||||
productModel: product.model || product.productModel || '',
|
||||
isToxic: Number(product.isToxic || 0),
|
||||
isExplosive: Number(product.isExplosive || 0),
|
||||
brandMode: product.brandMode || undefined,
|
||||
brandId: product.brandId || undefined,
|
||||
brandName: product.brandName || undefined,
|
||||
brandOptions: [],
|
||||
priceTiers: (product.priceTiers || []).map((t: any) => {
|
||||
let ids: string[] = []
|
||||
if (Array.isArray(t.letterOssIds) && t.letterOssIds.length) {
|
||||
ids = t.letterOssIds.map((id: any) => String(id))
|
||||
} else if (t.letterOssId != null && t.letterOssId !== '') {
|
||||
ids = [String(t.letterOssId)]
|
||||
}
|
||||
return {
|
||||
...t,
|
||||
id: forCopy ? undefined : t.id,
|
||||
contractId: forCopy ? undefined : t.contractId,
|
||||
contractProductId: forCopy ? undefined : t.contractProductId,
|
||||
letterOssIds: ids,
|
||||
...(forCopy ? { price: undefined } : {})
|
||||
}
|
||||
}),
|
||||
taxRate: product.taxRate || 6,
|
||||
taxAmount: forCopy ? 0 : (product.taxAmount ?? 0),
|
||||
packageSpec: product.packageSpec || '',
|
||||
deliveryMethod: product.deliveryMethod || ''
|
||||
}
|
||||
if (forCopy) {
|
||||
mapped.quantity = 0
|
||||
mapped.price = 0
|
||||
mapped.unitPrice = 0
|
||||
mapped.subtotal = 0
|
||||
mapped.remark = ''
|
||||
}
|
||||
return mapped
|
||||
})
|
||||
|
||||
/** 写入产品明细并刷新金额 */
|
||||
const applyContractProductsToForm = async (products: ExtendedContractProductForm[], contractType: string) => {
|
||||
form.value.products = products
|
||||
await enrichContractProductBrandMeta(form.value.products)
|
||||
|
||||
const isFw = isFrameworkContractType(contractType)
|
||||
form.value.products.forEach((product: any) => {
|
||||
normalizeFrameworkProductPricing(product, isFw)
|
||||
if (!isFw || !isFrameworkPriceMarket(product)) {
|
||||
calculateProductAmount(product)
|
||||
}
|
||||
})
|
||||
if (isFw) {
|
||||
form.value.amount = 0
|
||||
} else {
|
||||
calculateTotalAmount()
|
||||
}
|
||||
}
|
||||
|
||||
/** 复制合同:仅带入产品明细,客户等信息由用户重新填写 */
|
||||
const loadContractForCopy = async (source: ContractVO) => {
|
||||
await initNewContractForm()
|
||||
|
||||
const contractType = source.contractType || 'sale'
|
||||
form.value.contractType = contractType
|
||||
|
||||
let products = Array.isArray(source.products) ? source.products : []
|
||||
|
||||
// 列表 includeProducts 不含价阶;框架合同尝试拉详情补全,失败则回退列表明细
|
||||
if (isFrameworkContractType(contractType)) {
|
||||
try {
|
||||
const res = await getContract(source.id)
|
||||
if (res.data?.products?.length) {
|
||||
products = res.data.products
|
||||
form.value.contractType = res.data.contractType || contractType
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('框架合同复制:加载详情价阶失败,使用列表产品明细', error)
|
||||
}
|
||||
}
|
||||
|
||||
if (!products.length) {
|
||||
const res = await getContract(source.id)
|
||||
products = res.data?.products || []
|
||||
form.value.contractType = res.data?.contractType || contractType
|
||||
}
|
||||
|
||||
if (products.length) {
|
||||
const mapped = mapContractProductsFromSource(products, true)
|
||||
await applyContractProductsToForm(mapped, form.value.contractType)
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载合同详情 */
|
||||
const loadContractDetail = async (id: number | string) => {
|
||||
const res = await getContract(id)
|
||||
@@ -1492,47 +1602,8 @@ const loadContractDetail = async (id: number | string) => {
|
||||
}
|
||||
|
||||
if (contractData.products && Array.isArray(contractData.products)) {
|
||||
form.value.products = contractData.products.map((product: any) => ({
|
||||
...product,
|
||||
productModel: product.model || '',
|
||||
isToxic: Number(product.isToxic || 0),
|
||||
isExplosive: Number(product.isExplosive || 0),
|
||||
brandMode: product.brandMode || undefined,
|
||||
brandId: product.brandId || undefined,
|
||||
brandName: product.brandName || undefined,
|
||||
brandOptions: [],
|
||||
priceTiers: (product.priceTiers || []).map((t: any) => {
|
||||
let ids: string[] = []
|
||||
if (Array.isArray(t.letterOssIds) && t.letterOssIds.length) {
|
||||
ids = t.letterOssIds.map((id: any) => String(id))
|
||||
} else if (t.letterOssId != null && t.letterOssId !== '') {
|
||||
ids = [String(t.letterOssId)]
|
||||
}
|
||||
return {
|
||||
...t,
|
||||
letterOssIds: ids
|
||||
}
|
||||
}),
|
||||
taxRate: product.taxRate || 6,
|
||||
taxAmount: product.taxAmount ?? 0,
|
||||
packageSpec: product.packageSpec || '',
|
||||
deliveryMethod: product.deliveryMethod || ''
|
||||
}))
|
||||
|
||||
await enrichContractProductBrandMeta(form.value.products)
|
||||
|
||||
const isFw = isFrameworkContractType(contractData.contractType)
|
||||
form.value.products.forEach((product: any) => {
|
||||
normalizeFrameworkProductPricing(product, isFw)
|
||||
if (!isFw || !isFrameworkPriceMarket(product)) {
|
||||
calculateProductAmount(product)
|
||||
}
|
||||
})
|
||||
if (isFw) {
|
||||
form.value.amount = 0
|
||||
} else {
|
||||
calculateTotalAmount()
|
||||
}
|
||||
const products = mapContractProductsFromSource(contractData.products)
|
||||
await applyContractProductsToForm(products, contractData.contractType)
|
||||
}
|
||||
|
||||
if (form.value.startDate && form.value.endDate) {
|
||||
|
||||
@@ -1098,7 +1098,11 @@ import TinyMceEditor from '@/components/TinyMceEditor/index.vue';
|
||||
import { getOpportunity } from '@/api/crm/opportunity';
|
||||
import { getQuote } from '@/api/crm/quote';
|
||||
import { isFrameworkContractType, isContractEditableStatus, getContractReeditConfirmMessage } from './contractType';
|
||||
import { displayFrameworkMoney, displayFrameworkQuantity } from './frameworkProductPricing';
|
||||
import {
|
||||
displayFrameworkMoney,
|
||||
displayFrameworkQuantity,
|
||||
formatFrameworkQuantityForPrint
|
||||
} from './frameworkProductPricing';
|
||||
import {
|
||||
parseSettlementClauseDrafts,
|
||||
resolveSettlementClauseContent
|
||||
@@ -1594,6 +1598,8 @@ const replacePlaceholders = (htmlContent: string, contractData: ContractVO | und
|
||||
return dictStore.getLabel('crm_product_unit', unitValue) || unitValue || '';
|
||||
};
|
||||
|
||||
const isFrameworkContract = isFrameworkContractType(contractData.contractType);
|
||||
|
||||
// 构建产品明细表格行
|
||||
const productRows =
|
||||
contractData.products
|
||||
@@ -1610,7 +1616,7 @@ const replacePlaceholders = (htmlContent: string, contractData: ContractVO | und
|
||||
<td style="padding: 4px 6px; border: 1px solid #000; text-align: center; font-size: 12px;">${product.model || product.productModel || ''}</td>
|
||||
<td style="padding: 4px 6px; border: 1px solid #000; text-align: center; font-size: 12px;">${formatBrandForPrint(product.brandMode, product.brandName)}</td>
|
||||
<td style="padding: 4px 6px; border: 1px solid #000; text-align: center; font-size: 12px;">${getUnitLabel(product.unit)}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${product.quantity || 0}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${formatFrameworkQuantityForPrint(product, isFrameworkContract)}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: center; font-size: 12px;">${taxRateText}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${formatNumber(product.price)}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: right; font-size: 12px; overflow: hidden; word-break: break-all;">${formatNumber(beforeTax)}</td>
|
||||
@@ -1699,7 +1705,6 @@ const replacePlaceholders = (htmlContent: string, contractData: ContractVO | und
|
||||
const totalWithExtrasChinese = numberToChinese(totalWithExtras);
|
||||
const freightText = freightAmount > 0 ? `¥${formatNumber(freightAmount)}` : '-';
|
||||
const barrelDepositText = barrelDepositAmount > 0 ? `¥${formatNumber(barrelDepositAmount)}` : '-';
|
||||
const isFrameworkContract = isFrameworkContractType(contractData.contractType);
|
||||
const totalWithExtrasText = isFrameworkContract
|
||||
? '随行就市'
|
||||
: `${totalWithExtrasChinese}(¥${formatNumber(totalWithExtras)})`;
|
||||
@@ -1962,7 +1967,7 @@ const generateContractTemplate = (contractData: ContractVO | undefined): string
|
||||
<td style="padding: 4px 6px; border: 1px solid #000; text-align: center; font-size: 12px;">${product.productName || ''}</td>
|
||||
<td style="padding: 4px 6px; border: 1px solid #000; text-align: center; font-size: 12px;">${product.model || product.productModel || ''}</td>
|
||||
<td style="padding: 4px 6px; border: 1px solid #000; text-align: center; font-size: 12px;">${formatBrandForPrint(product.brandMode, product.brandName)}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${product.quantity || 0}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${formatFrameworkQuantityForPrint(product, isFrameworkContract)}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: center; font-size: 12px;">${taxRateText}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: center; font-size: 12px; overflow: hidden; word-break: break-all;">${formatNumber(product.price)}</td>
|
||||
<td style="padding: 4px 3px; border: 1px solid #000; text-align: right; font-size: 12px; overflow: hidden; word-break: break-all;">${formatNumber(beforeTax)}</td>
|
||||
|
||||
@@ -18,6 +18,8 @@ export type FrameworkPriceMode =
|
||||
(typeof FRAMEWORK_PRICE_MODE)[keyof typeof FRAMEWORK_PRICE_MODE]
|
||||
|
||||
export const FRAMEWORK_QUANTITY_LABEL = '按客户需求'
|
||||
/** 打印/PDF 富文本中「按客户需求」对应的用量文案 */
|
||||
export const FRAMEWORK_QUANTITY_PRINT_LABEL = '按实际到货数量'
|
||||
export const FRAMEWORK_PRICE_LABEL = '随行就市'
|
||||
|
||||
export type FrameworkPricingProduct = {
|
||||
@@ -160,6 +162,20 @@ export function displayFrameworkQuantity(product: FrameworkPricingProduct, isFra
|
||||
return formatFrameworkQuantityDisplay(normalizeFrameworkProductPricing({ ...product }, true))
|
||||
}
|
||||
|
||||
/** 打印/PDF 富文本用量列:按客户需求时显示「按实际到货数量」,否则与原先一致输出数量 */
|
||||
export function formatFrameworkQuantityForPrint(
|
||||
product: FrameworkPricingProduct,
|
||||
isFramework: boolean
|
||||
): string {
|
||||
if (isFramework) {
|
||||
const normalized = normalizeFrameworkProductPricing({ ...product }, true)
|
||||
if (isFrameworkQuantityCustomerDemand(normalized)) {
|
||||
return FRAMEWORK_QUANTITY_PRINT_LABEL
|
||||
}
|
||||
}
|
||||
return String(product.quantity || 0)
|
||||
}
|
||||
|
||||
export function displayFrameworkMoney(
|
||||
product: FrameworkPricingProduct,
|
||||
field: 'price' | 'subtotal' | 'taxAmount',
|
||||
|
||||
@@ -320,7 +320,8 @@ import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
fetchCustomerDetail,
|
||||
fetchCreateCustomer,
|
||||
fetchUpdateCustomer
|
||||
fetchUpdateCustomer,
|
||||
fetchCheckDuplicate
|
||||
} from '@/api/crm/customer'
|
||||
import type { CustomerForm as CustomerFormType } from '@/api/crm/customerTypes'
|
||||
import { addInvoiceInfo } from '@/api/crm/invoiceInfo'
|
||||
@@ -377,8 +378,40 @@ function unwrapApiData<T>(res: T | { data?: T }): T {
|
||||
}
|
||||
|
||||
// 表单校验规则
|
||||
const validateCustomerNameUnique = (
|
||||
_rule: unknown,
|
||||
value: string,
|
||||
callback: (error?: Error) => void
|
||||
) => {
|
||||
const name = (value || '').trim()
|
||||
if (!name) {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
fetchCheckDuplicate({
|
||||
customerName: name,
|
||||
excludeId: form.value.id != null ? String(form.value.id) : undefined
|
||||
})
|
||||
.then((res) => {
|
||||
const data = unwrapApiData(res as Record<string, unknown> | { data?: Record<string, unknown> })
|
||||
if (data?.isDuplicate && Array.isArray(data.duplicates) && data.duplicates.length) {
|
||||
const dup = data.duplicates[0] as Record<string, unknown>
|
||||
const customerNo = (dup.customerNo || dup.customer_no || '') as string
|
||||
callback(
|
||||
new Error(customerNo ? `客户名称已存在(编号:${customerNo})` : '客户名称已存在')
|
||||
)
|
||||
return
|
||||
}
|
||||
callback()
|
||||
})
|
||||
.catch(() => callback())
|
||||
}
|
||||
|
||||
const rules = ref<Record<string, FormItemRule[]>>({
|
||||
customerName: [{ required: true, message: '客户名称不能为空', trigger: 'blur' }],
|
||||
customerName: [
|
||||
{ required: true, message: '客户名称不能为空', trigger: 'blur' },
|
||||
{ validator: validateCustomerNameUnique, trigger: 'blur' }
|
||||
],
|
||||
shortName: [{ required: true, message: '客户简称不能为空', trigger: 'blur' }],
|
||||
customerType: [{ required: true, message: '客户类型不能为空', trigger: 'change' }],
|
||||
source: [{ required: true, message: '客户来源不能为空', trigger: 'change' }],
|
||||
@@ -592,6 +625,7 @@ function buildSubmitPayload() {
|
||||
delete payload.businessLicenseImg
|
||||
// 显式传空串:后端按「重新生成」处理;有值则手改入库
|
||||
payload.namePinyinAbbr = (form.value.namePinyinAbbr || '').trim()
|
||||
payload.customerName = (form.value.customerName || '').trim()
|
||||
return payload
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('id')"
|
||||
prop="id"
|
||||
label="ID"
|
||||
label="出入库单ID"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
@@ -569,7 +569,7 @@
|
||||
const loading = ref(false)
|
||||
|
||||
const listColumnDefs = [
|
||||
{ prop: 'id', label: 'ID', defaultVisible: false },
|
||||
{ prop: 'id', label: '出入库单ID' },
|
||||
{ prop: 'planNo', label: '计划号' },
|
||||
{ prop: 'date', label: '日期' },
|
||||
{ prop: 'partnerCompany', label: '往来单位' },
|
||||
@@ -595,7 +595,7 @@
|
||||
isIndeterminate,
|
||||
isColumnVisible,
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('db-inventory-list-columns', listColumnDefs)
|
||||
} = usePersistedListColumns('db-inventory-list-columns-v2', listColumnDefs)
|
||||
|
||||
const inventoryExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
|
||||
@@ -126,6 +126,19 @@
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column type="index" label="序号" width="60" align="center" header-align="center" />
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('inboundOutboundId')"
|
||||
prop="inboundOutboundId"
|
||||
label="出入库单ID"
|
||||
min-width="100"
|
||||
align="center"
|
||||
header-align="center"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="{ row }">
|
||||
{{ row.inboundOutboundId || '—' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isColumnVisible('inventoryDate')"
|
||||
prop="inventoryDate"
|
||||
@@ -559,6 +572,7 @@
|
||||
const router = useRouter()
|
||||
|
||||
const listColumnDefs = [
|
||||
{ prop: 'inboundOutboundId', label: '出入库单ID' },
|
||||
{ prop: 'inventoryDate', label: '日期' },
|
||||
{ prop: 'planNo', label: '计划单号' },
|
||||
{ prop: 'vehicleNo', label: '车牌号' },
|
||||
@@ -584,7 +598,7 @@
|
||||
isIndeterminate,
|
||||
isColumnVisible,
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('db-weighing-list-columns', listColumnDefs)
|
||||
} = usePersistedListColumns('db-weighing-list-columns-v2', listColumnDefs)
|
||||
|
||||
const weighingExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
@@ -605,6 +619,9 @@
|
||||
{ key: '__selection', interactive: false },
|
||||
{ key: '__index', interactive: false }
|
||||
]
|
||||
if (isColumnVisible('inboundOutboundId')) {
|
||||
cols.push({ key: 'inboundOutboundId', interactive: true, prop: 'inboundOutboundId' })
|
||||
}
|
||||
if (isColumnVisible('inventoryDate')) {
|
||||
cols.push({ key: 'inventoryDate', interactive: true, prop: 'inventoryDate' })
|
||||
}
|
||||
@@ -613,7 +630,9 @@
|
||||
}
|
||||
cols.push({ key: 'batchNo', interactive: true, prop: 'batchNo' })
|
||||
for (const def of listColumnDefs) {
|
||||
if (def.prop === 'inventoryDate' || def.prop === 'planNo') continue
|
||||
if (def.prop === 'inventoryDate' || def.prop === 'planNo' || def.prop === 'inboundOutboundId') {
|
||||
continue
|
||||
}
|
||||
if (!isColumnVisible(def.prop)) continue
|
||||
cols.push({
|
||||
key: def.prop,
|
||||
|
||||
@@ -1478,20 +1478,20 @@
|
||||
border-radius: 4px;
|
||||
}
|
||||
.chip.am {
|
||||
color: #b45309;
|
||||
background: #fffbeb;
|
||||
color: #fff;
|
||||
background: #d97706;
|
||||
}
|
||||
.chip.pm {
|
||||
color: #1d4ed8;
|
||||
background: #eff6ff;
|
||||
color: #fff;
|
||||
background: #2563eb;
|
||||
}
|
||||
.chip.duty {
|
||||
color: #b91c1c;
|
||||
background: #fef2f2;
|
||||
color: #fff;
|
||||
background: #dc2626;
|
||||
}
|
||||
.chip.other {
|
||||
color: #475569;
|
||||
background: #f1f5f9;
|
||||
color: #fff;
|
||||
background: #475569;
|
||||
}
|
||||
.chip.empty {
|
||||
color: var(--mint-text-muted, #64748b);
|
||||
|
||||
@@ -102,6 +102,27 @@
|
||||
:selected-ids="selectedRows.map((r) => r.id)"
|
||||
filename="计划归档.xlsx"
|
||||
/>
|
||||
<el-dropdown trigger="click" @command="handleBatchErpCommand">
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
:disabled="selectedRows.length === 0"
|
||||
:loading="erpBatchLoading"
|
||||
>
|
||||
<el-icon><DocumentChecked /></el-icon>
|
||||
ERP录入
|
||||
<el-icon class="el-icon--right"><ArrowDown /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="entered" :disabled="erpBatchLoading">
|
||||
已录入ERP
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="not_entered" :disabled="erpBatchLoading">
|
||||
未录入ERP
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
@@ -229,10 +250,8 @@
|
||||
<template #default="{ row }">
|
||||
<div class="pl-plan-archive-erp-cell" @click.stop @mousedown.stop>
|
||||
<el-checkbox
|
||||
class="pl-plan-archive-erp-checkbox"
|
||||
:model-value="Number(row.erpEntered) === 1"
|
||||
:disabled="row.followStatus === 'cancelled' || erpUpdatingId === row.id"
|
||||
@click.stop
|
||||
@change="(checked) => handleErpEnteredChange(row, Boolean(checked))"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -431,6 +450,8 @@ import ListColumnStatsRow from '@/components/business/list-column-stats-row/inde
|
||||
import type { StatsRowColumn } from '@/utils/list-column-stats'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import {
|
||||
ArrowDown,
|
||||
DocumentChecked,
|
||||
FolderChecked,
|
||||
RefreshLeft,
|
||||
Search
|
||||
@@ -472,7 +493,7 @@ const viewPlanId = ref('')
|
||||
const viewDialogRef = ref<InstanceType<typeof PlPlanViewDialog>>()
|
||||
const archiveDialogVisible = ref(false)
|
||||
const archivePlanId = ref('')
|
||||
const erpUpdatingId = ref('')
|
||||
const erpBatchLoading = ref(false)
|
||||
const planList = ref<Plan[]>([])
|
||||
|
||||
const listColumnDefs = [
|
||||
@@ -765,25 +786,49 @@ function handleToolbarArchive() {
|
||||
handleArchive(selectedRows.value[0])
|
||||
}
|
||||
|
||||
async function handleErpEnteredChange(row: Plan, entered: boolean) {
|
||||
if (row.followStatus === 'cancelled') return
|
||||
const previous = Number(row.erpEntered) === 1
|
||||
if (previous === entered) return
|
||||
async function handleBatchErpCommand(command: 'entered' | 'not_entered') {
|
||||
const entered = command === 'entered'
|
||||
const eligibleRows = selectedRows.value.filter((row) => row.followStatus !== 'cancelled')
|
||||
if (eligibleRows.length === 0) {
|
||||
ElMessage.warning('请选择未作废的计划')
|
||||
return
|
||||
}
|
||||
|
||||
erpUpdatingId.value = row.id
|
||||
row.erpEntered = entered ? 1 : 0
|
||||
const targets = eligibleRows.filter((row) => (Number(row.erpEntered) === 1) !== entered)
|
||||
if (targets.length === 0) {
|
||||
ElMessage.info(entered ? '所选计划均已录入 ERP' : '所选计划均未录入 ERP')
|
||||
return
|
||||
}
|
||||
|
||||
erpBatchLoading.value = true
|
||||
try {
|
||||
const res = await planApi.setErpEntered(row.id, entered)
|
||||
const data = pickBxData<Plan>(res)
|
||||
if (data?.id) {
|
||||
row.erpEntered = data.erpEntered ?? (entered ? 1 : 0)
|
||||
const results = await Promise.allSettled(
|
||||
targets.map((row) => planApi.setErpEntered(row.id, entered))
|
||||
)
|
||||
let successCount = 0
|
||||
results.forEach((result, index) => {
|
||||
const row = targets[index]
|
||||
if (result.status === 'fulfilled') {
|
||||
const data = pickBxData<Plan>(result.value)
|
||||
row.erpEntered = data?.erpEntered ?? (entered ? 1 : 0)
|
||||
successCount += 1
|
||||
return
|
||||
}
|
||||
const message =
|
||||
result.reason instanceof Error ? result.reason.message : '更新 ERP 状态失败'
|
||||
ElMessage.error(
|
||||
`${row.planNo || row.id}:${message.includes('失败') ? message : `更新 ERP 状态失败:${message}`}`
|
||||
)
|
||||
})
|
||||
|
||||
if (successCount > 0) {
|
||||
ElMessage.success(
|
||||
entered ? `已将 ${successCount} 条计划标记为已录入 ERP` : `已将 ${successCount} 条计划标记为未录入 ERP`
|
||||
)
|
||||
await refreshViewIfOpen()
|
||||
}
|
||||
} catch (error) {
|
||||
row.erpEntered = previous ? 1 : 0
|
||||
const message = error instanceof Error ? error.message : '更新 ERP 状态失败'
|
||||
ElMessage.error(message.includes('失败') ? message : `更新 ERP 状态失败:${message}`)
|
||||
} finally {
|
||||
erpUpdatingId.value = ''
|
||||
erpBatchLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,4 +867,9 @@ onMounted(() => {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.pl-plan-archive-erp-checkbox {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
}
|
||||
</style>
|
||||
@@ -173,15 +173,6 @@
|
||||
>
|
||||
<el-icon><DocumentCopy /></el-icon>三方人车快速创建
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="canForceFollowStatus"
|
||||
class="btn-ghost"
|
||||
:disabled="!selectedPlan"
|
||||
@click="openForceFollowStatusDialog"
|
||||
>
|
||||
<el-icon><EditPen /></el-icon>强制改状态
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="planApi.export"
|
||||
:get-filter-params="getPlanExportFilterParams"
|
||||
@@ -571,6 +562,13 @@
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-button
|
||||
v-if="canForceFollowStatus"
|
||||
class="btn-ghost"
|
||||
@click="openForceFollowStatusDialog"
|
||||
>
|
||||
<el-icon><EditPen /></el-icon>强制改状态
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="canVoidPlan(viewingPlan)"
|
||||
class="btn-ghost"
|
||||
@@ -614,27 +612,27 @@
|
||||
>
|
||||
<el-form label-position="top" class="form-grid-2">
|
||||
<el-form-item label="计划编号" style="margin-bottom: 0">
|
||||
<span>{{ selectedPlan?.planNo || '—' }}</span>
|
||||
<span>{{ viewingPlan?.planNo || '—' }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="单据类型" style="margin-bottom: 0">
|
||||
<span>{{ getPlanTypeLabel(selectedPlan?.planType) }}</span>
|
||||
<span>{{ getPlanTypeLabel(viewingPlan?.planType) }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="供方" style="margin-bottom: 0">
|
||||
<span>{{ selectedPlan?.supplierName || '—' }}</span>
|
||||
<span>{{ viewingPlan?.supplierName || '—' }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="需方" style="margin-bottom: 0">
|
||||
<span>{{ selectedPlan?.customerName || '—' }}</span>
|
||||
<span>{{ viewingPlan?.customerName || '—' }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="产品信息" class="form-col-span-2" style="margin-bottom: 0">
|
||||
<PlPlanListProductCell :products="selectedPlan?.products || []" />
|
||||
<PlPlanListProductCell :products="viewingPlan?.products || []" />
|
||||
</el-form-item>
|
||||
<el-form-item label="当前跟进状态" style="margin-bottom: 0">
|
||||
<el-tag
|
||||
v-if="selectedPlan"
|
||||
:type="getPlPlanFollowStatusTagType(selectedPlan.followStatus)"
|
||||
v-if="viewingPlan"
|
||||
:type="getPlPlanFollowStatusTagType(viewingPlan.followStatus)"
|
||||
size="small"
|
||||
>
|
||||
{{ getPlPlanFollowStatusLabel(selectedPlan.followStatus) }}
|
||||
{{ getPlPlanFollowStatusLabel(viewingPlan.followStatus) }}
|
||||
</el-tag>
|
||||
<span v-else>—</span>
|
||||
</el-form-item>
|
||||
@@ -1284,8 +1282,8 @@ function handleToolbarVoid() {
|
||||
}
|
||||
|
||||
function openForceFollowStatusDialog() {
|
||||
if (!selectedPlan.value) return
|
||||
forceFollowStatusValue.value = selectedPlan.value.followStatus || ''
|
||||
if (!viewingPlan.value) return
|
||||
forceFollowStatusValue.value = viewingPlan.value.followStatus || ''
|
||||
forceFollowDialogVisible.value = true
|
||||
}
|
||||
|
||||
@@ -1294,22 +1292,24 @@ function resetForceFollowDialog() {
|
||||
}
|
||||
|
||||
async function submitForceFollowStatus() {
|
||||
if (!selectedPlan.value) return
|
||||
if (!viewingPlan.value) return
|
||||
const next = (forceFollowStatusValue.value || '').trim()
|
||||
if (!next) {
|
||||
ElMessage.warning('请选择目标跟进状态')
|
||||
return
|
||||
}
|
||||
if (next === selectedPlan.value.followStatus) {
|
||||
if (next === viewingPlan.value.followStatus) {
|
||||
ElMessage.warning('目标状态与当前状态相同')
|
||||
return
|
||||
}
|
||||
forceFollowLoading.value = true
|
||||
try {
|
||||
await planApi.forceFollowStatus(selectedPlan.value.id, next)
|
||||
await planApi.forceFollowStatus(viewingPlan.value.id, next)
|
||||
ElMessage.success('跟进状态已更新')
|
||||
forceFollowDialogVisible.value = false
|
||||
fetchData()
|
||||
syncViewingPlan({ ...viewingPlan.value, followStatus: next })
|
||||
await fetchData()
|
||||
await refreshViewIfOpen()
|
||||
} catch (e) {
|
||||
const message = e instanceof Error ? e.message : '修改失败'
|
||||
ElMessage.error(message)
|
||||
|
||||
Reference in new issue
Block a user