提交
This commit is contained in:
1 parent
833544def3
commit
16be6fa22d
204 files changed
+455089
-46491
No files matched your search
@@ -198,6 +198,7 @@
|
||||
"196": "Community 196",
|
||||
"197": "v2.4.2.1 - 2025-06-16",
|
||||
"198": "fetchRoleOptions",
|
||||
"199": "colors.ts",
|
||||
"200": "index.js",
|
||||
"201": "Ha",
|
||||
"202": "Community 202",
|
||||
@@ -230,13 +231,13 @@
|
||||
"229": "useClientColumnFilters.ts",
|
||||
"230": "syncStatsColumnWidths",
|
||||
"231": "index.vue",
|
||||
"232": "index.vue",
|
||||
"232": "handleExportPdf",
|
||||
"233": "Community 233",
|
||||
"234": "Community 234",
|
||||
"235": "index.js",
|
||||
"236": "fastEnter.ts",
|
||||
"236": "pl-plan-contract-display.ts",
|
||||
"237": "DbPoundSlipQrcodeDialog.vue",
|
||||
"238": "pl-plan-contract-display.ts",
|
||||
"238": "error-handle.ts",
|
||||
"239": "Community 239",
|
||||
"240": "detail.vue",
|
||||
"241": "index.vue",
|
||||
@@ -244,21 +245,26 @@
|
||||
"243": "Community 243",
|
||||
"244": "loadUserOptions",
|
||||
"245": "index.js",
|
||||
"246": "getPlMaintenanceApplyStatusLabel",
|
||||
"246": "fetchData",
|
||||
"247": "Community 247",
|
||||
"248": "Community 248",
|
||||
"249": "crm-product-display.ts",
|
||||
"249": "syncStatsColumnWidths",
|
||||
"250": "handleAdd",
|
||||
"251": "handleDisburse",
|
||||
"252": "index.js",
|
||||
"253": "Community 253",
|
||||
"254": "fetchDesignerData",
|
||||
"254": "price-letter.ts",
|
||||
"255": "Community 255",
|
||||
"256": "handleOpen",
|
||||
"256": "index.vue",
|
||||
"257": "index.vue",
|
||||
"258": "loadUserOptions",
|
||||
"259": "Community 259",
|
||||
"260": "Community 260",
|
||||
"261": "Community 261",
|
||||
"262": "zh_CN.js",
|
||||
"264": "index.js",
|
||||
"265": "Community 265",
|
||||
"266": "zh_CN.js",
|
||||
"269": "Community 269",
|
||||
"270": "Community 270",
|
||||
"280": "Community 280",
|
||||
@@ -344,7 +350,6 @@
|
||||
"462": "Community 462",
|
||||
"471": "Community 471",
|
||||
"472": "Community 472",
|
||||
"473": "Community 473",
|
||||
"474": "Community 474",
|
||||
"475": "Community 475",
|
||||
"476": "Community 476",
|
||||
@@ -575,7 +580,6 @@
|
||||
"1284": "plugin.min.js",
|
||||
"1287": "plugin.js",
|
||||
"1288": "plugin.min.js",
|
||||
"1289": "index.js",
|
||||
"1290": "index.js",
|
||||
"1291": "index.js",
|
||||
"1292": "index.js",
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
"196": "Community 196",
|
||||
"197": "v2.4.2.1 - 2025-06-16",
|
||||
"198": "fetchRoleOptions",
|
||||
"199": "price-letter-template.ts",
|
||||
"199": "colors.ts",
|
||||
"200": "index.js",
|
||||
"201": "Ha",
|
||||
"202": "Community 202",
|
||||
@@ -231,13 +231,13 @@
|
||||
"229": "useClientColumnFilters.ts",
|
||||
"230": "syncStatsColumnWidths",
|
||||
"231": "index.vue",
|
||||
"232": "index.vue",
|
||||
"232": "handleExportPdf",
|
||||
"233": "Community 233",
|
||||
"234": "Community 234",
|
||||
"235": "index.js",
|
||||
"236": "fastEnter.ts",
|
||||
"236": "pl-plan-contract-display.ts",
|
||||
"237": "DbPoundSlipQrcodeDialog.vue",
|
||||
"238": "pl-plan-contract-display.ts",
|
||||
"238": "error-handle.ts",
|
||||
"239": "Community 239",
|
||||
"240": "detail.vue",
|
||||
"241": "index.vue",
|
||||
@@ -245,20 +245,24 @@
|
||||
"243": "Community 243",
|
||||
"244": "loadUserOptions",
|
||||
"245": "index.js",
|
||||
"246": "getPlMaintenanceApplyStatusLabel",
|
||||
"246": "fetchData",
|
||||
"247": "Community 247",
|
||||
"248": "Community 248",
|
||||
"249": "crm-product-display.ts",
|
||||
"249": "syncStatsColumnWidths",
|
||||
"250": "handleAdd",
|
||||
"251": "handleDisburse",
|
||||
"252": "index.js",
|
||||
"253": "Community 253",
|
||||
"254": "fetchDesignerData",
|
||||
"254": "price-letter.ts",
|
||||
"255": "Community 255",
|
||||
"256": "handleOpen",
|
||||
"256": "index.vue",
|
||||
"257": "index.vue",
|
||||
"258": "loadUserOptions",
|
||||
"259": "Community 259",
|
||||
"260": "Community 260",
|
||||
"261": "Community 261",
|
||||
"262": "zh_CN.js",
|
||||
"264": "index.js",
|
||||
"265": "Community 265",
|
||||
"269": "Community 269",
|
||||
"270": "Community 270",
|
||||
@@ -576,7 +580,6 @@
|
||||
"1284": "plugin.min.js",
|
||||
"1287": "plugin.js",
|
||||
"1288": "plugin.min.js",
|
||||
"1289": "index.js",
|
||||
"1290": "index.js",
|
||||
"1291": "index.js",
|
||||
"1292": "index.js",
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+10063
-7792
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,831 @@
|
||||
{
|
||||
"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": "handleExportPdf",
|
||||
"233": "Community 233",
|
||||
"234": "Community 234",
|
||||
"235": "index.js",
|
||||
"236": "pl-plan-contract-display.ts",
|
||||
"237": "DbPoundSlipQrcodeDialog.vue",
|
||||
"238": "error-handle.ts",
|
||||
"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": "syncStatsColumnWidths",
|
||||
"250": "handleAdd",
|
||||
"251": "handleDisburse",
|
||||
"252": "index.js",
|
||||
"253": "Community 253",
|
||||
"254": "price-letter.ts",
|
||||
"255": "Community 255",
|
||||
"256": "index.vue",
|
||||
"257": "index.vue",
|
||||
"258": "loadUserOptions",
|
||||
"259": "Community 259",
|
||||
"260": "Community 260",
|
||||
"261": "Community 261",
|
||||
"262": "zh_CN.js",
|
||||
"263": "v2.5.7 - 2025-09-14",
|
||||
"264": "index.js",
|
||||
"265": "Community 265",
|
||||
"266": "zh_CN.js",
|
||||
"269": "Community 269",
|
||||
"270": "Community 270",
|
||||
"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",
|
||||
"473": "Community 473",
|
||||
"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",
|
||||
"1202": "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",
|
||||
"1295": "index.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
+19290
-15260
File diff suppressed because it is too large.
Load diff
@@ -148,10 +148,16 @@ export async function checkConvert(id: number | string) {
|
||||
return { data: unwrapData(res) }
|
||||
}
|
||||
|
||||
export function exportClue(query?: ClueQuery) {
|
||||
export function exportClue(data: Record<string, any> = {}) {
|
||||
const { ids, columns, ...rest } = data
|
||||
const body: Record<string, any> = {
|
||||
...mapListQuery(rest as ClueQuery),
|
||||
...(ids ? { ids } : {}),
|
||||
...(columns ? { columns } : {})
|
||||
}
|
||||
return request.post({
|
||||
url: `${BASE}/export`,
|
||||
data: mapListQuery(query),
|
||||
data: body,
|
||||
responseType: 'blob',
|
||||
showErrorMessage: false
|
||||
})
|
||||
|
||||
@@ -77,10 +77,16 @@ export function approveTransfer(data: {
|
||||
})
|
||||
}
|
||||
|
||||
export async function exportApproval(query: ApprovalQuery) {
|
||||
export async function exportApproval(data: Record<string, any> = {}) {
|
||||
const { ids, columns, ...rest } = data
|
||||
const body: Record<string, any> = {
|
||||
...mapListQuery(rest as ApprovalQuery),
|
||||
...(ids ? { ids } : {}),
|
||||
...(columns ? { columns } : {})
|
||||
}
|
||||
return request.post({
|
||||
url: `${BASE}/export`,
|
||||
data: mapListQuery(query),
|
||||
data: body,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -81,10 +81,16 @@ export function executeChange(id: number | string) {
|
||||
return request.put({ url: `${BASE}/execute/${String(id)}` })
|
||||
}
|
||||
|
||||
export async function exportChange(query: ChangeQuery) {
|
||||
export async function exportChange(data: Record<string, any> = {}) {
|
||||
const { ids, columns, ...rest } = data
|
||||
const body: Record<string, any> = {
|
||||
...mapListQuery(rest as ChangeQuery),
|
||||
...(ids ? { ids } : {}),
|
||||
...(columns ? { columns } : {})
|
||||
}
|
||||
return request.post({
|
||||
url: `${BASE}/export`,
|
||||
data: mapListQuery(query),
|
||||
data: body,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
@@ -194,10 +194,16 @@ export function uploadAttachments(data: {
|
||||
})
|
||||
}
|
||||
|
||||
export async function exportContract(query?: ContractQuery) {
|
||||
export async function exportContract(data: Record<string, any> = {}) {
|
||||
const { ids, columns, ...rest } = data
|
||||
const body: Record<string, any> = {
|
||||
...mapListQuery(rest as ContractQuery),
|
||||
...(ids ? { ids } : {}),
|
||||
...(columns ? { columns } : {})
|
||||
}
|
||||
return request.post({
|
||||
url: `${BASE}/export`,
|
||||
data: mapListQuery(query),
|
||||
data: body,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -60,10 +60,16 @@ export function disableTemplate(id: number | string) {
|
||||
return request.put({ url: `${BASE}/disable/${String(id)}` })
|
||||
}
|
||||
|
||||
export async function exportTemplate(query: TemplateQuery) {
|
||||
export async function exportTemplate(data: Record<string, any> = {}) {
|
||||
const { ids, columns, ...rest } = data
|
||||
const body: Record<string, any> = {
|
||||
...mapListQuery(rest as TemplateQuery),
|
||||
...(ids ? { ids } : {}),
|
||||
...(columns ? { columns } : {})
|
||||
}
|
||||
return request.post({
|
||||
url: `${BASE}/export`,
|
||||
data: mapListQuery(query),
|
||||
data: body,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
@@ -119,10 +119,16 @@ export function markLost(data: OpportunityMarkLostParams) {
|
||||
})
|
||||
}
|
||||
|
||||
export async function exportOpportunity(query?: OpportunityQuery) {
|
||||
export async function exportOpportunity(data: Record<string, any> = {}) {
|
||||
const { ids, columns, ...rest } = data
|
||||
const body: Record<string, any> = {
|
||||
...mapListQuery(rest as OpportunityQuery),
|
||||
...(ids ? { ids } : {}),
|
||||
...(columns ? { columns } : {})
|
||||
}
|
||||
return request.post({
|
||||
url: `${BASE}/export`,
|
||||
data: mapListQuery(query),
|
||||
data: body,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -26,6 +26,15 @@ export function fetchPoolRecordList(data?: Record<string, any>) {
|
||||
return request.post({ url: '/web/crm/customer/pool/record/list', data })
|
||||
}
|
||||
|
||||
/** 导出公海客户 */
|
||||
export function fetchExportPoolCustomers(data: Record<string, any> = {}) {
|
||||
return request.post({
|
||||
url: '/web/crm/customer/pool/export',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
// ── 公海池规则 ──
|
||||
|
||||
/** 公海池规则列表 */
|
||||
@@ -62,3 +71,13 @@ export function fetchTogglePoolRule(data: { id: string; status: string }) {
|
||||
export function fetchExecutePoolRules(data?: Record<string, any>) {
|
||||
return request.post({ url: '/web/crm/customer/pool/rule/execute', data })
|
||||
}
|
||||
|
||||
/** 导出公海规则 */
|
||||
export function fetchExportPoolRules(data: Record<string, any> = {}) {
|
||||
return request.post({
|
||||
url: '/web/crm/customer/pool/rule/export',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -161,10 +161,16 @@ export function invalidQuote(id: string | number, remark?: string) {
|
||||
return request.post({ url: `${BASE}/invalid`, data: { id: String(id), remark } })
|
||||
}
|
||||
|
||||
export async function exportQuote(query?: QuoteQuery) {
|
||||
export async function exportQuote(data: Record<string, any> = {}) {
|
||||
const { ids, columns, ...rest } = data
|
||||
const body: Record<string, any> = {
|
||||
...mapListQuery(rest as QuoteQuery),
|
||||
...(ids ? { ids } : {}),
|
||||
...(columns ? { columns } : {})
|
||||
}
|
||||
return request.post({
|
||||
url: `${BASE}/export`,
|
||||
data: mapListQuery(query),
|
||||
data: body,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -104,6 +104,9 @@ export const inventoryApi = {
|
||||
list(params?: InventoryListParams) {
|
||||
return dbRequest.get<InventoryRecord[]>('/inventory', { params, timeout: 60000 })
|
||||
},
|
||||
export(data: Record<string, any>) {
|
||||
return dbRequest.post<Blob>('/inventory/export', data, { responseType: 'blob' })
|
||||
},
|
||||
get(id: string) {
|
||||
return dbRequest.get<InventoryRecord>(`/inventory/${id}`)
|
||||
},
|
||||
|
||||
@@ -131,6 +131,9 @@ export const planApi = {
|
||||
list(params?: PlanListParams) {
|
||||
return dbRequest.get<Plan[]>('/plans', { params })
|
||||
},
|
||||
export(data: Record<string, any>) {
|
||||
return dbRequest.post<Blob>('/plans/export', data, { responseType: 'blob' })
|
||||
},
|
||||
get(id: string) {
|
||||
return dbRequest.get<Plan>(`/plans/${id}`)
|
||||
},
|
||||
|
||||
@@ -104,6 +104,9 @@ export const weighingApi = {
|
||||
list(params?: WeighingListParams) {
|
||||
return dbRequest.get<WeighingRecord[]>('/weighing', { params })
|
||||
},
|
||||
export(data: Record<string, any>) {
|
||||
return dbRequest.post<Blob>('/weighing/export', data, { responseType: 'blob' })
|
||||
},
|
||||
get(id: string) {
|
||||
return dbRequest.get<WeighingRecord>(`/weighing/${id}`)
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
demoUnits
|
||||
} from './mock-data'
|
||||
import { DEFAULT_LIST_PAGE_SIZE } from '@/utils/table/tableConfig'
|
||||
import request from '@/utils/http'
|
||||
|
||||
type PageParams = { page?: number; pageSize?: number; keyword?: string }
|
||||
|
||||
@@ -387,3 +388,113 @@ export async function fetchAttachmentDownloadUrl(_data: { fileUrl: string; fileN
|
||||
await delay()
|
||||
return { downloadUrl: '#' }
|
||||
}
|
||||
|
||||
|
||||
const DEMO_PRODUCT_EXPORT_COLS = [
|
||||
{ field: 'id', title: 'id' },
|
||||
{ field: 'name', title: '商品名称' },
|
||||
{ field: 'skuCode', title: 'SKU编码' },
|
||||
{ field: 'categoryName', title: '分类' },
|
||||
{ field: 'measureValue', title: '计量' },
|
||||
{ field: 'unitName', title: '单位' },
|
||||
{ field: 'imageUrl', title: '图片URL' },
|
||||
{ field: 'isActive', title: '状态' },
|
||||
{ field: 'createAt', title: '创建时间' }
|
||||
]
|
||||
|
||||
const DEMO_CATEGORY_EXPORT_COLS = [
|
||||
{ field: 'id', title: 'id' },
|
||||
{ field: 'name', title: '分类名称' },
|
||||
{ field: 'parentId', title: '父分类ID' },
|
||||
{ field: 'parentName', title: '父分类名称' },
|
||||
{ field: 'sortOrder', title: '排序' },
|
||||
{ field: 'priceCoefficient', title: '价格系数(%)' },
|
||||
{ field: 'isActive', title: '状态' },
|
||||
{ field: 'imageUrl', title: '图片URL' }
|
||||
]
|
||||
|
||||
function pickExportColumns(
|
||||
all: { field: string; title: string }[],
|
||||
visible?: string[]
|
||||
) {
|
||||
if (!visible?.length) return all
|
||||
const set = new Set(visible)
|
||||
const picked = all.filter((c) => set.has(c.field))
|
||||
return picked.length ? picked : all
|
||||
}
|
||||
|
||||
/** Demo 商品列表导出(Mock 筛行 + 后端 xlsx) */
|
||||
export async function fetchExportDemoProducts(payload: Record<string, any> = {}) {
|
||||
await delay()
|
||||
let list = [...products]
|
||||
if (payload.categoryId) list = list.filter((p) => p.categoryId === payload.categoryId)
|
||||
if (payload.isActive === true || payload.isActive === false) {
|
||||
list = list.filter((p) => p.isActive === payload.isActive)
|
||||
}
|
||||
list = filterKeyword(list, ['name', 'skuCode'], payload.keyword)
|
||||
if (payload.ids?.length) {
|
||||
const idSet = new Set(payload.ids.map(String))
|
||||
list = list.filter((p) => idSet.has(String(p.id)))
|
||||
}
|
||||
const cols = pickExportColumns(DEMO_PRODUCT_EXPORT_COLS, payload.columns)
|
||||
const rows = list.map((row) => ({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
skuCode: (row as any).skuCode || 'SKU-DEMO',
|
||||
categoryName: row.categoryName,
|
||||
measureValue: (row as any).measureValue ?? 1,
|
||||
unitName: row.unitName,
|
||||
imageUrl: row.imageUrl,
|
||||
isActive: row.isActive ? '启用' : '禁用',
|
||||
createAt: row.createAt
|
||||
}))
|
||||
return request.post({
|
||||
url: '/web/admin/demo/xlsx-export',
|
||||
data: {
|
||||
sheetTitle: '商品数据',
|
||||
filenameStem: '商品数据',
|
||||
columns: cols,
|
||||
rows
|
||||
},
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
/** Demo 分类列表导出(Mock 筛行 + 后端 xlsx) */
|
||||
export async function fetchExportDemoCategories(payload: Record<string, any> = {}) {
|
||||
await delay()
|
||||
let list = [...categories]
|
||||
if (payload.isActive === true || payload.isActive === false) {
|
||||
list = list.filter((c) => c.isActive === payload.isActive)
|
||||
}
|
||||
list = filterKeyword(list, ['name'], payload.keyword)
|
||||
if (payload.ids?.length) {
|
||||
const idSet = new Set(payload.ids.map(String))
|
||||
list = list.filter((c) => idSet.has(String(c.id)))
|
||||
}
|
||||
const idToName = new Map(list.map((c) => [c.id, c.name]))
|
||||
// parent may be outside filtered set — use full categories map
|
||||
const allNames = new Map(categories.map((c) => [c.id, c.name]))
|
||||
const cols = pickExportColumns(DEMO_CATEGORY_EXPORT_COLS, payload.columns)
|
||||
const rows = list.map((row) => ({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
parentId: row.parentId || '',
|
||||
parentName: row.parentId ? allNames.get(row.parentId) || '' : '',
|
||||
sortOrder: row.sortOrder,
|
||||
priceCoefficient: row.priceCoefficient ?? 0,
|
||||
isActive: row.isActive ? '启用' : '禁用',
|
||||
imageUrl: row.imageUrl || ''
|
||||
}))
|
||||
return request.post({
|
||||
url: '/web/admin/demo/xlsx-export',
|
||||
data: {
|
||||
sheetTitle: '分类数据',
|
||||
filenameStem: '分类数据',
|
||||
columns: cols,
|
||||
rows
|
||||
},
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -55,6 +55,14 @@ export interface PublicIoOrderPage {
|
||||
items: PublicIoOrderItem[]
|
||||
}
|
||||
|
||||
export interface PublicIoOrderHistoryProduct {
|
||||
productName: string
|
||||
model?: string
|
||||
packageSpec?: string
|
||||
quantity?: number | null
|
||||
unit?: string
|
||||
}
|
||||
|
||||
export interface PublicIoOrderHistoryRecord {
|
||||
kind: 'inbound' | 'outbound' | string
|
||||
orderId: string
|
||||
@@ -66,6 +74,11 @@ export interface PublicIoOrderHistoryRecord {
|
||||
supplierName?: string | null
|
||||
customerName?: string | null
|
||||
vehicleNo?: string | null
|
||||
pickupTime?: string | null
|
||||
deliveryTime?: string | null
|
||||
pickupAddress?: string | null
|
||||
destinationAddress?: string | null
|
||||
products?: PublicIoOrderHistoryProduct[]
|
||||
siteAccessToken?: string | null
|
||||
siteUrl?: string | null
|
||||
status?: string | null
|
||||
|
||||
@@ -64,6 +64,14 @@ export interface PublicUploadResult {
|
||||
fileName?: string
|
||||
}
|
||||
|
||||
export interface PublicTransportHistoryProduct {
|
||||
productName: string
|
||||
model?: string
|
||||
packageSpec?: string
|
||||
quantity?: number | null
|
||||
unit?: string
|
||||
}
|
||||
|
||||
export interface PublicTransportHistoryRecord {
|
||||
planId: string
|
||||
planNo: string
|
||||
@@ -75,6 +83,7 @@ export interface PublicTransportHistoryRecord {
|
||||
deliveryTime?: string
|
||||
pickupAddress?: string
|
||||
destinationAddress?: string
|
||||
products?: PublicTransportHistoryProduct[]
|
||||
planVoided?: boolean
|
||||
planArchived?: boolean
|
||||
statusLabel?: string
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
<template>
|
||||
<div v-if="hasSelection" class="list-export-dropdown">
|
||||
<el-button
|
||||
class="btn-ghost list-export-dropdown__main"
|
||||
:disabled="disabled"
|
||||
:loading="exporting"
|
||||
@click="handleExportFiltered"
|
||||
>
|
||||
<el-icon><Download /></el-icon>
|
||||
导出筛选结果
|
||||
</el-button>
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
:disabled="disabled || exporting"
|
||||
@command="handleCommand"
|
||||
>
|
||||
<el-button class="btn-ghost list-export-dropdown__caret" :disabled="disabled || exporting">
|
||||
<el-icon><ArrowDown /></el-icon>
|
||||
<el-button class="btn-ghost" :disabled="disabled" :loading="exporting">
|
||||
<el-icon><Download /></el-icon>
|
||||
导出
|
||||
<el-icon class="list-export-dropdown__caret-icon"><ArrowDown /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="selected" :disabled="!selectedIds?.length">
|
||||
导出已选
|
||||
<el-dropdown-item command="filtered">导出筛选结果</el-dropdown-item>
|
||||
<el-dropdown-item command="selected" :disabled="!selectedCount">
|
||||
{{ selectedCount ? `导出已选(${selectedCount})` : '导出已选' }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
@@ -40,7 +34,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { ArrowDown, Download } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
@@ -77,6 +71,8 @@
|
||||
|
||||
const exporting = ref(false)
|
||||
|
||||
const selectedCount = computed(() => props.selectedIds?.length || 0)
|
||||
|
||||
function buildPayload(withIds: boolean): ListExportPayload {
|
||||
const payload: ListExportPayload = { ...props.getFilterParams() }
|
||||
if (props.visibleColumns?.length) {
|
||||
@@ -111,6 +107,7 @@
|
||||
}
|
||||
|
||||
function handleCommand(cmd: string) {
|
||||
if (cmd === 'filtered') void runExport(false)
|
||||
if (cmd === 'selected') void runExport(true)
|
||||
}
|
||||
</script>
|
||||
@@ -118,7 +115,7 @@
|
||||
<style scoped lang="scss">
|
||||
.list-export-dropdown {
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
|
||||
:deep(.el-button) {
|
||||
@@ -129,16 +126,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.list-export-dropdown__main {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
margin-right: -1px;
|
||||
}
|
||||
|
||||
.list-export-dropdown__caret {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
min-width: 36px;
|
||||
padding: 0 10px;
|
||||
.list-export-dropdown__caret-icon {
|
||||
margin-left: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -36,6 +36,7 @@
|
||||
value-format="YYYY-MM-DD"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
@change="handlePlanDateChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="归属公司" prop="belongsCompany">
|
||||
@@ -383,14 +384,18 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="pl-plan-logistics-block">
|
||||
<div class="pl-plan-logistics-block-head">
|
||||
<div class="pl-plan-logistics-block-wrap">
|
||||
<el-button
|
||||
class="pl-plan-logistics-swap-btn"
|
||||
text
|
||||
type="primary"
|
||||
@click="handleSwapPickupDelivery"
|
||||
>
|
||||
<el-icon><Sort /></el-icon>取送货互换
|
||||
</el-button>
|
||||
<div class="pl-plan-logistics-block">
|
||||
<h4 class="pl-plan-subtitle">送货信息</h4>
|
||||
<el-button text type="primary" @click="handleSwapPickupDelivery">
|
||||
<el-icon><Sort /></el-icon>取送货互换
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="form-grid-2">
|
||||
<div class="form-grid-2">
|
||||
<el-form-item label="送货地址" class="form-col-span-2">
|
||||
<PlAddressWithLibrary
|
||||
v-model="formData.destinationAddress"
|
||||
@@ -415,6 +420,7 @@
|
||||
<el-form-item label="注意事项" class="form-col-span-2">
|
||||
<el-input v-model="formData.destinationNotes" placeholder="送货注意事项" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1339,21 +1345,12 @@ function resetForm() {
|
||||
basicFormRef.value?.clearValidate()
|
||||
}
|
||||
|
||||
/** 新增时:取货/送达时间默认跟随计划日期;已手改则不覆盖 */
|
||||
watch(
|
||||
() => formData.planDate,
|
||||
(next, prev) => {
|
||||
if (isEdit.value || isCopy.value) return
|
||||
const nextVal = next || ''
|
||||
const prevVal = prev || ''
|
||||
if (!formData.pickupTime || formData.pickupTime === prevVal) {
|
||||
formData.pickupTime = nextVal
|
||||
}
|
||||
if (!formData.deliveryTime || formData.deliveryTime === prevVal) {
|
||||
formData.deliveryTime = nextVal
|
||||
}
|
||||
}
|
||||
)
|
||||
/** 计划日期变更时,取货/送货时间始终跟随;二者仍可单独调整 */
|
||||
function handlePlanDateChange(val: string | null) {
|
||||
const nextVal = val || ''
|
||||
formData.pickupTime = nextVal
|
||||
formData.deliveryTime = nextVal
|
||||
}
|
||||
|
||||
function handleOpened() {
|
||||
loadMasterData().then(async () => {
|
||||
@@ -1792,17 +1789,6 @@ async function handleSubmit(mode: 'save' | 'saveAndArrange' = 'save') {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.pl-plan-logistics-block-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.pl-plan-logistics-block-head .pl-plan-subtitle {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pl-plan-party-select-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
@@ -1873,12 +1859,30 @@ async function handleSubmit(mode: 'save' | 'saveAndArrange' = 'save') {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.pl-plan-logistics-row {
|
||||
margin-top: 34px;
|
||||
}
|
||||
|
||||
.pl-plan-party-row .pl-plan-party-block,
|
||||
.pl-plan-logistics-row .pl-plan-logistics-block {
|
||||
.pl-plan-logistics-row .pl-plan-logistics-block,
|
||||
.pl-plan-logistics-row .pl-plan-logistics-block-wrap {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.pl-plan-logistics-block-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pl-plan-logistics-swap-btn {
|
||||
position: absolute;
|
||||
top: -32px;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
height: 26px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.pl-plan-flow-bridge {
|
||||
flex: 0 0 88px;
|
||||
display: flex;
|
||||
@@ -1934,10 +1938,6 @@ async function handleSubmit(mode: 'save' | 'saveAndArrange' = 'save') {
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
.pl-plan-logistics-block-head {
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,27 @@ dbAxios.interceptors.request.use(async (config: InternalAxiosRequestConfig) => {
|
||||
})
|
||||
|
||||
dbAxios.interceptors.response.use(
|
||||
(res) => res.data,
|
||||
async (res) => {
|
||||
if (res.config.responseType === 'blob') {
|
||||
const contentType = String(res.headers['content-type'] || '')
|
||||
if (contentType.includes('application/json')) {
|
||||
const text = await (res.data as Blob).text()
|
||||
try {
|
||||
const json = JSON.parse(text) as { detail?: string; msg?: string }
|
||||
const message =
|
||||
typeof json.detail === 'string'
|
||||
? json.detail
|
||||
: json.msg || '导出失败'
|
||||
ElMessage.error(message)
|
||||
return Promise.reject(new Error(message))
|
||||
} catch {
|
||||
/* 非 JSON blob 直出 */
|
||||
}
|
||||
}
|
||||
return res.data
|
||||
}
|
||||
return res.data
|
||||
},
|
||||
async (err) => {
|
||||
const status = err.response?.status
|
||||
const config = err.config as RetryableConfig | undefined
|
||||
@@ -142,16 +162,36 @@ dbAxios.interceptors.response.use(
|
||||
|
||||
const showErrorMessage = config?.showErrorMessage !== false
|
||||
if (showErrorMessage) {
|
||||
const detail = err.response?.data?.detail
|
||||
const message =
|
||||
typeof detail === 'string'
|
||||
? detail
|
||||
: Array.isArray(detail)
|
||||
? detail.map((x: { msg?: string }) => x.msg).filter(Boolean).join(';')
|
||||
: err.response?.data?.msg
|
||||
let message: string | undefined
|
||||
const data = err.response?.data
|
||||
if (data instanceof Blob) {
|
||||
try {
|
||||
const text = await data.text()
|
||||
const json = JSON.parse(text) as { detail?: string; msg?: string }
|
||||
message = typeof json.detail === 'string' ? json.detail : json.msg
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
} else {
|
||||
const detail = data?.detail
|
||||
message =
|
||||
typeof detail === 'string'
|
||||
? detail
|
||||
: Array.isArray(detail)
|
||||
? detail.map((x: { msg?: string }) => x.msg).filter(Boolean).join(';')
|
||||
: data?.msg
|
||||
}
|
||||
ElMessage.error(message || err.message || '网络异常')
|
||||
}
|
||||
return Promise.reject(err)
|
||||
return Promise.reject(
|
||||
err instanceof Error && err.message
|
||||
? err
|
||||
: new Error(
|
||||
(typeof err.response?.data?.detail === 'string'
|
||||
? err.response.data.detail
|
||||
: err.message) || '网络异常'
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -185,6 +185,14 @@
|
||||
<el-icon><CircleClose /></el-icon>标为无效
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="exportClue"
|
||||
:get-filter-params="getClueExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="ids.map(String)"
|
||||
:visible-columns="clueExportColumns"
|
||||
filename="线索列表.xlsx"
|
||||
/>
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -504,6 +512,7 @@
|
||||
import AssignForm from './assignForm.vue'
|
||||
import InvalidForm from './invalidForm.vue'
|
||||
import DetailDrawer from './detailDrawer.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
@@ -579,12 +588,29 @@
|
||||
]
|
||||
})
|
||||
|
||||
const clueExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('company')) cols.unshift('company')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getClueExportFilterParams() {
|
||||
const params = buildQueryParams()
|
||||
delete params.pageNum
|
||||
delete params.pageSize
|
||||
if (activeView.value === 'mine') params.viewMode = 'mine'
|
||||
else if (activeView.value === 'toFollow') params.viewType = 'toFollow'
|
||||
else if (activeView.value === 'today') params.viewType = 'todayNew'
|
||||
else if (activeView.value === 'converted') params.viewType = 'converted'
|
||||
return params
|
||||
}
|
||||
|
||||
|
||||
const importDialogVisible = ref(false)
|
||||
const importFileList = ref<UploadFile[]>([])
|
||||
const importLoading = ref(false)
|
||||
const importUpdateSupport = ref(false)
|
||||
const templateLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
|
||||
const canConvertSelected = computed(() => {
|
||||
if (selectedRows.value.length !== 1) return false
|
||||
@@ -852,29 +878,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handleExport() {
|
||||
exportLoading.value = true
|
||||
try {
|
||||
const params = buildQueryParams()
|
||||
const res = await exportClue(params)
|
||||
const blob =
|
||||
res instanceof Blob
|
||||
? res
|
||||
: new Blob([res as BlobPart], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `线索列表_${new Date().getTime()}.xlsx`
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
} catch {
|
||||
ElMessage.error('导出失败')
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watchDebounced(
|
||||
() => ({ ...searchForm, dateRange: dateRange.value }),
|
||||
|
||||
@@ -130,9 +130,14 @@
|
||||
>
|
||||
<el-icon><Upload /></el-icon>上传扫描件
|
||||
</el-button>
|
||||
<el-button class="btn-ghost" :loading="exportLoading" @click="handleExport">
|
||||
<el-icon><Download /></el-icon>导出
|
||||
</el-button>
|
||||
<ListExportDropdown
|
||||
:export-fn="exportContract"
|
||||
:get-filter-params="getContractExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="ids.map(String)"
|
||||
:visible-columns="contractExportColumns"
|
||||
filename="合同列表.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
@@ -562,6 +567,7 @@ import {
|
||||
openCrmAttachmentPreviewInNewTab
|
||||
} from '@/utils/crm-attachment'
|
||||
import ListToolbarDateShortcuts from '@/components/core/list-toolbar-date-shortcuts/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListColumnStatsRow from '@/components/business/list-column-stats-row/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
@@ -578,7 +584,6 @@ const isManageMode = computed(() => props.mode === 'manage')
|
||||
const pageTitle = computed(() => (isManageMode.value ? '合同管理' : '合同审批'))
|
||||
|
||||
const userStore = useUserStore();
|
||||
const exportLoading = ref(false);
|
||||
|
||||
/** 当前登录用户 ID(后端 current-user 返回 id,兼容历史 userId 字段) */
|
||||
const resolveCurrentUserId = (): string => {
|
||||
@@ -1108,29 +1113,26 @@ const handleView = (row?: ContractVO) => {
|
||||
contractDetailRef.value?.open(targetRow.id);
|
||||
};
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
exportLoading.value = true;
|
||||
try {
|
||||
const res = await exportContract({ ...queryParams.value });
|
||||
const blob =
|
||||
res instanceof Blob
|
||||
? res
|
||||
: new Blob([res as any], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = `contract_${new Date().getTime()}.xlsx`;
|
||||
link.click();
|
||||
URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error('导出失败:', error);
|
||||
} finally {
|
||||
exportLoading.value = false;
|
||||
const contractExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('contractNo')) cols.unshift('contractNo')
|
||||
if (!cols.includes('contractName')) {
|
||||
const idx = cols.indexOf('contractNo')
|
||||
cols.splice(idx + 1, 0, 'contractName')
|
||||
}
|
||||
};
|
||||
return cols
|
||||
})
|
||||
|
||||
function getContractExportFilterParams() {
|
||||
const params: Record<string, any> = { ...queryParams.value }
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
params.signDateBegin = dateRange.value[0]
|
||||
params.signDateEnd = dateRange.value[1]
|
||||
}
|
||||
delete params.pageNum
|
||||
delete params.pageSize
|
||||
return params
|
||||
}
|
||||
|
||||
/** 提交审批(单条) */
|
||||
const handleSubmit = (row?: ContractVO) => {
|
||||
|
||||
@@ -70,13 +70,14 @@
|
||||
@search="handleQuickSearch"
|
||||
@clear="handleQuickSearchClear"
|
||||
/>
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
:loading="exportLoading"
|
||||
@click="handleExport"
|
||||
>
|
||||
<el-icon><Download /></el-icon>导出
|
||||
</el-button>
|
||||
<ListExportDropdown
|
||||
:export-fn="exportApproval"
|
||||
:get-filter-params="getApprovalExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="approvalExportColumns"
|
||||
filename="合同审批记录.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
@@ -266,6 +267,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ContractApproval">
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
@@ -319,6 +321,24 @@
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('crm_contract_approval_visible_columns', listColumnDefs)
|
||||
|
||||
const approvalExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('contractNo')) cols.unshift('contractNo')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getApprovalExportFilterParams() {
|
||||
const params: Record<string, any> = { ...queryParams.value }
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
params.beginTime = dateRange.value[0]
|
||||
params.endTime = dateRange.value[1]
|
||||
}
|
||||
delete params.pageNum
|
||||
delete params.pageSize
|
||||
return params
|
||||
}
|
||||
|
||||
|
||||
const queryParams = ref<ApprovalQuery>({
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
@@ -356,7 +376,6 @@
|
||||
const loading = ref(true)
|
||||
const selectedRows = ref<ApprovalVO[]>([])
|
||||
const submitLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
const total = ref(0)
|
||||
const dateRange = ref<[string, string]>()
|
||||
|
||||
@@ -538,36 +557,6 @@
|
||||
viewDialog.data = res.data
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
queryParams.value.beginTime = dateRange.value[0]
|
||||
queryParams.value.endTime = dateRange.value[1]
|
||||
} else {
|
||||
queryParams.value.beginTime = undefined
|
||||
queryParams.value.endTime = undefined
|
||||
}
|
||||
exportLoading.value = true
|
||||
try {
|
||||
const res = await exportApproval(queryParams.value)
|
||||
const blob =
|
||||
res instanceof Blob
|
||||
? res
|
||||
: new Blob([res as BlobPart], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `contract_approval_${new Date().getTime()}.xlsx`
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
$modal.msgError('导出失败')
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList()
|
||||
|
||||
@@ -119,13 +119,14 @@
|
||||
>
|
||||
<el-icon><RefreshLeft /></el-icon>撤回
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
:loading="exportLoading"
|
||||
@click="handleExport"
|
||||
>
|
||||
<el-icon><Download /></el-icon>导出
|
||||
</el-button>
|
||||
<ListExportDropdown
|
||||
:export-fn="exportChange"
|
||||
:get-filter-params="getChangeExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="changeExportColumns"
|
||||
filename="合同变更.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
@@ -402,6 +403,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ContractChange">
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
@@ -472,6 +474,24 @@
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('crm_contract_change_visible_columns', listColumnDefs)
|
||||
|
||||
const changeExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('contractNo')) cols.unshift('contractNo')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getChangeExportFilterParams() {
|
||||
const params: Record<string, any> = { ...queryParams.value }
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
params.beginTime = dateRange.value[0]
|
||||
params.endTime = dateRange.value[1]
|
||||
}
|
||||
delete params.pageNum
|
||||
delete params.pageSize
|
||||
return params
|
||||
}
|
||||
|
||||
|
||||
const queryParams = ref<ChangeQuery>({
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
@@ -505,7 +525,6 @@
|
||||
const selectedRows = ref<ChangeVO[]>([])
|
||||
const loading = ref(true)
|
||||
const submitLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
const total = ref(0)
|
||||
const ids = ref<number[]>([])
|
||||
const dateRange = ref<[string, string]>()
|
||||
@@ -757,36 +776,6 @@
|
||||
await refreshViewDialogIfOpen()
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
if (dateRange.value && dateRange.value.length === 2) {
|
||||
queryParams.value.beginTime = dateRange.value[0]
|
||||
queryParams.value.endTime = dateRange.value[1]
|
||||
} else {
|
||||
queryParams.value.beginTime = undefined
|
||||
queryParams.value.endTime = undefined
|
||||
}
|
||||
exportLoading.value = true
|
||||
try {
|
||||
const res = await exportChange(queryParams.value)
|
||||
const blob =
|
||||
res instanceof Blob
|
||||
? res
|
||||
: new Blob([res as BlobPart], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `contract_change_${new Date().getTime()}.xlsx`
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
$modal.msgError('导出失败')
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
dialog.visible = false
|
||||
|
||||
@@ -75,13 +75,14 @@
|
||||
>
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-button>
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
:loading="exportLoading"
|
||||
@click="handleExport"
|
||||
>
|
||||
<el-icon><Download /></el-icon>导出
|
||||
</el-button>
|
||||
<ListExportDropdown
|
||||
:export-fn="exportTemplate"
|
||||
:get-filter-params="getTemplateExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="templateExportColumns"
|
||||
filename="合同模板.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
@@ -332,6 +333,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ContractTemplate">
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
@@ -397,6 +399,20 @@
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('crm_contract_template_visible_columns', listColumnDefs)
|
||||
|
||||
const templateExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('templateName')) cols.unshift('templateName')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getTemplateExportFilterParams() {
|
||||
const params: Record<string, any> = { ...queryParams.value }
|
||||
delete params.pageNum
|
||||
delete params.pageSize
|
||||
return params
|
||||
}
|
||||
|
||||
|
||||
const queryParams = ref<TemplateQuery>({
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
@@ -428,7 +444,6 @@
|
||||
const selectedRows = ref<TemplateVO[]>([])
|
||||
const loading = ref(true)
|
||||
const submitLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
const total = ref(0)
|
||||
const ids = ref<number[]>([])
|
||||
|
||||
@@ -618,29 +633,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
exportLoading.value = true
|
||||
try {
|
||||
const res = await exportTemplate(queryParams.value)
|
||||
const blob =
|
||||
res instanceof Blob
|
||||
? res
|
||||
: new Blob([res as BlobPart], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `contract_template_${new Date().getTime()}.xlsx`
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
$modal.msgError('导出失败')
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
dialog.visible = false
|
||||
|
||||
@@ -161,6 +161,14 @@
|
||||
放入公海
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportCustomer"
|
||||
:get-filter-params="getCustomerExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="customerExportColumns"
|
||||
filename="客户列表.xlsx"
|
||||
/>
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -681,6 +689,7 @@ import TransferForm from './TransferDialog.vue'
|
||||
import IntoPoolForm from './IntoPoolDialog.vue'
|
||||
import FollowForm from './FollowFormDialog.vue'
|
||||
import DealForm from './DealDialog.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
@@ -780,6 +789,23 @@ const {
|
||||
]
|
||||
})
|
||||
|
||||
const customerExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('customerName')) cols.unshift('customerName')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getCustomerExportFilterParams() {
|
||||
const params = buildQueryParams()
|
||||
delete params.page
|
||||
delete params.pageSize
|
||||
if (activeView.value && activeView.value !== 'all') {
|
||||
params.viewMode = activeView.value
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
|
||||
// 子组件引用
|
||||
const customerFormRef = ref<InstanceType<typeof CustomerForm>>()
|
||||
const customerDetailRef = ref<InstanceType<typeof CustomerDetail>>()
|
||||
@@ -986,24 +1012,6 @@ async function handleDelete(row?: any) {
|
||||
await getList()
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
async function handleExport() {
|
||||
try {
|
||||
const params = buildQueryParams()
|
||||
const res = await fetchExportCustomer(params)
|
||||
const blob = new Blob([res as any], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `客户列表_${new Date().getTime()}.xlsx`
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
} catch {
|
||||
ElMessage.error('导出失败')
|
||||
}
|
||||
}
|
||||
|
||||
watchDebounced(
|
||||
() => ({ ...searchForm, dateRange: dateRange.value }),
|
||||
|
||||
@@ -92,6 +92,14 @@
|
||||
手动执行
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportPoolRules"
|
||||
:get-filter-params="getPoolRuleExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="poolRuleExportColumns"
|
||||
filename="公海规则.xlsx"
|
||||
/>
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -227,6 +235,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { watchDebounced } from '@vueuse/core'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
@@ -247,6 +256,7 @@ import {
|
||||
fetchDeletePoolRule,
|
||||
fetchTogglePoolRule,
|
||||
fetchExecutePoolRules,
|
||||
fetchExportPoolRules,
|
||||
} from '@/api/crm/pool'
|
||||
import RuleDialog from './components/RuleDialog.vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
@@ -276,6 +286,22 @@ const {
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('crm_pool_rule_visible_columns', listColumnDefs)
|
||||
|
||||
const poolRuleExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('poolName')) cols.unshift('poolName')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getPoolRuleExportFilterParams() {
|
||||
const quickKeyword = quickSearchKeyword.value?.trim()
|
||||
return {
|
||||
poolName: quickKeyword || searchForm.poolName || undefined,
|
||||
ruleType: searchForm.ruleType || undefined,
|
||||
status: searchForm.status || undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 数据列表
|
||||
const ruleList = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
|
||||
@@ -71,6 +71,14 @@
|
||||
分配客户
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportPoolCustomers"
|
||||
:get-filter-params="getPoolExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="ids"
|
||||
:visible-columns="poolExportColumns"
|
||||
filename="公海客户.xlsx"
|
||||
/>
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -536,7 +544,8 @@ import {
|
||||
More,
|
||||
} from '@element-plus/icons-vue'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { fetchPoolCustomerList } from '@/api/crm/pool'
|
||||
import { fetchPoolCustomerList, fetchExportPoolCustomers } from '@/api/crm/pool'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
@@ -623,6 +632,24 @@ const {
|
||||
]
|
||||
})
|
||||
|
||||
const poolExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('customerName')) cols.unshift('customerName')
|
||||
if (!cols.includes('customerNo')) cols.unshift('customerNo')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getPoolExportFilterParams() {
|
||||
const quickKeyword = quickSearchKeyword.value?.trim()
|
||||
const filterKeyword =
|
||||
searchForm.customerName?.trim() || searchForm.customerNo?.trim() || undefined
|
||||
return {
|
||||
keyword: quickKeyword || filterKeyword,
|
||||
level: searchForm.level || undefined
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const claimDialogRef = ref()
|
||||
const assignDialogRef = ref()
|
||||
const customerDetailRef = ref()
|
||||
|
||||
@@ -135,6 +135,14 @@
|
||||
<el-icon><User /></el-icon>批量分配
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="exportOpportunity"
|
||||
:get-filter-params="getOpportunityExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="ids.map(String)"
|
||||
:visible-columns="opportunityExportColumns"
|
||||
filename="商机列表.xlsx"
|
||||
/>
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -587,6 +595,7 @@
|
||||
import BatchUpdateStageDialog from './components/BatchUpdateStageDialog.vue'
|
||||
import BatchUpdateDateDialog from './components/BatchUpdateDateDialog.vue'
|
||||
import OpportunityDetailDrawer from './components/OpportunityDetailDrawer.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
|
||||
@@ -594,7 +603,6 @@
|
||||
const router = useRouter()
|
||||
|
||||
const selectedRows = ref<OpportunityVO[]>([])
|
||||
const exportLoading = ref(false)
|
||||
const assignLoading = ref(false)
|
||||
|
||||
// 列配置
|
||||
@@ -841,23 +849,6 @@
|
||||
await getList()
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
exportLoading.value = true
|
||||
try {
|
||||
const blob = await exportOpportunity({ ...queryParams.value })
|
||||
const url = window.URL.createObjectURL(blob as Blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `商机数据_${Date.now()}.xlsx`
|
||||
link.click()
|
||||
window.URL.revokeObjectURL(url)
|
||||
} catch {
|
||||
ElMessage.error('导出失败')
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 变更阶段 */
|
||||
const handleChangeStage = (row?: OpportunityVO) => {
|
||||
|
||||
@@ -111,6 +111,14 @@
|
||||
<el-icon><CircleClose /></el-icon>作废
|
||||
</el-button>
|
||||
|
||||
<ListExportDropdown
|
||||
:export-fn="exportQuote"
|
||||
:get-filter-params="getQuoteExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="ids.map(String)"
|
||||
:visible-columns="quoteExportColumns"
|
||||
filename="报价单列表.xlsx"
|
||||
/>
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
:column-defs="listColumnDefs"
|
||||
@@ -867,6 +875,7 @@ import { fitRichTextTablesToMaxWidth } from '@/utils/tinymce-table-excel-resize'
|
||||
import QuoteFormDialog from './components/QuoteFormDialog.vue'
|
||||
import QuoteDetailDialog from './components/QuoteDetailDialog.vue'
|
||||
import ListToolbarDateShortcuts from '@/components/core/list-toolbar-date-shortcuts/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import { usePersistedListColumns } from '@/composables/usePersistedListColumns'
|
||||
import {
|
||||
@@ -1001,6 +1010,20 @@ const {
|
||||
]
|
||||
})
|
||||
|
||||
const quoteExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('quoteNo')) cols.unshift('quoteNo')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getQuoteExportFilterParams() {
|
||||
const params = { ...buildListQueryParams() }
|
||||
delete params.pageNum
|
||||
delete params.pageSize
|
||||
return params
|
||||
}
|
||||
|
||||
|
||||
type QuoteViewName = 'all' | 'submitted' | 'accepted'
|
||||
|
||||
interface TabFilterState {
|
||||
@@ -1054,7 +1077,6 @@ const loading = ref(true);
|
||||
const total = ref(0);
|
||||
const expandLoadingMap = reactive<Record<string, boolean>>({});
|
||||
const selectedRows = ref<QuoteVO[]>([]);
|
||||
const exportLoading = ref(false);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const ids = ref<(string | number)[]>([]);
|
||||
@@ -1463,29 +1485,6 @@ const handleQuickSearchClear = () => {
|
||||
handleQuickSearch();
|
||||
};
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
exportLoading.value = true;
|
||||
try {
|
||||
const res = await exportQuote(buildListQueryParams())
|
||||
const blob =
|
||||
res instanceof Blob
|
||||
? res
|
||||
: new Blob([res as any], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
})
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `quote_${new Date().getTime()}.xlsx`
|
||||
link.click()
|
||||
URL.revokeObjectURL(url)
|
||||
} catch (error) {
|
||||
console.error('导出失败:', error)
|
||||
} finally {
|
||||
exportLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 报价分析 */
|
||||
const handleStatistics = () => {
|
||||
|
||||
@@ -112,10 +112,14 @@
|
||||
<el-icon><Delete /></el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
<el-button class="btn-ghost" :loading="exportLoading" @click="handleExport">
|
||||
<el-icon><Download /></el-icon>
|
||||
导出 Excel
|
||||
</el-button>
|
||||
<ListExportDropdown
|
||||
:export-fn="(payload) => inventoryApi.export(payload)"
|
||||
:get-filter-params="getInventoryExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="inventoryExportColumns"
|
||||
filename="出入库列表.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
@@ -536,6 +540,7 @@
|
||||
import DbCrmCustomerSelect from '@/components/business/db/DbCrmCustomerSelect.vue'
|
||||
import ListToolbarDateShortcuts from '@/components/core/list-toolbar-date-shortcuts/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListColumnStatsRow from '@/components/business/list-column-stats-row/index.vue'
|
||||
import type { StatsRowColumn } from '@/utils/list-column-stats'
|
||||
@@ -592,6 +597,17 @@
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('db-inventory-list-columns', listColumnDefs)
|
||||
|
||||
const inventoryExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('planNo')) cols.unshift('planNo')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getInventoryExportFilterParams() {
|
||||
return { ...buildListQueryParams() }
|
||||
}
|
||||
|
||||
|
||||
const inventoryTableWrapRef = ref<HTMLElement | null>(null)
|
||||
const inventoryStatsRowRef = ref<{ resync?: () => void } | null>(null)
|
||||
|
||||
@@ -631,7 +647,6 @@
|
||||
return (row as any)?.[prop]
|
||||
}
|
||||
|
||||
const exportLoading = ref(false)
|
||||
const saving = ref(false)
|
||||
const tableData = ref<InventoryRecord[]>([])
|
||||
const allRecords = ref<InventoryRecord[]>([])
|
||||
@@ -1114,52 +1129,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
exportLoading.value = true
|
||||
try {
|
||||
let records = await inventoryApi.list(buildListQueryParams())
|
||||
if (records.length === 0) {
|
||||
$modal.msgWarning('没有数据可导出')
|
||||
return
|
||||
}
|
||||
|
||||
let list = [...records]
|
||||
if (sortProp.value && sortOrder.value) {
|
||||
list.sort((a, b) => compare(a, b, sortProp.value, sortOrder.value!))
|
||||
}
|
||||
|
||||
const headers = ['日期', '往来单位', '业务类型', '产品', '数量(吨)', '车牌号', '计划号', '备注']
|
||||
const csvContent = [
|
||||
headers.join(','),
|
||||
...list.map((r) =>
|
||||
[
|
||||
r.date,
|
||||
r.partnerCompany,
|
||||
r.businessType,
|
||||
r.product,
|
||||
r.quantity,
|
||||
r.vehicleNo,
|
||||
r.planNo || '',
|
||||
r.remarks || ''
|
||||
].join(',')
|
||||
)
|
||||
].join('\n')
|
||||
const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
const now = new Date()
|
||||
const stamp = `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}_${pad2(now.getHours())}${pad2(now.getMinutes())}${pad2(now.getSeconds())}`
|
||||
a.download = `出入库列表_${stamp}.csv`
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
$modal.msgSuccess('导出成功')
|
||||
} catch (error) {
|
||||
console.error('导出失败', error)
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
useDbInstantSearch(
|
||||
() => ({
|
||||
|
||||
@@ -112,10 +112,14 @@
|
||||
<el-icon><Delete /></el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
<el-button class="btn-ghost" :loading="exportLoading" @click="handleExport">
|
||||
<el-icon><Download /></el-icon>
|
||||
导出 Excel
|
||||
</el-button>
|
||||
<ListExportDropdown
|
||||
:export-fn="(payload) => planApi.export(payload)"
|
||||
:get-filter-params="getPlanExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="planExportColumns"
|
||||
filename="计划列表.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
@@ -488,6 +492,7 @@
|
||||
import DbCrmCustomerSelect from '@/components/business/db/DbCrmCustomerSelect.vue'
|
||||
import ListToolbarDateShortcuts from '@/components/core/list-toolbar-date-shortcuts/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListColumnStatsRow from '@/components/business/list-column-stats-row/index.vue'
|
||||
import type { StatsRowColumn } from '@/utils/list-column-stats'
|
||||
@@ -534,6 +539,17 @@
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('db-plans-list-columns', listColumnDefs)
|
||||
|
||||
const planExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('planNo')) cols.unshift('planNo')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getPlanExportFilterParams() {
|
||||
return { ...buildListQueryParams() }
|
||||
}
|
||||
|
||||
|
||||
const plansTableWrapRef = ref<HTMLElement | null>(null)
|
||||
const plansStatsRowRef = ref<{ resync?: () => void } | null>(null)
|
||||
|
||||
@@ -565,7 +581,6 @@
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
const saving = ref(false)
|
||||
const tableData = ref<Plan[]>([])
|
||||
const total = ref(0)
|
||||
@@ -993,64 +1008,6 @@
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
exportLoading.value = true
|
||||
try {
|
||||
const records = await fetchFilteredPlans()
|
||||
if (records.length === 0) {
|
||||
$modal.msgWarning('没有数据可导出')
|
||||
return
|
||||
}
|
||||
|
||||
const headers = [
|
||||
'计划号',
|
||||
'往来单位',
|
||||
'计划日期',
|
||||
'起始日期',
|
||||
'截止日期',
|
||||
'产品',
|
||||
'规格',
|
||||
'车牌号',
|
||||
'计划量',
|
||||
'已执行量',
|
||||
'执行状态',
|
||||
'备注'
|
||||
]
|
||||
const csvContent = [
|
||||
headers.join(','),
|
||||
...records.map((r) =>
|
||||
[
|
||||
r.planNo,
|
||||
r.customerName,
|
||||
r.planDate,
|
||||
r.startDate,
|
||||
r.endDate,
|
||||
r.product,
|
||||
r.specification,
|
||||
r.vehicleNo,
|
||||
r.plannedQuantity,
|
||||
r.executedQuantity || 0,
|
||||
r.executionStatus,
|
||||
r.remarks || ''
|
||||
].join(',')
|
||||
)
|
||||
].join('\n')
|
||||
const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
const now = new Date()
|
||||
const stamp = `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}_${pad2(now.getHours())}${pad2(now.getMinutes())}${pad2(now.getSeconds())}`
|
||||
a.download = `计划列表_${stamp}.csv`
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
$modal.msgSuccess('导出成功')
|
||||
} catch (error) {
|
||||
console.error('导出失败', error)
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
useDbInstantSearch(
|
||||
() => ({
|
||||
|
||||
@@ -91,10 +91,14 @@
|
||||
<el-icon><Close /></el-icon>
|
||||
作废
|
||||
</el-button>
|
||||
<el-button class="btn-ghost" :loading="exportLoading" @click="handleExport">
|
||||
<el-icon><Download /></el-icon>
|
||||
导出 Excel
|
||||
</el-button>
|
||||
<ListExportDropdown
|
||||
:export-fn="(payload) => weighingApi.export(payload)"
|
||||
:get-filter-params="getWeighingExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="weighingExportColumns"
|
||||
filename="地磅单列表.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions
|
||||
:loading="loading"
|
||||
@@ -527,6 +531,7 @@
|
||||
import DbCrmCustomerSelect from '@/components/business/db/DbCrmCustomerSelect.vue'
|
||||
import ListToolbarDateShortcuts from '@/components/core/list-toolbar-date-shortcuts/index.vue'
|
||||
import ListQuickSearchInput from '@/components/business/list-quick-search-input/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListColumnStatsRow from '@/components/business/list-column-stats-row/index.vue'
|
||||
import type { StatsRowColumn } from '@/utils/list-column-stats'
|
||||
@@ -581,6 +586,17 @@
|
||||
resetToDefault
|
||||
} = usePersistedListColumns('db-weighing-list-columns', listColumnDefs)
|
||||
|
||||
const weighingExportColumns = computed(() => {
|
||||
const cols = [...visibleColumns.value]
|
||||
if (!cols.includes('planNo')) cols.unshift('planNo')
|
||||
return cols
|
||||
})
|
||||
|
||||
function getWeighingExportFilterParams() {
|
||||
return { ...buildListQueryParams() }
|
||||
}
|
||||
|
||||
|
||||
const weighingTableWrapRef = ref<HTMLElement | null>(null)
|
||||
const weighingStatsRowRef = ref<{ resync?: () => void } | null>(null)
|
||||
|
||||
@@ -609,7 +625,6 @@
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
const saving = ref(false)
|
||||
const allData = ref<WeighingRecord[]>([])
|
||||
const total = ref(0)
|
||||
@@ -1075,60 +1090,6 @@
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
exportLoading.value = true
|
||||
try {
|
||||
const exportRecords = await weighingApi.list(buildListQueryParams())
|
||||
if (exportRecords.length === 0) {
|
||||
$modal.msgWarning('没有数据可导出')
|
||||
return
|
||||
}
|
||||
|
||||
const headers = [
|
||||
'车牌号',
|
||||
'货物名称',
|
||||
'业务类型',
|
||||
'毛重(kg)',
|
||||
'皮重(kg)',
|
||||
'净重(kg)',
|
||||
'毛重时间',
|
||||
'皮重时间',
|
||||
'供货单位',
|
||||
'收货单位'
|
||||
]
|
||||
const csvContent = [
|
||||
headers.join(','),
|
||||
...exportRecords.map((r) =>
|
||||
[
|
||||
r.vehicleNo,
|
||||
r.cargoName,
|
||||
r.businessType,
|
||||
r.grossWeight,
|
||||
r.tareWeight,
|
||||
r.netWeight,
|
||||
r.grossWeightTime,
|
||||
r.tareWeightTime,
|
||||
r.supplier,
|
||||
r.consignee
|
||||
].join(',')
|
||||
)
|
||||
].join('\n')
|
||||
const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8' })
|
||||
const url = URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
const now = new Date()
|
||||
const stamp = `${now.getFullYear()}${pad2(now.getMonth() + 1)}${pad2(now.getDate())}_${pad2(now.getHours())}${pad2(now.getMinutes())}${pad2(now.getSeconds())}`
|
||||
a.download = `地磅单列表_${stamp}.csv`
|
||||
a.click()
|
||||
URL.revokeObjectURL(url)
|
||||
$modal.msgSuccess('导出成功')
|
||||
} catch (error) {
|
||||
console.error('导出失败', error)
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const clearInventoryRouteQuery = () => {
|
||||
if (!route.query.inboundOutboundId) return
|
||||
|
||||
@@ -47,16 +47,14 @@
|
||||
批量删除
|
||||
</el-button>
|
||||
|
||||
<ArtExcelExport
|
||||
:data="batchExportData"
|
||||
:list-total="pagination.total"
|
||||
:load-all-data="loadAllCategoriesForExport"
|
||||
:filename="categoryExportFilename"
|
||||
sheetName="分类数据"
|
||||
:columns="categoryExportColumns"
|
||||
>
|
||||
批量导出
|
||||
</ArtExcelExport>
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportDemoCategories"
|
||||
:get-filter-params="getDemoCategoryExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="demoCategoryExportVisibleColumns"
|
||||
filename="分类数据.xlsx"
|
||||
/>
|
||||
|
||||
<ArtExcelExport
|
||||
:data="categoryImportTemplateData"
|
||||
@@ -510,7 +508,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import ListToolbarEndActions from '@/components/business/list-toolbar-end-actions/index.vue'
|
||||
import AttachmentUploadField from '@/components/business/attachment-upload-field/index.vue'
|
||||
import { useListMediaActive } from '@/composables/useListMediaActive'
|
||||
/* eslint-disable vue/no-v-model-argument */
|
||||
@@ -533,6 +532,7 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
|
||||
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
|
||||
import {
|
||||
fetchCategoryList,
|
||||
fetchExportDemoCategories,
|
||||
fetchCreateCategory,
|
||||
fetchUpdateCategory,
|
||||
fetchDeleteCategory,
|
||||
@@ -595,6 +595,24 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
|
||||
selectedRows.value = rows
|
||||
}
|
||||
|
||||
const demoCategoryExportVisibleColumns = [
|
||||
'id',
|
||||
'name',
|
||||
'parentId',
|
||||
'parentName',
|
||||
'sortOrder',
|
||||
'priceCoefficient',
|
||||
'isActive',
|
||||
'imageUrl'
|
||||
]
|
||||
|
||||
function getDemoCategoryExportFilterParams() {
|
||||
return {
|
||||
keyword: searchForm.keyword || undefined,
|
||||
isActive: searchForm.isActive === '' ? undefined : searchForm.isActive
|
||||
}
|
||||
}
|
||||
|
||||
const categoryExportFilename = 'base_category_batch_export'
|
||||
const categoryImportTemplateFilename = 'base_category_import_template'
|
||||
|
||||
|
||||
@@ -62,16 +62,14 @@
|
||||
批量删除
|
||||
</el-button>
|
||||
|
||||
<ArtExcelExport
|
||||
:data="batchExportData"
|
||||
:list-total="pagination.total"
|
||||
:load-all-data="loadAllProductsForExport"
|
||||
:filename="productExportFilename"
|
||||
sheetName="商品数据"
|
||||
:columns="productExportColumns"
|
||||
>
|
||||
批量导出
|
||||
</ArtExcelExport>
|
||||
<ListExportDropdown
|
||||
:export-fn="fetchExportDemoProducts"
|
||||
:get-filter-params="getDemoProductExportFilterParams"
|
||||
:has-selection="true"
|
||||
:selected-ids="selectedRows.map((r) => String(r.id))"
|
||||
:visible-columns="demoProductExportVisibleColumns"
|
||||
filename="商品数据.xlsx"
|
||||
/>
|
||||
|
||||
<ListToolbarEndActions :loading="loading" @refresh="loadData" />
|
||||
</div>
|
||||
@@ -925,9 +923,11 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
|
||||
} from '@element-plus/icons-vue'
|
||||
import { VueDraggable as draggable } from 'vue-draggable-plus'
|
||||
import ProductViewDialog from '@/components/business/product-view-dialog/index.vue'
|
||||
import ListExportDropdown from '@/components/business/list-export-dropdown/index.vue'
|
||||
import AttachmentUploadField from '@/components/business/attachment-upload-field/index.vue'
|
||||
import {
|
||||
fetchProductList,
|
||||
fetchExportDemoProducts,
|
||||
fetchProductDetail,
|
||||
fetchCreateProduct,
|
||||
fetchUpdateProduct,
|
||||
@@ -973,6 +973,26 @@ import ListToolbarEndActions from '@/components/business/list-toolbar-end-action
|
||||
selectedRows.value = rows
|
||||
}
|
||||
|
||||
const demoProductExportVisibleColumns = [
|
||||
'id',
|
||||
'name',
|
||||
'skuCode',
|
||||
'categoryName',
|
||||
'measureValue',
|
||||
'unitName',
|
||||
'imageUrl',
|
||||
'isActive',
|
||||
'createAt'
|
||||
]
|
||||
|
||||
function getDemoProductExportFilterParams() {
|
||||
return {
|
||||
keyword: searchForm.keyword || undefined,
|
||||
categoryId: searchForm.categoryId || undefined,
|
||||
isActive: searchForm.isActive === '' ? undefined : searchForm.isActive
|
||||
}
|
||||
}
|
||||
|
||||
const productExportFilename = 'base_product_batch_export'
|
||||
const formatMeasureCell = (v: unknown) => {
|
||||
if (v == null || v === '') return '-'
|
||||
|
||||
@@ -10,48 +10,29 @@
|
||||
/>
|
||||
|
||||
<div class="filters">
|
||||
<div class="filter-row">
|
||||
<van-field
|
||||
class="date-field"
|
||||
readonly
|
||||
is-link
|
||||
clickable
|
||||
:model-value="pickDate"
|
||||
placeholder="选择日期"
|
||||
@click="openDatePicker"
|
||||
/>
|
||||
<input
|
||||
v-model="keyword"
|
||||
type="search"
|
||||
class="search-input"
|
||||
placeholder="供方/需方"
|
||||
enterkeyhint="search"
|
||||
/>
|
||||
</div>
|
||||
<div class="chips">
|
||||
<button
|
||||
v-for="q in quickOptions"
|
||||
:key="q.offset"
|
||||
type="button"
|
||||
class="chip"
|
||||
:class="{ on: pickDate === q.ymd }"
|
||||
@click="setQuick(q.offset)"
|
||||
>
|
||||
{{ q.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-popup v-model:show="showDatePicker" position="bottom" round>
|
||||
<van-date-picker
|
||||
v-model="datePickerValue"
|
||||
title="选择日期"
|
||||
<van-calendar
|
||||
class="history-calendar"
|
||||
:poppable="false"
|
||||
:show-confirm="false"
|
||||
:show-title="false"
|
||||
:show-mark="false"
|
||||
:safe-area-inset-bottom="false"
|
||||
switch-mode="month"
|
||||
color="#059669"
|
||||
:row-height="28"
|
||||
:default-date="calendarDate"
|
||||
:min-date="minDate"
|
||||
:max-date="maxDate"
|
||||
@confirm="onDateConfirm"
|
||||
@cancel="showDatePicker = false"
|
||||
@select="onCalendarSelect"
|
||||
/>
|
||||
</van-popup>
|
||||
<input
|
||||
v-model="keyword"
|
||||
type="search"
|
||||
class="search-input"
|
||||
placeholder="车牌号/产品名称"
|
||||
enterkeyhint="search"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<van-empty v-if="errorMessage" :description="errorMessage" />
|
||||
<van-list
|
||||
@@ -72,16 +53,33 @@
|
||||
>
|
||||
<span class="index-tag">{{ index + 1 }}</span>
|
||||
<div class="record-top">
|
||||
<span class="plan-no">{{ row.orderNo || row.planNo || '—' }}</span>
|
||||
<span class="card-title">{{ cardTitle(row) }}</span>
|
||||
<span class="tag" :class="tagClass(row)">{{ row.statusLabel || '进行中' }}</span>
|
||||
</div>
|
||||
<div class="meta">类型:{{ kindLabel(row.kind) }} · 计划:{{ row.planNo || '—' }}</div>
|
||||
<div class="meta">
|
||||
往来:{{ row.partnerCompany || '—' }} · 车牌:{{ row.vehicleNo || '—' }}
|
||||
车牌:<span class="plate-hl">{{ row.vehicleNo || '—' }}</span>
|
||||
</div>
|
||||
<div class="meta">
|
||||
供方:{{ row.supplierName || '—' }} · 需方:{{ row.customerName || '—' }}
|
||||
取货:{{ formatDay(row.pickupTime) }} · 送货:{{ formatDay(row.deliveryTime) }}
|
||||
</div>
|
||||
<div class="meta">
|
||||
路线:{{ row.pickupAddress || '—' }} → {{ row.destinationAddress || '—' }}
|
||||
</div>
|
||||
<template v-if="!(row.products || []).length">
|
||||
<div class="meta">产品:—</div>
|
||||
<div class="meta">规格型号:—</div>
|
||||
<div class="meta">包装规格:—</div>
|
||||
<div class="meta">数量:— · 单位:—</div>
|
||||
</template>
|
||||
<template v-for="(prod, pIndex) in row.products || []" :key="pIndex">
|
||||
<div class="meta">产品:{{ prod.productName || '—' }}</div>
|
||||
<div class="meta">规格型号:{{ prod.model || '—' }}</div>
|
||||
<div class="meta">包装规格:{{ prod.packageSpec || '—' }}</div>
|
||||
<div class="meta">
|
||||
数量:{{ formatQty(prod.quantity) }} · 单位:{{ prod.unit || '—' }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="meta">运输计划号:{{ row.planNo || '—' }}</div>
|
||||
</div>
|
||||
</van-list>
|
||||
</div>
|
||||
@@ -99,9 +97,7 @@
|
||||
|
||||
import 'vant/es/toast/style'
|
||||
import 'vant/es/list/style'
|
||||
import 'vant/es/field/style'
|
||||
import 'vant/es/popup/style'
|
||||
import 'vant/es/date-picker/style'
|
||||
import 'vant/es/calendar/style'
|
||||
import '@/styles/public-mobile-vant.scss'
|
||||
|
||||
const PAGE_SIZE = 20
|
||||
@@ -118,19 +114,18 @@
|
||||
const records = ref<PublicIoOrderHistoryRecord[]>([])
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pickDate = ref(addDays(0))
|
||||
const pickDate = ref(formatYmd(startOfToday()))
|
||||
const calendarDate = ref(startOfToday())
|
||||
const keyword = ref('')
|
||||
const showDatePicker = ref(false)
|
||||
const datePickerValue = ref<string[]>(ymdToParts(pickDate.value))
|
||||
const minDate = new Date(new Date().getFullYear() - 2, 0, 1)
|
||||
const maxDate = new Date(new Date().getFullYear() + 2, 11, 31)
|
||||
let requestSeq = 0
|
||||
|
||||
const quickOptions = [
|
||||
{ label: '今日', offset: 0, ymd: addDays(0) },
|
||||
{ label: '明日', offset: 1, ymd: addDays(1) },
|
||||
{ label: '后天', offset: 2, ymd: addDays(2) }
|
||||
]
|
||||
function startOfToday() {
|
||||
const d = new Date()
|
||||
d.setHours(0, 0, 0, 0)
|
||||
return d
|
||||
}
|
||||
|
||||
function formatYmd(d: Date) {
|
||||
const y = d.getFullYear()
|
||||
@@ -139,34 +134,33 @@
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
function addDays(n: number) {
|
||||
const d = new Date()
|
||||
d.setHours(0, 0, 0, 0)
|
||||
d.setDate(d.getDate() + n)
|
||||
return formatYmd(d)
|
||||
function formatDay(value?: string | null) {
|
||||
if (!value) return '—'
|
||||
const normalized = String(value).replace('T', ' ')
|
||||
return normalized.length >= 10 ? normalized.slice(0, 10) : normalized
|
||||
}
|
||||
|
||||
function ymdToParts(ymd: string): string[] {
|
||||
const [y, m, d] = String(ymd || '').split('-')
|
||||
if (!y || !m || !d) return ymdToParts(addDays(0))
|
||||
return [y, m, d]
|
||||
function formatQty(value?: number | null) {
|
||||
if (value == null) return '—'
|
||||
return String(value)
|
||||
}
|
||||
|
||||
function openDatePicker() {
|
||||
datePickerValue.value = ymdToParts(pickDate.value)
|
||||
showDatePicker.value = true
|
||||
function cardTitleDate(row: PublicIoOrderHistoryRecord) {
|
||||
const fromPlan = formatDay(row.planDate)
|
||||
if (fromPlan !== '—') return fromPlan
|
||||
const fromPickup = formatDay(row.pickupTime)
|
||||
if (fromPickup !== '—') return fromPickup
|
||||
const fromDelivery = formatDay(row.deliveryTime)
|
||||
if (fromDelivery !== '—') return fromDelivery
|
||||
return pickDate.value
|
||||
}
|
||||
|
||||
function onDateConfirm({ selectedValues }: { selectedValues: string[] }) {
|
||||
pickDate.value = selectedValues.join('-')
|
||||
showDatePicker.value = false
|
||||
reload()
|
||||
}
|
||||
|
||||
function kindLabel(kind?: string) {
|
||||
if (kind === 'inbound') return '入库'
|
||||
if (kind === 'outbound') return '出库'
|
||||
return '—'
|
||||
function cardTitle(row: PublicIoOrderHistoryRecord) {
|
||||
const names = (row.products || [])
|
||||
.map((p) => (p.productName || '').trim())
|
||||
.filter(Boolean)
|
||||
const productLabel = names.length ? names.join('、') : '—'
|
||||
return `${cardTitleDate(row)} ${productLabel}`
|
||||
}
|
||||
|
||||
function tagClass(row: PublicIoOrderHistoryRecord) {
|
||||
@@ -183,9 +177,11 @@
|
||||
router.push({ name: detailRouteName(), params: { token: token.value } })
|
||||
}
|
||||
|
||||
function setQuick(offset: number) {
|
||||
pickDate.value = addDays(offset)
|
||||
datePickerValue.value = ymdToParts(pickDate.value)
|
||||
function onCalendarSelect(date: Date) {
|
||||
const next = formatYmd(date)
|
||||
if (next === pickDate.value) return
|
||||
pickDate.value = next
|
||||
calendarDate.value = date
|
||||
reload()
|
||||
}
|
||||
|
||||
@@ -283,7 +279,7 @@
|
||||
|
||||
.filters {
|
||||
margin-bottom: 12px;
|
||||
padding: 12px 14px;
|
||||
padding: 4px 4px 10px;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
border: 1px solid #e2e8f0;
|
||||
@@ -292,78 +288,45 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
|
||||
gap: 8px;
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
.history-calendar {
|
||||
height: auto;
|
||||
--van-calendar-background: #fff;
|
||||
--van-calendar-header-shadow: none;
|
||||
--van-calendar-header-title-height: 32px;
|
||||
--van-calendar-header-subtitle-font-size: 13px;
|
||||
--van-calendar-weekdays-height: 24px;
|
||||
--van-calendar-weekdays-font-size: 11px;
|
||||
--van-calendar-day-height: 28px;
|
||||
--van-calendar-day-font-size: 12px;
|
||||
--van-calendar-day-margin-bottom: 0;
|
||||
--van-calendar-selected-day-size: 26px;
|
||||
--van-primary-color: #059669;
|
||||
|
||||
.date-field {
|
||||
padding: 0 12px;
|
||||
min-height: 40px;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 8px;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
|
||||
:deep(.van-field__control) {
|
||||
font-size: 14px;
|
||||
color: #1e293b;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
:deep(.van-calendar__footer) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:deep(.van-field__right-icon) {
|
||||
margin-right: 0;
|
||||
color: #64748b;
|
||||
:deep(.van-calendar__body) {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.search-input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
width: calc(100% - 8px);
|
||||
max-width: 100%;
|
||||
min-width: 0;
|
||||
height: 40px;
|
||||
height: 36px;
|
||||
margin: 8px 4px 0;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
color: #1e293b;
|
||||
color: #0f172a;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.chips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.chip {
|
||||
height: 30px;
|
||||
padding: 0 12px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid #d1fae5;
|
||||
background: #ecfdf5;
|
||||
color: #047857;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chip.on {
|
||||
background: #059669;
|
||||
border-color: #059669;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.record-card {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
@@ -402,7 +365,7 @@
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.plan-no {
|
||||
.card-title {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
@@ -435,7 +398,7 @@
|
||||
|
||||
.meta {
|
||||
font-size: 13px;
|
||||
color: #64748b;
|
||||
color: #0f172a;
|
||||
line-height: 1.45;
|
||||
word-break: break-all;
|
||||
|
||||
@@ -443,4 +406,10 @@
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.plate-hl {
|
||||
color: #059669;
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
}
|
||||
</style>
|
||||
@@ -9,66 +9,68 @@
|
||||
@click-left="goBack"
|
||||
/>
|
||||
|
||||
<van-loading v-if="loading" vertical class="page-loading">加载中...</van-loading>
|
||||
<van-empty v-else-if="errorMessage" :description="errorMessage" />
|
||||
<van-loading v-if="bootLoading" vertical class="page-loading">加载中...</van-loading>
|
||||
<van-empty v-else-if="fatalError" :description="fatalError" />
|
||||
<template v-else>
|
||||
<div class="filters">
|
||||
<div class="filter-row">
|
||||
<van-field
|
||||
class="date-field"
|
||||
readonly
|
||||
is-link
|
||||
clickable
|
||||
:model-value="pickDate"
|
||||
placeholder="选择日期"
|
||||
@click="openDatePicker"
|
||||
/>
|
||||
<div class="chips">
|
||||
<button
|
||||
v-for="q in quickOptions"
|
||||
:key="q.offset"
|
||||
type="button"
|
||||
class="chip"
|
||||
:class="{ on: pickDate === q.ymd }"
|
||||
@click="setQuick(q.offset)"
|
||||
>
|
||||
{{ q.label }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-popup v-model:show="showDatePicker" position="bottom" round>
|
||||
<van-date-picker
|
||||
v-model="datePickerValue"
|
||||
title="选择日期"
|
||||
<van-calendar
|
||||
class="history-calendar"
|
||||
:poppable="false"
|
||||
:show-confirm="false"
|
||||
:show-title="false"
|
||||
:show-mark="false"
|
||||
:safe-area-inset-bottom="false"
|
||||
switch-mode="month"
|
||||
color="#059669"
|
||||
:row-height="28"
|
||||
:default-date="calendarDate"
|
||||
:min-date="minDate"
|
||||
:max-date="maxDate"
|
||||
@confirm="onDateConfirm"
|
||||
@cancel="showDatePicker = false"
|
||||
@select="onCalendarSelect"
|
||||
/>
|
||||
</van-popup>
|
||||
|
||||
<van-empty v-if="!records.length" description="暂无运输记录" />
|
||||
<div
|
||||
v-for="(row, index) in records"
|
||||
:key="row.planId"
|
||||
class="record-card"
|
||||
role="button"
|
||||
@click="openRecord(row)"
|
||||
>
|
||||
<span class="index-tag">{{ index + 1 }}</span>
|
||||
<div class="record-top">
|
||||
<span class="plan-no">{{ row.planNo }}</span>
|
||||
<span class="tag" :class="tagClass(row)">{{ row.statusLabel || '进行中' }}</span>
|
||||
</div>
|
||||
<div class="meta">
|
||||
取货:{{ formatDay(row.pickupTime) }} · 送货:{{ formatDay(row.deliveryTime) }}
|
||||
</div>
|
||||
<div class="meta">
|
||||
线路:{{ row.pickupAddress || '—' }} → {{ row.destinationAddress || '—' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<van-loading v-if="loading" vertical class="list-loading">加载中...</van-loading>
|
||||
<van-empty v-else-if="!records.length" description="暂无运输记录" />
|
||||
<template v-else>
|
||||
<div
|
||||
v-for="(row, index) in records"
|
||||
:key="row.planId"
|
||||
class="record-card"
|
||||
role="button"
|
||||
@click="openRecord(row)"
|
||||
>
|
||||
<span class="index-tag">{{ index + 1 }}</span>
|
||||
<div class="record-top">
|
||||
<span class="card-title">{{ cardTitle(row) }}</span>
|
||||
<span class="tag" :class="tagClass(row)">{{ row.statusLabel || '进行中' }}</span>
|
||||
</div>
|
||||
<div class="meta">
|
||||
车牌:<span class="plate-hl">{{ row.licensePlate || '—' }}</span>
|
||||
</div>
|
||||
<div class="meta">
|
||||
取货:{{ formatDay(row.pickupTime) }} · 送货:{{ formatDay(row.deliveryTime) }}
|
||||
</div>
|
||||
<div class="meta">
|
||||
路线:{{ row.pickupAddress || '—' }} → {{ row.destinationAddress || '—' }}
|
||||
</div>
|
||||
<template v-if="!(row.products || []).length">
|
||||
<div class="meta">产品:—</div>
|
||||
<div class="meta">规格型号:—</div>
|
||||
<div class="meta">包装规格:—</div>
|
||||
<div class="meta">数量:— · 单位:—</div>
|
||||
</template>
|
||||
<template v-for="(prod, pIndex) in row.products || []" :key="pIndex">
|
||||
<div class="meta">产品:{{ prod.productName || '—' }}</div>
|
||||
<div class="meta">规格型号:{{ prod.model || '—' }}</div>
|
||||
<div class="meta">包装规格:{{ prod.packageSpec || '—' }}</div>
|
||||
<div class="meta">
|
||||
数量:{{ formatQty(prod.quantity) }} · 单位:{{ prod.unit || '—' }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="meta">运输计划号:{{ row.planNo || '—' }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</PublicMobileShell>
|
||||
@@ -83,29 +85,27 @@
|
||||
import PublicMobileShell from '@/layouts/PublicMobileShell.vue'
|
||||
|
||||
import 'vant/es/toast/style'
|
||||
import 'vant/es/field/style'
|
||||
import 'vant/es/popup/style'
|
||||
import 'vant/es/date-picker/style'
|
||||
import 'vant/es/calendar/style'
|
||||
import '@/styles/public-mobile-vant.scss'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const token = computed(() => String(route.params.token || ''))
|
||||
|
||||
const loading = ref(true)
|
||||
const errorMessage = ref('')
|
||||
const bootLoading = ref(true)
|
||||
const loading = ref(false)
|
||||
const fatalError = ref('')
|
||||
const records = ref<PublicTransportHistoryRecord[]>([])
|
||||
const pickDate = ref(addDays(0))
|
||||
const showDatePicker = ref(false)
|
||||
const datePickerValue = ref<string[]>(ymdToParts(pickDate.value))
|
||||
const pickDate = ref(formatYmd(startOfToday()))
|
||||
const calendarDate = ref(startOfToday())
|
||||
const minDate = new Date(new Date().getFullYear() - 2, 0, 1)
|
||||
const maxDate = new Date(new Date().getFullYear() + 2, 11, 31)
|
||||
|
||||
const quickOptions = [
|
||||
{ label: '今日', offset: 0, ymd: addDays(0) },
|
||||
{ label: '明日', offset: 1, ymd: addDays(1) },
|
||||
{ label: '后天', offset: 2, ymd: addDays(2) }
|
||||
]
|
||||
function startOfToday() {
|
||||
const d = new Date()
|
||||
d.setHours(0, 0, 0, 0)
|
||||
return d
|
||||
}
|
||||
|
||||
function formatYmd(d: Date) {
|
||||
const y = d.getFullYear()
|
||||
@@ -114,36 +114,33 @@
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
function addDays(n: number) {
|
||||
const d = new Date()
|
||||
d.setHours(0, 0, 0, 0)
|
||||
d.setDate(d.getDate() + n)
|
||||
return formatYmd(d)
|
||||
}
|
||||
|
||||
function ymdToParts(ymd: string): string[] {
|
||||
const [y, m, d] = String(ymd || '').split('-')
|
||||
if (!y || !m || !d) return ymdToParts(addDays(0))
|
||||
return [y, m, d]
|
||||
}
|
||||
|
||||
function openDatePicker() {
|
||||
datePickerValue.value = ymdToParts(pickDate.value)
|
||||
showDatePicker.value = true
|
||||
}
|
||||
|
||||
function onDateConfirm({ selectedValues }: { selectedValues: string[] }) {
|
||||
pickDate.value = selectedValues.join('-')
|
||||
showDatePicker.value = false
|
||||
load()
|
||||
}
|
||||
|
||||
function formatDay(value?: string) {
|
||||
if (!value) return '—'
|
||||
const normalized = value.replace('T', ' ')
|
||||
return normalized.length >= 10 ? normalized.slice(0, 10) : normalized
|
||||
}
|
||||
|
||||
function formatQty(value?: number | null) {
|
||||
if (value == null) return '—'
|
||||
return String(value)
|
||||
}
|
||||
|
||||
function cardTitleDate(row: PublicTransportHistoryRecord) {
|
||||
const fromPickup = formatDay(row.pickupTime)
|
||||
if (fromPickup !== '—') return fromPickup
|
||||
const fromDelivery = formatDay(row.deliveryTime)
|
||||
if (fromDelivery !== '—') return fromDelivery
|
||||
return pickDate.value
|
||||
}
|
||||
|
||||
function cardTitle(row: PublicTransportHistoryRecord) {
|
||||
const names = (row.products || [])
|
||||
.map((p) => (p.productName || '').trim())
|
||||
.filter(Boolean)
|
||||
const productLabel = names.length ? names.join('、') : '—'
|
||||
return `${cardTitleDate(row)} ${productLabel}`
|
||||
}
|
||||
|
||||
function tagClass(row: PublicTransportHistoryRecord) {
|
||||
if (row.planVoided || row.statusLabel === '已作废') return 'tag--danger'
|
||||
if (row.planArchived || row.statusLabel === '已归档') return 'tag--muted'
|
||||
@@ -154,10 +151,12 @@
|
||||
router.push({ name: 'PublicPlTransportDriver', params: { token: token.value } })
|
||||
}
|
||||
|
||||
function setQuick(offset: number) {
|
||||
pickDate.value = addDays(offset)
|
||||
datePickerValue.value = ymdToParts(pickDate.value)
|
||||
load()
|
||||
function onCalendarSelect(date: Date) {
|
||||
const next = formatYmd(date)
|
||||
if (next === pickDate.value) return
|
||||
pickDate.value = next
|
||||
calendarDate.value = date
|
||||
load({ silentBoot: true })
|
||||
}
|
||||
|
||||
function openRecord(row: PublicTransportHistoryRecord) {
|
||||
@@ -169,30 +168,44 @@
|
||||
router.push({ name: 'PublicPlTransportDriver', params: { token: accessToken } })
|
||||
}
|
||||
|
||||
async function load() {
|
||||
async function load(options?: { silentBoot?: boolean }) {
|
||||
loading.value = true
|
||||
errorMessage.value = ''
|
||||
if (!options?.silentBoot) {
|
||||
bootLoading.value = true
|
||||
fatalError.value = ''
|
||||
}
|
||||
try {
|
||||
const data = await publicTransportApi.getHistory(token.value, pickDate.value)
|
||||
records.value = data?.records || []
|
||||
fatalError.value = ''
|
||||
} catch (e: any) {
|
||||
errorMessage.value = e?.message || '链接无效或已失效'
|
||||
records.value = []
|
||||
if (!options?.silentBoot) {
|
||||
fatalError.value = e?.message || '链接无效或已失效'
|
||||
} else {
|
||||
showFailToast(e?.message || '加载失败')
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
bootLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
onMounted(() => load())
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-loading {
|
||||
.page-loading,
|
||||
.list-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 48px 0;
|
||||
}
|
||||
|
||||
.list-loading {
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
.transport-nav-bar {
|
||||
margin: -12px -16px 12px;
|
||||
border-radius: 0 0 12px 12px;
|
||||
@@ -214,7 +227,7 @@
|
||||
|
||||
.filters {
|
||||
margin-bottom: 12px;
|
||||
padding: 12px 14px;
|
||||
padding: 4px 4px 2px;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
border: 1px solid #e2e8f0;
|
||||
@@ -223,69 +236,29 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
.history-calendar {
|
||||
height: auto;
|
||||
--van-calendar-background: #fff;
|
||||
--van-calendar-header-shadow: none;
|
||||
--van-calendar-header-title-height: 32px;
|
||||
--van-calendar-header-subtitle-font-size: 13px;
|
||||
--van-calendar-weekdays-height: 24px;
|
||||
--van-calendar-weekdays-font-size: 11px;
|
||||
--van-calendar-day-height: 28px;
|
||||
--van-calendar-day-font-size: 12px;
|
||||
--van-calendar-day-margin-bottom: 0;
|
||||
--van-calendar-selected-day-size: 26px;
|
||||
--van-primary-color: #059669;
|
||||
|
||||
.date-field {
|
||||
flex: 0 1 11.5em;
|
||||
min-width: 0;
|
||||
padding: 0 10px;
|
||||
min-height: 40px;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 8px;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
|
||||
:deep(.van-field__control) {
|
||||
font-size: 14px;
|
||||
color: #1e293b;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
:deep(.van-calendar__footer) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:deep(.van-field__right-icon) {
|
||||
margin-right: 0;
|
||||
color: #64748b;
|
||||
:deep(.van-calendar__body) {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.chips {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: 0;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.chip {
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid #d1fae5;
|
||||
background: #ecfdf5;
|
||||
color: #047857;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.chip.on {
|
||||
background: #059669;
|
||||
border-color: #059669;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.record-card {
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
@@ -324,7 +297,7 @@
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.plan-no {
|
||||
.card-title {
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
@@ -357,7 +330,7 @@
|
||||
|
||||
.meta {
|
||||
font-size: 13px;
|
||||
color: #64748b;
|
||||
color: #0f172a;
|
||||
line-height: 1.45;
|
||||
word-break: break-all;
|
||||
|
||||
@@ -365,4 +338,10 @@
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.plate-hl {
|
||||
color: #059669;
|
||||
font-weight: 700;
|
||||
font-size: 15px;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user