소스 검색

Merge branch 'develop_yh58' of jianguan-web/jg-ocs-html into pre-release

李磊 1 개월 전
부모
커밋
d8d0e42925

+ 152 - 542
package-lock.json

@@ -2355,6 +2355,11 @@
       "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==",
       "dev": true
     },
+    "adler-32": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz",
+      "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A=="
+    },
     "ajv": {
       "version": "6.10.2",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
@@ -3303,6 +3308,16 @@
       "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
       "dev": true
     },
+    "bindings": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/bindings/-/bindings-1.5.0.tgz",
+      "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "file-uri-to-path": "1.0.0"
+      }
+    },
     "block-stream": {
       "version": "0.0.9",
       "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -3764,6 +3779,15 @@
         "lazy-cache": "^1.0.3"
       }
     },
+    "cfb": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz",
+      "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
+      "requires": {
+        "adler-32": "~1.3.0",
+        "crc-32": "~1.2.0"
+      }
+    },
     "chalk": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@@ -4212,6 +4236,11 @@
       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
       "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
     },
+    "codepage": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz",
+      "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
+    },
     "collection-visit": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
@@ -4676,6 +4705,11 @@
         }
       }
     },
+    "crc-32": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz",
+      "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="
+    },
     "create-ecdh": {
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
@@ -6845,6 +6879,11 @@
       "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
       "dev": true
     },
+    "exit-on-epipe": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
+      "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
+    },
     "expand-brackets": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
@@ -7203,6 +7242,11 @@
       "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
       "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
     },
+    "fflate": {
+      "version": "0.3.11",
+      "resolved": "https://registry.npmmirror.com/fflate/-/fflate-0.3.11.tgz",
+      "integrity": "sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A=="
+    },
     "figgy-pudding": {
       "version": "3.5.1",
       "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
@@ -7239,6 +7283,18 @@
         "schema-utils": "^1.0.0"
       }
     },
+    "file-saver": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz",
+      "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
+    },
+    "file-uri-to-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+      "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+      "dev": true,
+      "optional": true
+    },
     "filename-regex": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
@@ -7457,6 +7513,11 @@
       "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
       "dev": true
     },
+    "frac": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz",
+      "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
+    },
     "fragment-cache": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -7511,551 +7572,14 @@
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
     },
     "fsevents": {
-      "version": "1.2.9",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
-      "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+      "version": "1.2.13",
+      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-1.2.13.tgz",
+      "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
       "dev": true,
       "optional": true,
       "requires": {
-        "nan": "^2.12.1",
-        "node-pre-gyp": "^0.12.0"
-      },
-      "dependencies": {
-        "abbrev": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "ansi-regex": {
-          "version": "2.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "aproba": {
-          "version": "1.2.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "are-we-there-yet": {
-          "version": "1.1.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "delegates": "^1.0.0",
-            "readable-stream": "^2.0.6"
-          }
-        },
-        "balanced-match": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "brace-expansion": {
-          "version": "1.1.11",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "balanced-match": "^1.0.0",
-            "concat-map": "0.0.1"
-          }
-        },
-        "chownr": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "code-point-at": {
-          "version": "1.1.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "concat-map": {
-          "version": "0.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "console-control-strings": {
-          "version": "1.1.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "core-util-is": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "debug": {
-          "version": "4.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "deep-extend": {
-          "version": "0.6.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "delegates": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "detect-libc": {
-          "version": "1.0.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "fs-minipass": {
-          "version": "1.2.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minipass": "^2.2.1"
-          }
-        },
-        "fs.realpath": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "gauge": {
-          "version": "2.7.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "aproba": "^1.0.3",
-            "console-control-strings": "^1.0.0",
-            "has-unicode": "^2.0.0",
-            "object-assign": "^4.1.0",
-            "signal-exit": "^3.0.0",
-            "string-width": "^1.0.1",
-            "strip-ansi": "^3.0.1",
-            "wide-align": "^1.1.0"
-          }
-        },
-        "glob": {
-          "version": "7.1.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.0.4",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
-        "has-unicode": {
-          "version": "2.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "iconv-lite": {
-          "version": "0.4.24",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "safer-buffer": ">= 2.1.2 < 3"
-          }
-        },
-        "ignore-walk": {
-          "version": "3.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minimatch": "^3.0.4"
-          }
-        },
-        "inflight": {
-          "version": "1.0.6",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "once": "^1.3.0",
-            "wrappy": "1"
-          }
-        },
-        "inherits": {
-          "version": "2.0.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "ini": {
-          "version": "1.3.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "is-fullwidth-code-point": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "number-is-nan": "^1.0.0"
-          }
-        },
-        "isarray": {
-          "version": "1.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "minimatch": {
-          "version": "3.0.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "brace-expansion": "^1.1.7"
-          }
-        },
-        "minimist": {
-          "version": "0.0.8",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "minipass": {
-          "version": "2.3.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "safe-buffer": "^5.1.2",
-            "yallist": "^3.0.0"
-          }
-        },
-        "minizlib": {
-          "version": "1.2.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minipass": "^2.2.1"
-          }
-        },
-        "mkdirp": {
-          "version": "0.5.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "minimist": "0.0.8"
-          }
-        },
-        "ms": {
-          "version": "2.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "needle": {
-          "version": "2.3.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "debug": "^4.1.0",
-            "iconv-lite": "^0.4.4",
-            "sax": "^1.2.4"
-          }
-        },
-        "node-pre-gyp": {
-          "version": "0.12.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "detect-libc": "^1.0.2",
-            "mkdirp": "^0.5.1",
-            "needle": "^2.2.1",
-            "nopt": "^4.0.1",
-            "npm-packlist": "^1.1.6",
-            "npmlog": "^4.0.2",
-            "rc": "^1.2.7",
-            "rimraf": "^2.6.1",
-            "semver": "^5.3.0",
-            "tar": "^4"
-          }
-        },
-        "nopt": {
-          "version": "4.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "abbrev": "1",
-            "osenv": "^0.1.4"
-          }
-        },
-        "npm-bundled": {
-          "version": "1.0.6",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "npm-packlist": {
-          "version": "1.4.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ignore-walk": "^3.0.1",
-            "npm-bundled": "^1.0.1"
-          }
-        },
-        "npmlog": {
-          "version": "4.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "are-we-there-yet": "~1.1.2",
-            "console-control-strings": "~1.1.0",
-            "gauge": "~2.7.3",
-            "set-blocking": "~2.0.0"
-          }
-        },
-        "number-is-nan": {
-          "version": "1.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "object-assign": {
-          "version": "4.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "once": {
-          "version": "1.4.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "wrappy": "1"
-          }
-        },
-        "os-homedir": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "os-tmpdir": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "osenv": {
-          "version": "0.1.5",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "os-homedir": "^1.0.0",
-            "os-tmpdir": "^1.0.0"
-          }
-        },
-        "path-is-absolute": {
-          "version": "1.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "process-nextick-args": {
-          "version": "2.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "rc": {
-          "version": "1.2.8",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "deep-extend": "^0.6.0",
-            "ini": "~1.3.0",
-            "minimist": "^1.2.0",
-            "strip-json-comments": "~2.0.1"
-          },
-          "dependencies": {
-            "minimist": {
-              "version": "1.2.0",
-              "bundled": true,
-              "dev": true,
-              "optional": true
-            }
-          }
-        },
-        "readable-stream": {
-          "version": "2.3.6",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.3",
-            "isarray": "~1.0.0",
-            "process-nextick-args": "~2.0.0",
-            "safe-buffer": "~5.1.1",
-            "string_decoder": "~1.1.1",
-            "util-deprecate": "~1.0.1"
-          }
-        },
-        "rimraf": {
-          "version": "2.6.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "glob": "^7.1.3"
-          }
-        },
-        "safe-buffer": {
-          "version": "5.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "safer-buffer": {
-          "version": "2.1.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "sax": {
-          "version": "1.2.4",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "semver": {
-          "version": "5.7.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "set-blocking": {
-          "version": "2.0.0",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "signal-exit": {
-          "version": "3.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "string-width": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "code-point-at": "^1.0.0",
-            "is-fullwidth-code-point": "^1.0.0",
-            "strip-ansi": "^3.0.0"
-          }
-        },
-        "string_decoder": {
-          "version": "1.1.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "safe-buffer": "~5.1.0"
-          }
-        },
-        "strip-ansi": {
-          "version": "3.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-regex": "^2.0.0"
-          }
-        },
-        "strip-json-comments": {
-          "version": "2.0.1",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "tar": {
-          "version": "4.4.8",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "chownr": "^1.1.1",
-            "fs-minipass": "^1.2.5",
-            "minipass": "^2.3.4",
-            "minizlib": "^1.1.1",
-            "mkdirp": "^0.5.0",
-            "safe-buffer": "^5.1.2",
-            "yallist": "^3.0.2"
-          }
-        },
-        "util-deprecate": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "wide-align": {
-          "version": "1.1.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "string-width": "^1.0.2 || 2"
-          }
-        },
-        "wrappy": {
-          "version": "1.0.2",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        },
-        "yallist": {
-          "version": "3.0.3",
-          "bundled": true,
-          "dev": true,
-          "optional": true
-        }
+        "bindings": "^1.5.0",
+        "nan": "^2.12.1"
       }
     },
     "fstream": {
@@ -14121,6 +13645,11 @@
         }
       }
     },
+    "printj": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/printj/-/printj-1.1.2.tgz",
+      "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
+    },
     "private": {
       "version": "0.1.8",
       "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@@ -15876,6 +15405,14 @@
       "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
       "dev": true
     },
+    "ssf": {
+      "version": "0.11.2",
+      "resolved": "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz",
+      "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
+      "requires": {
+        "frac": "~1.1.2"
+      }
+    },
     "sshpk": {
       "version": "1.16.1",
       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
@@ -18085,11 +17622,21 @@
       "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
       "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
     },
+    "wmf": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz",
+      "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
+    },
     "wolfy87-eventemitter": {
       "version": "5.1.0",
       "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.1.0.tgz",
       "integrity": "sha1-NcGsDdGsDBXjXZgVCPwiCEoToBE="
     },
+    "word": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/word/-/word-0.3.0.tgz",
+      "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
+    },
     "wordwrap": {
       "version": "0.0.2",
       "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
@@ -18191,6 +17738,69 @@
         "async-limiter": "~1.0.0"
       }
     },
+    "xlsx": {
+      "version": "0.18.5",
+      "resolved": "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz",
+      "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
+      "requires": {
+        "adler-32": "~1.3.0",
+        "cfb": "~1.2.1",
+        "codepage": "~1.15.0",
+        "crc-32": "~1.2.1",
+        "ssf": "~0.11.2",
+        "wmf": "~1.0.1",
+        "word": "~0.3.0"
+      }
+    },
+    "xlsx-js-style": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/xlsx-js-style/-/xlsx-js-style-1.2.0.tgz",
+      "integrity": "sha512-DDT4FXFSWfT4DXMSok/m3TvmP1gvO3dn0Eu/c+eXHW5Kzmp7IczNkxg/iEPnImbG9X0Vb8QhROda5eatSR/97Q==",
+      "requires": {
+        "adler-32": "~1.2.0",
+        "cfb": "^1.1.4",
+        "codepage": "~1.14.0",
+        "commander": "~2.17.1",
+        "crc-32": "~1.2.0",
+        "exit-on-epipe": "~1.0.1",
+        "fflate": "^0.3.8",
+        "ssf": "~0.11.2",
+        "wmf": "~1.0.1",
+        "word": "~0.3.0"
+      },
+      "dependencies": {
+        "adler-32": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.2.0.tgz",
+          "integrity": "sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==",
+          "requires": {
+            "exit-on-epipe": "~1.0.1",
+            "printj": "~1.1.0"
+          }
+        },
+        "codepage": {
+          "version": "1.14.0",
+          "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.14.0.tgz",
+          "integrity": "sha512-iz3zJLhlrg37/gYRWgEPkaFTtzmnEv1h+r7NgZum2lFElYQPi0/5bnmuDfODHxfp0INEfnRqyfyeIJDbb7ahRw==",
+          "requires": {
+            "commander": "~2.14.1",
+            "exit-on-epipe": "~1.0.1"
+          },
+          "dependencies": {
+            "commander": {
+              "version": "2.14.1",
+              "resolved": "https://registry.npmmirror.com/commander/-/commander-2.14.1.tgz",
+              "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw=="
+            }
+          }
+        },
+        "commander": {
+          "version": "2.17.1",
+          "resolved": "https://registry.npmmirror.com/commander/-/commander-2.17.1.tgz",
+          "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
+        }
+      }
+    },
     "xml-name-validator": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",

+ 4 - 1
package.json

@@ -21,6 +21,7 @@
     "core-js": "2.6.9",
     "echarts": "^5.4.0",
     "enquire.js": "^2.1.6",
+    "file-saver": "^2.0.5",
     "lodash": "^4.17.20",
     "lodash.get": "^4.4.2",
     "lodash.pick": "^4.4.0",
@@ -50,7 +51,9 @@
     "vue2.0-zoom": "^2.1.1",
     "vuescroll": "^4.17.3",
     "vuex": "^3.1.1",
-    "wangeditor": "^4.7.15"
+    "wangeditor": "^4.7.15",
+    "xlsx": "^0.18.5",
+    "xlsx-js-style": "^1.2.0"
   },
   "devDependencies": {
     "@ant-design/colors": "^3.2.1",

+ 1 - 1
public/version.json

@@ -1,4 +1,4 @@
 {
-    "version": "2.2.553",
+    "version": "2.2.58",
     "message": "发现有新版本发布,确定更新系统?"
 }

+ 23 - 0
src/api/reportDailyConf.js

@@ -0,0 +1,23 @@
+import { axios } from '@/utils/request'
+
+//  每日报表配置  无分页
+export const reportDailyConfList = (params) => {
+  return axios({
+    url: '/dailyReportConf/queryList',
+    data: params,
+    method: 'post',
+    headers: {
+      'module': encodeURIComponent('列表查询')
+    }
+  })
+}
+
+// 每日报表配置  保存
+export const dailyReportConfSave = (params) => {
+  const url = '/dailyReportConf/save'
+  return axios({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}

+ 13 - 0
src/api/reportData.js

@@ -1,4 +1,17 @@
 import { axios } from '@/utils/request'
+
+// 每日报表
+export const salesReportDailyList = (params) => {
+  const url = `/report/reportData/query`
+  return axios({
+    url: url,
+    data: params,
+    method: 'post',
+    headers: {
+      'module': encodeURIComponent('每日报表查询')
+    }
+  })
+}
 // 获取开单退货单表头
 export const salesReportReturnTitle = (params) => {
   return axios({

+ 1 - 1
src/config/dealerManagement.js

@@ -308,7 +308,7 @@ export default {
             title: '管辖品类权限设置',
             icon: 'user',
             hidden: true,
-            replaceTab: true,
+            replaceTab: false,
             permission: 'M_settingsIndex'
           }
         }

+ 27 - 2
src/config/report/salesReport.js

@@ -74,7 +74,7 @@ export default {
       meta: {
         title: '各品类经营分析表',
         icon: 'profile',
-        permission: 'M_regionTypeSalesReportList'
+        permission: 'M_regionTypeBusinessReportList'
       },
       hideChildrenInMenu: true,
       children: [
@@ -86,7 +86,32 @@ export default {
             title: '各品类经营分析表',
             icon: 'profile',
             hidden: true,
-            permission: 'M_regionTypeSalesReportList'
+            permission: 'M_regionTypeBusinessReportList'
+          }
+        }
+      ]
+    },
+    {
+      path: '/reportData/dailyReport',
+      redirect: '/reportData/dailyReport/list',
+      name: 'dailyReport',
+      component: BlankLayout,
+      meta: {
+        title: '每日报表',
+        icon: 'profile',
+        permission: 'M_dailyReport'
+      },
+      hideChildrenInMenu: true,
+      children: [
+        {
+          path: 'list',
+          name: 'dailyReportList',
+          component: () => import(/* webpackChunkName: "reportData" */ '@/views/reportData/dailyReport/index.vue'),
+          meta: {
+            title: '每日报表',
+            icon: 'profile',
+            hidden: true,
+            permission: 'M_dailyReport'
           }
         }
       ]

+ 25 - 0
src/config/sysSetting.js

@@ -299,6 +299,31 @@ export default {
         }
       ]
     },
+    {
+      path: '/setting/dailyReportSettings',
+      redirect: '/setting/dailyReportSettings/index',
+      name: 'dailyReportSettings',
+      component: BlankLayout,
+      meta: {
+        title: '每日报表配置',
+        icon: 'sketch',
+        permission: 'M_dailyReportSettings'
+      },
+      hideChildrenInMenu: true,
+      children: [
+        {
+          path: 'index',
+          name: 'dailyReportSettingsIndex',
+          component: () => import(/* webpackChunkName: "setting" */ '@/views/setting/dailyReportSettings/index.vue'),
+          meta: {
+            title: '每日报表配置',
+            icon: 'sketch',
+            hidden: true,
+            permission: 'M_dailyReportSettings'
+          }
+        }
+      ]
+    },
     {
       path: '/setting/tireSubsidySetting',
       redirect: '/setting/tireSubsidySetting/index',

+ 3 - 17
src/views/dealerManagement/businessOwnerSettings/categorySet.vue

@@ -25,7 +25,6 @@
                 <a-col :span="20">
                   <a-tag
                     :id="'categorySet-chooseType'+record.bizUserScopeSn"
-                    style="margin-bottom:10px;"
                     closable
                     @close.prevent="delLabel(record.bizUserScopeSn,con,'typeList')"
                     v-for="(con,i) in record.productTypeList"
@@ -54,7 +53,6 @@
               <a-row v-if="record.productBrandList && record.productBrandList.length>0">
                 <a-col :span="20">
                   <a-tag
-                    style="margin-bottom:10px;"
                     :id="'categorySet-chooseBrand'+record.bizUserScopeSn"
                     closable
                     @close.prevent="delLabel(record.bizUserScopeSn,item,'brandList')"
@@ -103,8 +101,8 @@
 import { commonMixin } from '@/utils/mixin'
 // 组件
 import { STable } from '@/components'
-import ChooseBrandModal from '@/views/common/chooseBrandModal.vue'
-import ChooseTypeModal from '@/views/common/chooseTypeModal.vue'
+import ChooseBrandModal from './chooseBrandModal.vue'
+import ChooseTypeModal from './chooseTypeModal.vue'
 // 接口
 import { getNewScopeSn, queryProductScopePage, saveProductBrandList, saveProductTypeList, bizuserScopeDelete, deleteProductBrand, deleteProductType } from '@/api/bizuser'
 export default {
@@ -234,13 +232,7 @@ export default {
     },
     // 添加品牌标签
     addBrandTag (pos, row) {
-      const newData = []
-      row.productBrandList.forEach(item => {
-        const obj = {}
-        obj.goodsSn = item.dataSn
-        newData.push(obj)
-      })
-      this.chooseBrand = newData
+      this.chooseBrand = row.productBrandList
       this.chooseObj = row
       this.openBrandModal = true
     },
@@ -336,9 +328,3 @@ export default {
   }
 }
 </script>
-
-<style lang="less">
-  .categorySet-wrap{
-
-  }
-</style>

+ 127 - 0
src/views/dealerManagement/businessOwnerSettings/chooseBrandModal.vue

@@ -0,0 +1,127 @@
+<template>
+  <a-modal
+    centered
+    class="chooseBrand-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="选择产品品牌"
+    v-model="isShow"
+    @cancel="isShow=false"
+    :width="800">
+    <div class="chooseBrand-con">
+      <a-row style="height: 400px;overflow-y: scroll;">
+        <a-col :span="6" v-for="(item,index) in brandList" :key="item.brandSn">
+          <a-checkbox :checked="item.checked" :disabled="item.isDisabled" @change="e=>onChange(e,index)">
+            {{ item.brandName }}
+          </a-checkbox>
+        </a-col>
+      </a-row>
+      <!-- 按钮 -->
+      <div class="btn-con">
+        <a-button
+          id="chooseBrand-cancel"
+          class="button-cancel"
+          @click="isShow=false"
+          style="padding: 0 30px;">取消</a-button>
+        <a-button
+          type="primary"
+          id="chooseBrand-submit"
+          @click="handleSave"
+          style="padding: 0 30px;margin-left: 15px;">保存</a-button>
+      </div>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { productBrandQuery } from '@/api/productBrand'
+export default {
+  name: 'ChooseBrandModal',
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    chooseData: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      brandList: [] //  品牌数据
+    }
+  },
+  methods: {
+    // 保存
+    handleSave () {
+      const _this = this
+      const checkedRowList = _this.brandList.filter(item => item.checked)
+      if (checkedRowList.length < 1) {
+        _this.$message.warning('请在列表勾选后再进行操作!')
+        return
+      }
+      _this.$emit('ok', checkedRowList)
+      _this.isShow = false
+    },
+    // change
+    onChange (e, pos) {
+      this.brandList.map(item => {
+        item.checked = false
+        return item
+      })
+      this.brandList[pos].checked = e.target.checked
+      this.$forceUpdate()
+    },
+    // 获取品牌数据
+    getBrandList () {
+      const _this = this
+      productBrandQuery({}).then(res => {
+        if (res.status == 200) {
+          if (_this.chooseData && _this.chooseData.length > 0) {
+            const checkedList = _this.chooseData.map(item => item.dataSn)
+            res.data.map(item => {
+              item.checked = checkedList.includes(item.brandSn)
+            })
+          }
+          _this.brandList = res.data
+        } else {
+          _this.brandList = []
+        }
+      })
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      } else {
+        const _this = this
+        _this.getBrandList()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .chooseBrand-modal{
+    .chooseBrand-con{
+      .btn-con{
+        text-align: center;
+        margin: 30px 0 20px;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 165 - 0
src/views/dealerManagement/businessOwnerSettings/chooseTypeModal.vue

@@ -0,0 +1,165 @@
+<template>
+  <a-modal
+    centered
+    class="chooseType-modal"
+    :footer="null"
+    :maskClosable="false"
+    title="选择产品分类"
+    v-model="isShow"
+    @cancel="isShow=false"
+    width="50%">
+    <div class="chooseType-con">
+      <a-tree
+        style="height: 400px;overflow-y: scroll;"
+        checkable
+        @check="onCheck"
+        :checkStrictly="linkageStatus"
+        :checkedKeys="selectedKey"
+        :treeData="productTypeList"
+        :replaceFields="replaceFields"
+        :expandedKeys.sync="expandedKeys"
+      />
+      <!-- 按钮 -->
+      <div class="btn-con">
+        <a-button
+          id="chooseType-cancel"
+          class="button-cancel"
+          @click="isShow=false"
+          style="padding: 0 30px;">取消</a-button>
+        <a-button
+          type="primary"
+          id="chooseType-submit"
+          @click="handleSave"
+          style="padding: 0 30px;margin-left: 15px;">保存</a-button>
+      </div>
+    </div>
+  </a-modal>
+</template>
+
+<script>
+import { productTypeQuery } from '@/api/productType'
+export default {
+  name: 'ChooseTypeModal',
+  props: {
+    openModal: { //  弹框显示状态
+      type: Boolean,
+      default: false
+    },
+    chooseData: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    linkageStatus: { // 父子是否联动
+      type: Boolean,
+      default: true
+    }
+  },
+  data () {
+    return {
+      isShow: this.openModal, //  是否打开弹框
+      selectedKey: [], //  选中项
+      checkedRows: [], //  选中项  整条数据
+      replaceFields: {// tree 渲染配置
+        children: 'children',
+        title: 'productTypeName',
+        key: 'productTypeSn'
+      },
+      productTypeList: [], // tree列表数据
+      expandedKeys: []// 第一级  展开sn
+    }
+  },
+  methods: {
+    //  产品分类  列表
+    getProductType () {
+      productTypeQuery({}).then(res => {
+        if (res.status == 200) {
+          this.recursionFun(res.data)
+          this.productTypeList = res.data
+          this.expandedKeys = this.getLevel1Keys(res.data) // 仅展开二级
+        } else {
+          this.productTypeList = []
+        }
+      })
+    },
+    // 遍历树数据,提取所有一级节点的 Key
+    getLevel1Keys (treeData) {
+      const keys = []
+      treeData.forEach(level1Node => {
+        keys.push(level1Node.productTypeSn)
+      })
+      return keys
+    },
+    // 保存
+    handleSave () {
+      if (this.selectedKey.checked && this.selectedKey.checked.length < 1) {
+        this.$message.warning('请在列表勾选后再进行操作!')
+        return
+      }
+      this.$emit('ok', this.checkedRows)
+      this.isShow = false
+    },
+    //  递归函数
+    recursionFun (data) {
+      if (data) {
+        data.map((item, index) => {
+          item.disabled = (item.productTypeLevel == 1 || item.productTypeLevel == 3)
+          if (item.children && item.children.length > 0) {
+            this.recursionFun(item.children)
+          }
+        })
+      }
+    },
+    onCheck (checkedKeys, { checkedNodes, node }) {
+      this.checkedRows = []
+      // 强制单选:仅保留最后一次选中的节点
+      this.selectedKey = [node.eventKey]
+      if (checkedNodes && checkedNodes.length == 1) {
+        this.checkedRows.push(checkedNodes[0].data.props)
+      } else {
+        this.checkedRows.push(checkedNodes[1].data.props)
+      }
+    }
+  },
+  watch: {
+    //  父页面传过来的弹框状态
+    openModal (newValue, oldValue) {
+      this.isShow = newValue
+    },
+    //  重定义的弹框状态
+    isShow (newValue, oldValue) {
+      if (!newValue) {
+        this.$emit('close')
+      } else {
+        this.getProductType()
+        // 清空已选项
+        this.selectedKey = []
+        // 回显已选数据
+        const _this = this
+        this.$nextTick(() => {
+          _this.checkedRows = _this.chooseData
+          _this.chooseData.forEach(item => {
+            _this.selectedKey.push(item.goodsSn)
+          })
+        })
+      }
+    }
+
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .chooseType-modal{
+    .chooseType-con{
+      .btn-con{
+        text-align: center;
+        margin: 30px 0 20px;
+        .button-cancel{
+          font-size: 12px;
+        }
+      }
+    }
+  }
+</style>

+ 74 - 0
src/views/reportData/dailyReport/index.vue

@@ -0,0 +1,74 @@
+<template>
+  <div class="dayReport-box">
+    <!-- 选项卡切换 -->
+    <a-tabs v-model="activeKey" @change="callback" :tabBarStyle="{'background':'#fff',height:'41px',overflow:'hidden',marginBottom:'5px'}">
+      <a-tab-pane :key="item.id" :tab="item.name" v-for="item in tabsList" forceRender>
+        <dTable :ref="'table'+item.id"></dTable>
+      </a-tab-pane>
+    </a-tabs>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import dTable from './table.vue'
+export default {
+  name: 'RegionTypeSalesReportList',
+  mixins: [commonMixin],
+  components: { dTable },
+  data () {
+    return {
+      spinning: false,
+      activeKey: 0, // 切换显示页面值 0 各分区品类实售明细 1各区域品类实售明细
+      tabsList: [] // tab切换data
+    }
+  },
+  methods: {
+    // tabs切换  change时间
+    callback (key) {
+      this.activeKey = key
+      this.$refs['table' + this.activeKey][0].pageInit(this.activeKey)
+    },
+    // 初始化
+    pageInit () {
+      this.tabsList = []
+      if (this.$hasPermissions('M_National_Sales_Daily_Report')) {
+        this.tabsList.push({ id: 0, name: '全国销售日报' })
+      }
+      if (this.$hasPermissions('M_Project_Sales_Daily_Report')) {
+        this.tabsList.push({ id: 1, name: '项目销售日报1' })
+      }
+      if (this.$hasPermissions('M_Project_Sales_Daily_Report_2')) {
+        this.tabsList.push({ id: 2, name: '项目销售日报2' })
+      }
+      if (this.$hasPermissions('M_Regional_Sales_Daily_Report')) {
+        this.tabsList.push({ id: 3, name: '分区销售日报' })
+      }
+      this.activeKey = this.tabsList[0].id
+      this.$nextTick(() => {
+        this.$refs['table' + this.activeKey][0].pageInit(this.activeKey)
+      })
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  },
+  activated () {
+    // 如果是新页签打开,则重置当前页面
+    if (this.$store.state.app.isNewTab) {
+      this.pageInit()
+    }
+  },
+  beforeRouteEnter (to, from, next) {
+    next(vm => {})
+  }
+}
+</script>
+<style lang="less" scoped>
+.dayReport-box{
+  min-height: calc(100vh - 90px);
+  background: #fff;
+}
+</style>

+ 320 - 0
src/views/reportData/dailyReport/table.vue

@@ -0,0 +1,320 @@
+<template>
+  <div>
+    <a-spin :spinning="spinning" tip="Loading...">
+      <a-card size="small" class="card-table">
+        <!-- 搜索条件 -->
+        <div class="table-page-search-wrapper newTableSearchName" ref="tableSearch">
+          <a-form-model
+            id="dayReportList-form"
+            ref="ruleForm"
+            class="form-model-con"
+            layout="inline"
+            :rules="rules"
+            :model="queryParam"
+            @keyup.enter.native="handleSearch">
+            <a-row :gutter="15">
+              <a-col :md="6" :sm="24">
+                <a-form-model-item label="月份" prop="month">
+                  <a-month-picker
+                    placeholder="请选择月份"
+                    locale="zh-cn"
+                    id="dayReportList-month"
+                    v-model="queryParam.month"
+                    :allowClear="false"
+                    @change="onChange"
+                    :disabled-date="disabledDate"
+                    style="width: 100%;"/>
+                </a-form-model-item>
+              </a-col>
+              <a-col :md="6" :sm="24" style="margin-bottom: 10px;">
+                <a-button type="primary" @click="handleSearch" :disabled="disabled" id="dayReportList-refresh">查询</a-button>
+                <a-button style="margin-left: 5px" @click="resetSearchForm" :disabled="disabled" id="dayReportList-reset">重置</a-button>
+                <a-button
+                  style="margin-left: 5px"
+                  type="primary"
+                  class="button-warning"
+                  @click="handleExport"
+                  :disabled="tableData.length==0"
+                  v-if="$hasPermissions('B_National_Sales_Daily_Export')&&activeKey==0
+                    ||$hasPermissions('B_Project_Sales_Daily_Export')&&activeKey==1
+                    ||$hasPermissions('B_Project_Sales_Daily_Export_2')&&activeKey==2
+                    ||$hasPermissions('M_Regional_Sales_Daily_Export')&&activeKey==3"
+                  :loading="exportLoading"
+                  id="dayReportList-export">导出</a-button>
+              </a-col>
+            </a-row>
+          </a-form-model>
+        </div>
+        <!-- 列表 -->
+        <table0
+          v-if="activeKey == 0"
+          ref="table0"
+          :month="queryParam.month"
+          :columns="columns"
+          :tableData="tableData"
+          :nowDate="nowDate"
+        ></table0>
+        <table1
+          v-if="activeKey == 1"
+          ref="table1"
+          :month="queryParam.month"
+          :columns="columns"
+          :tableData="tableData"
+          :nowDate="nowDate"
+        ></table1>
+        <table2
+          v-if="activeKey == 2"
+          ref="table2"
+          :month="queryParam.month"
+          :columns="columns"
+          :tableData="tableData"
+          :nowDate="nowDate"
+        ></table2>
+        <table3
+          v-if="activeKey == 3"
+          ref="table3"
+          :month="queryParam.month"
+          :columns="columns"
+          :tableData="tableData"
+          :nowDate="nowDate"
+        ></table3>
+      </a-card>
+    </a-spin>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+import XLSX from 'xlsx-js-style'
+// 组件
+import moment from 'moment'
+import table0 from './table0'
+import table1 from './table1'
+import table2 from './table2'
+import table3 from './table3'
+// 接口
+import { salesReportDailyList } from '@/api/reportData.js'
+export default {
+  name: 'RegionTypeSalesReportList',
+  mixins: [commonMixin],
+  components: { table0, table1, table2, table3 },
+  data () {
+    return {
+      spinning: false,
+      activeKey: 0, // 切换显示页面值 0 各分区品类实售明细 1各区域品类实售明细
+      advanced: true, // 高级搜索 展开/关闭
+      disabled: false, //  查询、重置按钮是否可操作
+      exportLoading: false, // 导出按钮加载状态
+      tableHeight: 0, // 表格高度
+      tabsList: [{ id: 0, name: '全国销售日报' }, { id: 1, name: '项目销售日报1' }, { id: 2, name: '项目销售日报2' }, { id: 3, name: '分区销售日报' }], // tab切换data
+      columns: [], // 表头数据
+      tableData: [], // 表格数据
+      totalNums: 0, // 总条数
+      // 查询参数
+      queryParam: {
+        month: moment().format('YYYY-MM') // 月份默认值
+      },
+      rules: {
+        'month': [{ required: true, message: '请选择月份', trigger: 'change' }]
+      },
+      nowDate: ''
+    }
+  },
+  methods: {
+    // 月份 change
+    onChange (date, dateString) {
+      this.queryParam.month = dateString
+    },
+    // 月份选择范围
+    disabledDate (current) {
+      return current && current > moment().endOf('day')
+    },
+    // tabs切换  change时间
+    callback (key) {
+      this.activeKey = key
+      const _this = this
+      _this.$nextTick(() => {
+        this.resetSearchForm()
+      })
+    },
+    // 查询
+    handleSearch () {
+      const _this = this
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          _this.getTableData()
+        } else {
+          _this.$message.error('请选择月份')
+          return false
+        }
+      })
+    },
+    //  重置
+    resetSearchForm () {
+      this.$refs.ruleForm.resetFields()
+      this.tableData = []
+      this.totalNums = 0
+      this.totalNums = []
+    },
+    exportTable (dom, title) {
+      const zim = 'A、B、C、D、E、F、G、H、I、J、K、L、M、N、O、P、Q、R、S、T、U、V、W、X、Y、Z‌'.split('、')
+      var ws = XLSX.utils.table_to_sheet(dom)
+      // console.log(ws)
+      // 设置样式
+      Object.keys(ws).forEach(cell => {
+        if (cell[0] !== '!') {
+          // 设置表头样式
+          if (cell === 'A1') {
+            ws[cell].s = {
+              font: { bold: true, color: { rgb: 'FFFFFF' } },
+              fill: { fgColor: { rgb: '4472C4' } },
+              alignment: { horizontal: 'center' }
+            }
+          } else {
+            ws[cell].s = {
+              alignment: {
+                horizontal: 'center',
+                vertical: 'center'
+              }
+            }
+          }
+        }
+      })
+
+      // 表格0
+      if (this.activeKey == 0) {
+        const ri = [6, 11, 20, 23]
+        this.columns.forEach((item, i) => {
+          if (i > 1) {
+            const cols = zim[i]
+            ri.forEach((row, j) => {
+              const a = ws[cols + row]
+              if (a) {
+                a.v = Number(a.v * 100).toFixed(2) + '%' // 设置单元格格式为百分比
+                a.t = 's'
+              }
+            })
+          }
+        })
+      }
+      // 表格1表格2
+      if (this.activeKey == 1 || this.activeKey == 2) {
+        const cols = zim[this.columns.length - 1]
+        Array(this.totalNums).fill().forEach((item, i) => {
+          const a = ws[cols + (i + 3)]
+          console.log(a)
+          if (a) {
+            a.v = Number(a.v * 100).toFixed(2) + '%' // 设置单元格格式为百分比
+            a.t = 's'
+          }
+        })
+      }
+      // 表格3
+      if (this.activeKey == 3) {
+        const ci = [6, 8]
+        ci.forEach((row) => {
+          const cols = zim[row]
+          Array(this.totalNums).fill().forEach((item, i) => {
+            const a = ws[cols + (i + 4)]
+            if (a) {
+              a.v = Number(a.v * 100).toFixed(2) + '%' // 设置单元格格式为百分比
+              a.t = 's'
+            }
+          })
+        })
+      }
+      // 4. 设置列宽
+      ws['!cols'] = Array(this.columns.length).fill().map(() => ({ wch: this.activeKey == 3 ? 15 : 35 }))
+      const timeStr = moment().format('YYYYMMDDHHmmss')
+      // 创建工作簿并导出
+      var wb = XLSX.utils.book_new()
+      // 5. 写入文件
+      XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
+      XLSX.writeFile(wb, this.queryParam.month.split('-')[1] + '月' + title + '-' + timeStr + '.xlsx')
+    },
+    //  导出
+    handleExport () {
+      const excelTitle = this.tabsList.find(item => item.id == this.activeKey)
+      if (this.$refs.table0 && this.activeKey == 0) {
+        this.totalNums = this.$refs.table0.list.length
+        this.exportTable(this.$refs.table0.getTable(), excelTitle.name)
+      } else if (this.$refs.table1 && this.activeKey == 1) {
+        this.totalNums = this.$refs.table1.list.length
+        this.exportTable(this.$refs.table1.getTable(), excelTitle.name)
+      } else if (this.$refs.table2 && this.activeKey == 2) {
+        this.totalNums = this.$refs.table2.list.length
+        this.exportTable(this.$refs.table2.getTable(), excelTitle.name)
+      } else if (this.$refs.table3 && this.activeKey == 3) {
+        this.totalNums = this.$refs.table3.list.length
+        this.exportTable(this.$refs.table3.getTable(), excelTitle.name)
+      }
+    },
+    // 获取表格数据
+    async getTableData () {
+      const reportType = ['COUNTRY_SALES_DAY', 'DailyPL', 'DailyPLJL', 'AREA_SALES_DAY'][this.activeKey]
+      const reportDate = this.queryParam.month + '-01 00:00:00'
+      this.nowDate = moment().format('DD日HH点mm分')
+      this.spinning = true
+      const data = await salesReportDailyList({ reportType, reportDate }).then(res => res.data)
+      if (data && data.length) {
+        this.tableData = data
+        // 全国销售日报
+        if (this.activeKey == 0) {
+          this.columns = ['', '']
+          data.forEach(item => {
+            this.columns.push(item.subareaName)
+          })
+        }
+        // 项目销售日报1
+        if (this.activeKey == 1) {
+          this.columns = this.getColumns()
+        }
+        // 项目销售日报2
+        if (this.activeKey == 2) {
+          this.columns = [1, 2, 3, 4, 5]
+        }
+        // 分区销售报表
+        if (this.activeKey == 3 && this.$refs.table3) {
+          this.columns = this.$refs.table3.columns
+        }
+        // 初始化页面
+        this.$nextTick(() => {
+          if (this.$refs['table' + this.activeKey]) {
+            this.$refs['table' + this.activeKey].pageInit()
+          }
+        })
+      } else {
+        this.tableData = []
+      }
+      this.spinning = false
+    },
+    getColumns () {
+      const row = this.tableData[0]
+      const ret = []
+      if (row) {
+        row.detailList[0].forEach(item => {
+          ret.push(item)
+        })
+        ret.push(row.bymb)
+        ret.push(row.wcl)
+      }
+      return ret
+    },
+    // 初始化
+    pageInit (activeKey) {
+      this.activeKey = activeKey
+    }
+  },
+  mounted () {
+    if (!this.$store.state.app.isNewTab) { // 页签刷新时调用
+      this.pageInit()
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.card-table{
+  height: calc(100vh - 140px);
+  overflow: auto;
+}
+</style>

+ 196 - 0
src/views/reportData/dailyReport/table0.vue

@@ -0,0 +1,196 @@
+<template>
+  <div>
+    <!-- 全国销售日报 -->
+    <table class="table-box" id="day-table-0" v-if="tableData.length">
+      <thead class="ant-table-thead">
+        <tr>
+          <th :colspan="columns.length">
+            <div class="table-title">{{ dateStr }} 全国销售日报 <span v-if="showDz">(截止{{ nowDate }})</span></div>
+          </th>
+        </tr>
+        <tr>
+          <th v-for="(item,index) in columns" :key="index">{{ item }}</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr v-for="item in list" :key="item.key">
+          <td
+            v-for="cols in columns.length"
+            :key="cols+'td'"
+            :width="cols==2?350:150"
+            v-if="item['col'+cols]!==''"
+            :rowspan="hasRowspan(item['col'+cols])[1]"
+            :align="item['col'+cols].indexOf('.')>=0 ? (hasRate(item)&&cols>2?'center':'right'):'center'"
+            :class="item.key=='currRealFinish'||item.key=='currRealTireFinish'?'red':''"
+          >
+            {{ hasRowspan(item['col'+cols])[1] ? hasRowspan(item['col'+cols])[0] : item['col'+cols] }}{{ hasRate(item)&&cols>2?'%':'' }}
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <div v-else class="noData">
+      暂无数据,请点击查询
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Table0',
+  props: {
+    tableData: {
+      type: Array,
+      default: () => []
+    },
+    month: {
+      type: String,
+      default: () => ''
+    },
+    columns: {
+      type: Array,
+      default: () => []
+    },
+    nowDate: {
+      type: String,
+      default: () => ''
+    }
+  },
+  data () {
+    return {
+      months: '',
+      list: [],
+      showDz: false,
+      dateStr: ''
+    }
+  },
+  methods: {
+    getmonths () {
+      this.months = this.month.split('-')[1]
+      this.dateStr = this.month.replace('-', '年') + '月'
+    },
+    getshowDz () {
+      const nowMonths = new Date().getMonth() + 1
+      this.showDz = this.months == nowMonths
+    },
+    getlist () {
+      const rets = []
+      const row1 = [
+        '年度目标|yearTarget',
+        '截止1-' + (this.months - 1) + '月销售实际完成|histSalesReal',
+        '累计' + this.months + '月销售实际截止完成|accuSalesReal',
+        '年度完成率|yearTargetRate',
+        '本月目标|currTarget',
+        '本月实际销售|currSalesReal',
+        '本月销售实际退货|currReturnReal',
+        '本月销售实际完成|currRealFinish',
+        '本月达成率|currTargetRate',
+        '预估订单|currExpect',
+        '预估完成|currExpectFinish',
+        '离目标差额|currTargetDiff'
+      ]
+      const row2 = [
+        '年度目标|yearTargetTire',
+        '截止1-' + (this.months - 1) + '月销售实际完成条数|histSalesRealTireNum',
+        '截止1-' + (this.months - 1) + '月销售实际完成销售额|histSalesRealTireAmount',
+        '累计' + this.months + '月销售实际完成条数|accuSalesRealTireNum',
+        '累计' + this.months + '月销售实际截止完成|accuSalesRealTireAmount',
+        '年度完成率|yearTargetTireRate',
+        '本月目标条数|currTargetTireNum',
+        '本月销售条数|currSalesTireNum',
+        '本月达成率|currTargetTireRate',
+        '本月实际销售|currSalesTireReal',
+        '本月销售实际退货|currReturnTireReal',
+        '本月销售实际完成|currRealTireFinish',
+        '预估订单|currExpectTire',
+        '预估完成|currExpectTireFinish',
+        '离目标差额|currTargetTireDiff'
+      ]
+      const row3 = ['本月实际销售额|totalCurrRealFinish', '本月预估完成|totalCurrExpectFinish']
+      const getRows = function (row, arr, name) {
+        row.forEach((item, i) => {
+          const nameArr = item.split('|')
+          if (i == 0) {
+            arr.push({ col1: name + 'rowspan' + row.length, col2: nameArr[0], key: nameArr[1] })
+          } else {
+            arr.push({ col1: '', col2: nameArr[0], key: nameArr[1] })
+          }
+        })
+      }
+      // 品牌
+      getRows(row1, rets, '品牌')
+      // 轮胎
+      getRows(row2, rets, '轮胎')
+      // 品牌+轮胎
+      getRows(row3, rets, '品牌+轮胎')
+      // 循环列
+      rets.forEach(item => {
+        this.tableData.forEach((cols, i) => {
+          for (const key in cols) {
+            if (key === item.key) {
+              const data = item.col2.indexOf('条数') >= 0 ? String(cols[key]) : Number(cols[key]).toFixed(2)
+              item['col' + (i + 3)] = data
+            }
+          }
+        })
+      })
+      this.list = rets
+    },
+    hasRowspan (row) {
+      return row && row.toString().split('rowspan')
+    },
+    hasRate (row) {
+      return ['yearTargetRate', 'currTargetRate', 'yearTargetTireRate', 'currTargetTireRate'].includes(row.key)
+    },
+    getTable () {
+      return document.getElementById('day-table-0')
+    },
+    pageInit () {
+      this.getmonths()
+      this.getshowDz()
+      this.getlist()
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .table-title{
+    font-size: 16px;
+    font-weight: bold;
+    width: 100%;
+    max-width: 1400px;
+    text-align: center;
+  }
+  .noData{
+    width: 100%;
+    text-align: center;
+    font-size: 16px;
+    color: #999;
+    min-height: 300px;
+    line-height: 300px;
+  }
+  .table-box{
+    width: 100%;
+    max-width: 1400px;
+    font-size: 14px;
+    .red{
+      color: red;
+    }
+    tr > th{
+      padding: 6px 8px;
+      border: 1px solid #dedede;
+      text-align: center;
+    }
+    tr > td{
+      padding: 5px;
+      border: 1px solid #dedede;
+    }
+    tr{
+      &:hover{
+        td{
+          background-color: #ffd6d4;
+        }
+      }
+    }
+  }
+</style>

+ 148 - 0
src/views/reportData/dailyReport/table1.vue

@@ -0,0 +1,148 @@
+<template>
+  <div>
+    <!-- 项目销售日报 -->
+    <table class="table-box" id="day-table-1" v-if="tableData.length">
+      <thead class="ant-table-thead">
+        <tr>
+          <th :colspan="columns.length">
+            <div class="table-title">{{ dateStr }} 项目销售日报1 <span v-if="showDz">(截止{{ nowDate }})</span></div>
+          </th>
+        </tr>
+        <tr>
+          <th v-for="item in columns" :key="item">{{ item }}</th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr v-for="(sitem,index) in list" :key="index">
+          <td
+            width="150"
+            v-for="(td,tdi) in sitem"
+            :key="tdi+'td'"
+            :rowspan="hasRowspan(td)[1]"
+            :align="typeof td == 'number' ? 'right':'center'"
+            :class="hasRed(td)||hasHj(sitem,index,td,tdi)?'red':''"
+          >
+            {{ hasRowspan(td)[1] ? hasRowspan(td)[0] : tdi > 0 ? Number(td).toFixed(2) : td }}
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <div v-else class="noData">
+      暂无数据,请点击查询
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Table1',
+  props: {
+    tableData: {
+      type: Array,
+      default: () => []
+    },
+    month: {
+      type: String,
+      default: () => ''
+    },
+    columns: {
+      type: Array,
+      default: () => []
+    },
+    nowDate: {
+      type: String,
+      default: () => ''
+    }
+  },
+  data () {
+    return {
+      months: '',
+      list: [],
+      showDz: false,
+      dateStr: ''
+    }
+  },
+  methods: {
+    getmonths () {
+      this.months = this.month.split('-')[1]
+      this.dateStr = this.month.replace('-', '年') + '月'
+    },
+    getshowDz () {
+      const nowMonths = new Date().getMonth() + 1
+      this.showDz = this.months == nowMonths
+    },
+    getlist () {
+      let rets = []
+      this.tableData.forEach((item, i) => {
+        if (i > 0) {
+          item.detailList[0].push(item.bymb + 'rowspan' + item.detailList.length, item.wcl + 'rowspan' + item.detailList.length)
+          rets = rets.concat(item.detailList)
+        }
+      })
+      this.list = rets
+    },
+    hasRowspan (row) {
+      return row.toString().split('rowspan')
+    },
+    hasHj (a, b, c, d) {
+      const hj = this.columns.findIndex(item => item == '销售额合计')
+      const arr = ['合计', '箭牌喇叭', '制动系统']
+      return (d == hj && arr.find(item => a.toString().indexOf(item) >= 0))
+    },
+    hasRed (row, tdi) {
+      const arr = ['合计', '箭牌喇叭', '制动系统']
+      return arr.find(item => row.toString().indexOf(item) >= 0)
+    },
+    getTable () {
+      return document.getElementById('day-table-1')
+    },
+    pageInit () {
+      this.getmonths()
+      this.getshowDz()
+      this.getlist()
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .table-title{
+    font-size: 16px;
+    font-weight: bold;
+    width: 100%;
+    max-width: 1400px;
+    text-align: center;
+  }
+  .noData{
+    width: 100%;
+    text-align: center;
+    font-size: 16px;
+    color: #999;
+    min-height: 300px;
+    line-height: 300px;
+  }
+  .table-box{
+    width: 100%;
+    max-width: 1400px;
+    font-size: 14px;
+    .red{
+      color: red;
+    }
+    tr > th{
+      padding: 6px 8px;
+      border: 1px solid #dedede;
+      text-align: center;
+    }
+    tr > td{
+      padding: 5px;
+      border: 1px solid #dedede;
+    }
+    tr{
+      &:hover{
+        td{
+          background-color: #ffd6d4;
+        }
+      }
+    }
+  }
+</style>

+ 128 - 0
src/views/reportData/dailyReport/table2.vue

@@ -0,0 +1,128 @@
+<template>
+  <div>
+    <div v-if="tableData.length">
+      <!-- 全国销售日报 -->
+      <table class="table-box" id="day-table-2" >
+        <thead class="ant-table-thead">
+          <tr>
+            <th :colspan="cloumns.length">
+              <div class="table-title">{{ dateStr }} 项目销售日报2 <span v-if="showDz">(截止{{ nowDate }})</span></div>
+            </th>
+          </tr>
+          <tr>
+            <th v-for="item in cloumns" :key="item">{{ item }}</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr v-for="(item,index) in list" :key="index">
+            <td align="center">{{ item.proName }}</td>
+            <td align="center">{{ item.userName }}</td>
+            <td align="center">{{ Number(item.bymb).toFixed(2) }}</td>
+            <td align="center">{{ Number(item.amount).toFixed(2) }}</td>
+            <td align="center" class="red">{{ item.wcl }}</td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    <div v-else class="noData">
+      暂无数据,请点击查询
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Table2',
+  props: {
+    tableData: {
+      type: Array,
+      default: () => []
+    },
+    month: {
+      type: String,
+      default: () => ''
+    },
+    nowDate: {
+      type: String,
+      default: () => ''
+    }
+  },
+  data () {
+    return {
+      months: '',
+      list: [],
+      showDz: false,
+      dateStr: '',
+      cloumns: []
+    }
+  },
+  methods: {
+    getcloumns () {
+      const m = this.month.split('-')
+      this.cloumns = ['项目', '品类经理', m[1] + '月业绩目标', m[1] + '月销售额截止达成', '达成率']
+    },
+    getmonths () {
+      this.months = this.month.split('-')[1]
+      this.dateStr = this.month.replace('-', '年') + '月'
+    },
+    getshowDz () {
+      const nowMonths = new Date().getMonth() + 1
+      this.showDz = this.months == nowMonths
+    },
+    getlist () {
+      this.list = this.tableData
+    },
+    getTable () {
+      return document.getElementById('day-table-2')
+    },
+    pageInit () {
+      this.getmonths()
+      this.getcloumns()
+      this.getshowDz()
+      this.getlist()
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .table-title{
+    font-size: 16px;
+    font-weight: bold;
+    width: 100%;
+    max-width: 1400px;
+    text-align: center;
+  }
+  .noData{
+    width: 100%;
+    text-align: center;
+    font-size: 16px;
+    color: #999;
+    min-height: 300px;
+    line-height: 300px;
+  }
+  .table-box{
+    width: 100%;
+    max-width: 1400px;
+    font-size: 14px;
+    .red{
+      color: red;
+    }
+    tr > th{
+      padding: 6px 8px;
+      border: 1px solid #dedede;
+      text-align: center;
+    }
+    tr > td{
+      padding: 5px;
+      border: 1px solid #dedede;
+    }
+    tr{
+      &:hover{
+        td{
+          background-color: #ffd6d4;
+        }
+      }
+    }
+  }
+</style>

+ 247 - 0
src/views/reportData/dailyReport/table3.vue

@@ -0,0 +1,247 @@
+<template>
+  <div>
+    <!-- 分区销售日报 -->
+    <table class="table-box" id="day-table-3" v-if="tableData.length">
+      <thead class="ant-table-thead">
+        <tr>
+          <th :colspan="columns.length">
+            <div class="table-title">{{ dateStr }} 分区销售日报 <span v-if="showDz">(截止{{ nowDate }})</span></div>
+          </th>
+        </tr>
+        <tr>
+          <th key="managerNameList" rowspan="2" style="text-align: center;">
+            <span class="ant-table-header-column"><div><span class="ant-table-column-title">区域负责人</span><span class="ant-table-column-sorter"></span></div></span>
+          </th>
+          <th key="subareaAreaName" rowspan="2" style="text-align: center;">
+            <span class="ant-table-header-column"><div><span class="ant-table-column-title">分区</span><span class="ant-table-column-sorter"></span></div></span>
+          </th>
+          <th key="2" colspan="8" class="ant-table-align-center" style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">品牌</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th key="3" colspan="4" class="ant-table-align-center" style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">轮胎</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th key="4" colspan="1" class="ant-table-align-center ant-table-row-cell-last" style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">品牌+轮胎</span><span class="ant-table-column-sorter"></span></div></span></th>
+        </tr>
+        <tr>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">年度目标</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">截止1-{{ months-1 }}月完成</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">{{ months }}月销售额截止达成</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">累计{{ months }}月截止完成</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title red">年度完成率</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">{{ months }}月业绩目标</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title red">达成率</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">今日销售额</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">截止1-{{ months-1 }}月销售额</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">{{ months }}月销售额截止达成</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">累计{{ months }}月截止完成</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">今日销售额</span><span class="ant-table-column-sorter"></span></div></span></th>
+          <th class="ant-table-align-center ant-table-row-cell-break-word ant-table-row-cell-last" style="text-align: center;"><span class="ant-table-header-column"><div><span class="ant-table-column-title">{{ months }}月销售额截止达成</span><span class="ant-table-column-sorter"></span></div></span></th>
+        </tr>
+      </thead>
+      <tbody>
+        <tr v-for="(item, index) in list" :key="index">
+          <td
+            v-for="(sitem,si) in columns"
+            :key="sitem.dataIndex+index"
+            :class="sitem.title.indexOf('率')>=0?'red '+(hjRow.indexOf(index)>=0?'hj':''):(hjRow.indexOf(index)>=0?'hj':'')"
+            style="text-align: center;"
+            v-if="!(index==list.length-1&&si==0)"
+            :colspan="index==list.length-1&&si==1?2:1"
+            :style="index==list.length-1?'color: red;font-weight:bold;background:#dfdeff;border-color:#c7c7ff;':''"
+          >
+            {{ si>1 ? Number(item[sitem.dataIndex]).toFixed(2) : item[sitem.dataIndex].toString() }}{{ sitem.title.indexOf('率')>=0?'%':'' }}
+          </td>
+        </tr>
+      </tbody>
+    </table>
+    <div v-else class="noData">
+      暂无数据,请点击查询
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Table3',
+  props: {
+    tableData: {
+      type: Array,
+      default: () => []
+    },
+    month: {
+      type: String,
+      default: () => ''
+    },
+    nowDate: {
+      type: String,
+      default: () => ''
+    }
+  },
+  data () {
+    return {
+      months: '',
+      list: [],
+      showDz: false,
+      dateStr: ''
+    }
+  },
+  computed: {
+    hjRow () {
+      const ret = []
+      this.list.forEach((item, index) => {
+        if (item.subareaAreaName.indexOf('合计') >= 0 || item.subareaAreaName.indexOf('云南省') >= 0) {
+          ret.push(index)
+        }
+      })
+      return ret
+    },
+    columns () {
+      return [
+        {
+          title: '区域负责人',
+          dataIndex: 'managerNameList',
+          align: 'center',
+          width: '250'
+        },
+        {
+          title: '分区',
+          dataIndex: 'subareaAreaName',
+          align: 'center',
+          width: '250'
+        },
+        {
+          title: '年度目标',
+          dataIndex: 'yearTarget',
+          align: 'center',
+          width: '100'
+        },
+        {
+          title: '截止1-' + (this.months - 1) + '月完成',
+          dataIndex: 'histSalesReal',
+          align: 'center',
+          width: '100'
+        }, {
+          title: this.months + '月销售额截止达成',
+          dataIndex: 'currSalesReal',
+          align: 'center',
+          width: '130'
+        }, {
+          title: '累计' + this.months + '月截止完成',
+          dataIndex: 'accuSalesReal',
+          align: 'center',
+          width: '100'
+        }, {
+          title: '年度完成率',
+          dataIndex: 'yearTargetRate',
+          align: 'center',
+          width: '100'
+        }, {
+          title: this.months + '月业绩目标',
+          dataIndex: 'currTarget',
+          align: 'center',
+          width: '100'
+        }, {
+          title: '达成率',
+          dataIndex: 'currTargetRate',
+          align: 'center',
+          width: '100'
+        }, {
+          title: '今日销售额',
+          dataIndex: 'todaySalesReal',
+          align: 'center',
+          width: '100'
+        },
+        {
+          title: '截止1-' + (this.months - 1) + '月销售额',
+          dataIndex: 'histSalesRealTireAmount',
+          align: 'center',
+          width: '100'
+        }, {
+          title: this.months + '月销售额截止达成',
+          dataIndex: 'currSalesTireReal',
+          align: 'center',
+          width: '130'
+        }, {
+          title: '累计' + this.months + '月截止完成',
+          dataIndex: 'accuSalesRealTireAmount',
+          align: 'center',
+          width: '100'
+        }, {
+          title: '今日销售额',
+          dataIndex: 'todaySalesTireReal',
+          align: 'center',
+          width: '100'
+        },
+        {
+          title: this.months + '月销售额截止达成',
+          dataIndex: 'totalCurrSalesTireReal',
+          align: 'center',
+          width: '130'
+        }
+      ]
+    }
+  },
+  methods: {
+    getmonths () {
+      this.months = this.month.split('-')[1]
+      this.dateStr = this.month.replace('-', '年') + '月'
+    },
+    getshowDz () {
+      const nowMonths = new Date().getMonth() + 1
+      this.showDz = this.months == nowMonths
+    },
+    getlist () {
+      this.list = this.tableData
+    },
+    getTable () {
+      return document.getElementById('day-table-3')
+    },
+    pageInit () {
+      this.getmonths()
+      this.getshowDz()
+      this.getlist()
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+  .table-title{
+    font-size: 16px;
+    font-weight: bold;
+    width: 100%;
+    text-align: center;
+  }
+  .noData{
+    width: 100%;
+    text-align: center;
+    font-size: 16px;
+    color: #999;
+    min-height: 300px;
+    line-height: 300px;
+  }
+  .table-box{
+    width: 100%;
+    font-size: 14px;
+    tr > th{
+      padding: 6px 8px;
+      border: 1px solid #dedede;
+      text-align: center;
+    }
+    .red{
+      color: red;
+    }
+    .hj{
+      font-weight: bold;
+      background-color: #f4f5ff;
+    }
+    tr > td{
+      padding: 5px;
+      border: 1px solid #dedede;
+    }
+    tr{
+      &:hover{
+        td{
+          background-color: #ffd6d4;
+        }
+      }
+    }
+  }
+</style>

+ 1 - 0
src/views/reportData/regionTypeBusinessReport/list.vue

@@ -50,6 +50,7 @@
                 @click="handleExport"
                 :disabled="disabled"
                 :loading="exportLoading"
+                v-if="$hasPermissions('M_regionTypeBusinessReport_export')"
                 id="regionTypeBusinessReportList-export">导出</a-button>
             </a-col>
           </a-row>

+ 325 - 0
src/views/setting/dailyReportSettings/categoryTargetList.vue

@@ -0,0 +1,325 @@
+<template>
+  <div>
+    <a-card size="small" :bordered="false" class="estimatedOrderList-wrap searchBoxNormal">
+      <!-- 搜索条件 -->
+      <div class="table-page-search-wrapper" ref="tableSearch">
+        <a-form-model
+          id="estimatedOrderList-form"
+          ref="ruleForm"
+          class="form-model-con"
+          layout="inline"
+          :model="queryParam"
+          :rules="rules">
+          <a-row :gutter="15">
+            <a-col :md="5" :sm="24">
+              <a-form-model-item label="年份" prop="confYear">
+                <a-select
+                  id="estimatedOrderList-confYear"
+                  style="width: 100%"
+                  placeholder="请选择年份"
+                  :value="queryParam.confYear"
+                  @change="changeYear">
+                  <a-select-option :id="'estimatedOrderList-'+item" v-for="item in years" :value="item" :key="item">
+                    {{ item }}
+                  </a-select-option>
+                </a-select>
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="4" :sm="24">
+              <a-button
+                type="primary"
+                @click="handleSearch"
+                :disabled="disabled"
+                id="estimatedOrderList-refresh">查询</a-button>
+              <a-button
+                style="margin-left: 8px"
+                @click="resetSearchForm"
+                :disabled="disabled"
+                id="estimatedOrderList-reset">重置</a-button>
+            </a-col>
+          </a-row>
+        </a-form-model>
+      </div>
+    </a-card>
+    <a-card size="small" :bordered="false">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <!-- 列表 -->
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.no"
+          rowKeyName="no"
+          :style="{ height: tableHeight+70+'px' }"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight}"
+          :defaultLoadData="false"
+          :showPagination="false"
+          bordered>
+          <!-- 1月~12月 -->
+          <template
+            v-for="col in 12"
+            :slot="'month'+col"
+            slot-scope="text, record"
+          >
+            <div :key="col">
+              <a-input-number
+                style="width:100%;"
+                v-if="record.editable"
+                size="small"
+                :min="0"
+                :max="999999999.99"
+                placeholder="请输入"
+                :value="text"
+                :precision="2"
+                :id="'estimatedOrderList-input-'+record.id"
+                @blur="e => handleChange(e.target.value,record, col)"/>
+              <template v-else>
+                {{ text?toThousands(text):'0.00' }}
+              </template>
+            </div>
+          </template>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <span v-if="record.editable">
+              <a-button
+                size="small"
+                type="link"
+                class="button-info"
+                @click="handleSave(record)"
+                :id="'estimatedOrderList-save-btn'+record.id"
+              >
+                保存
+              </a-button>
+              <a-popconfirm title="确定取消吗?" :id="'estimatedOrderList-cancel-btn'+record.id" @confirm="() => handleCancel(record)">
+                <a>取消</a>
+              </a-popconfirm>
+            </span>
+            <a-button
+              size="small"
+              type="link"
+              v-else-if="$hasPermissions('B_dailyReportSettings_edit')&&!record.editable"
+              class="button-info"
+              :disabled="editingKey !== ''"
+              @click="handleEdit(record)"
+              :id="'estimatedOrderList-edit-btn'+record.id"
+            >
+              编辑
+            </a-button>
+            <span v-else>--</span>
+          </template>
+        </s-table>
+      </a-spin>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+// 组件
+import { STable } from '@/components'
+// 接口
+import { reportDailyConfList, dailyReportConfSave } from '@/api/reportDailyConf'
+export default {
+  name: 'EstimatedOrderList',
+  mixins: [commonMixin],
+  components: { STable },
+  props: {
+    pageType: { //  弹框显示状态
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      disabled: false, //  查询、重置按钮是否可操作
+      tableHeight: 0, // 表格高度
+      toYears: new Date().getFullYear(), // 今年
+      editingKey: '', // 按钮是否禁用
+      //  查询条件
+      queryParam: {
+        confType: undefined, // 页面类型
+        confYear: new Date().getFullYear() // 年份
+      },
+      rules: {
+        confYear: [{ required: true, message: '请选择年份', trigger: 'change' }]
+      },
+      dataSources: null, // 表格数据
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        // 获取列表数据  wu分页
+        this.queryParam.confType = this.pageType
+        const params = Object.assign(parameter, this.queryParam)
+        return reportDailyConfList(params).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            // 计算表格序号
+            for (var i = 0; i < data.length; i++) {
+              data[i].no = i + 1
+              data[i].editable = false
+            }
+          }
+          this.disabled = false
+          this.spinning = false
+          this.dataSources = data
+          return data
+        })
+      }
+    }
+  },
+  computed: {
+    // 获取年份数据
+    years () {
+      const years = []
+      const lens = (this.toYears - 2023) + 1
+      for (let i = 0; i < lens; i++) {
+        years.push(this.toYears - i)
+      }
+      return years
+    },
+    columns () {
+      const _this = this
+      const arr = [
+        { title: (_this.pageType === 'CATEGORY_MONTHLY_TARGET' ? '类别' : '项目'), dataIndex: 'productTypeName', width: '12%', align: 'center', customRender: function (text) { return text || '--' } },
+        { title: '1月', dataIndex: 'value01', width: '8%', align: 'right', scopedSlots: { customRender: 'month1' } },
+        { title: '2月', dataIndex: 'value02', width: '8%', align: 'right', scopedSlots: { customRender: 'month2' } },
+        { title: '3月', dataIndex: 'value03', width: '8%', align: 'right', scopedSlots: { customRender: 'month3' } },
+        { title: '4月', dataIndex: 'value04', width: '8%', align: 'right', scopedSlots: { customRender: 'month4' } },
+        { title: '5月', dataIndex: 'value05', width: '8%', align: 'right', scopedSlots: { customRender: 'month5' } },
+        { title: '6月', dataIndex: 'value06', width: '8%', align: 'right', scopedSlots: { customRender: 'month6' } },
+        { title: '7月', dataIndex: 'value07', width: '8%', align: 'right', scopedSlots: { customRender: 'month7' } },
+        { title: '8月', dataIndex: 'value08', width: '8%', align: 'right', scopedSlots: { customRender: 'month8' } },
+        { title: '9月', dataIndex: 'value09', width: '8%', align: 'right', scopedSlots: { customRender: 'month9' } },
+        { title: '10月', dataIndex: 'value10', width: '8%', align: 'right', scopedSlots: { customRender: 'month10' } },
+        { title: '11月', dataIndex: 'value11', width: '8%', align: 'right', scopedSlots: { customRender: 'month11' } },
+        { title: '12月', dataIndex: 'value12', width: '8%', align: 'right', scopedSlots: { customRender: 'month12' } },
+        { title: '合计', dataIndex: 'summation', width: '11%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '11%', align: 'center' }
+      ]
+      if (_this.pageType === 'CATEGORY_MANAGER_MONTHLY_TARGET') {
+        arr.splice(1, 0, { title: '品类经理', dataIndex: 'userName', width: '12%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true })
+      }
+      return arr
+    }
+  },
+  methods: {
+    // 添加数据处理方法
+    processData (data, field) {
+      let count = 0
+      data.forEach((item, index) => {
+        if (index === 0 || item[field] !== data[index - 1][field]) {
+          count = 1
+          // 向后查找相同项
+          for (let i = index + 1; i < data.length; i++) {
+            if (item[field] === data[i][field]) count++
+            else break
+          }
+          item.rowSpan = count // 设置合并行数
+        } else {
+          item.rowSpan = 0 // 后续相同项设置为0(不渲染)
+        }
+      })
+      return data
+    },
+    // 查询
+    handleSearch () {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.editingKey = ''
+          this.$refs.table.refresh(true)
+        } else {
+          this.$message.error('请选择年份')
+          return false
+        }
+      })
+    },
+    // 选择查询年份  change
+    changeYear (val) {
+      this.editingKey = ''
+      if (!val) {
+        this.queryParam.confYear = void 0
+      } else {
+        this.queryParam.confYear = val
+      }
+    },
+    // 编辑
+    handleEdit (row) {
+      this.editingKey = row.no
+      row.editable = true
+    },
+    // 保存
+    handleSave (row) {
+      row.confYear = this.queryParam.confYear
+      dailyReportConfSave(row).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          row.editable = false
+          this.editingKey = ''
+          this.$refs.table.refresh(true)
+        }
+      })
+    },
+    // 取消
+    handleCancel (row) {
+      row.editable = false
+      this.editingKey = ''
+      this.$refs.table.refresh(true)
+    },
+    // input   change事件
+    handleChange (val, row, column) {
+      const _this = this
+      const newColumn = _this.padZero(column)
+      row['value' + newColumn] = val || 0
+      row.summation = _this.calculateTotal(row)
+      // _this.dataSources[column * 1 - 1] = row
+    },
+    // 补零方法
+    padZero (num) {
+      return String(num).padStart(2, '0')
+    },
+    // 计算合计
+    calculateTotal (rowData) {
+      const keys = Array.from({ length: 12 }, (_, i) => 'value' + this.padZero(i + 1))
+      const totalNum = keys.reduce((sum, key) => sum + (Number(rowData[key]) || 0), 0)
+      console.log('sdsdsd:', totalNum)
+      return totalNum
+    },
+    //  重置
+    resetSearchForm () {
+      this.editingKey = ''
+      this.queryParam.confType = undefined
+      this.queryParam.confYear = new Date().getFullYear()
+      this.$refs.ruleForm.resetFields()
+      this.$refs.table.refresh(true)
+    },
+    // 初始化
+    pageInit () {
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        this.setTableH()
+      })
+      this.resetSearchForm()
+    },
+    // 计算表格高度
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 280
+    }
+  },
+  mounted () {
+    this.pageInit()
+  }
+}
+</script>
+<style lang="less" scoped>
+/deep/.button-info[disabled] {
+  color: gray;
+}
+/deep/.ant-input-number-handler-wrap {
+  display: none;
+}
+</style>

+ 337 - 0
src/views/setting/dailyReportSettings/estimatedOrderList.vue

@@ -0,0 +1,337 @@
+<template>
+  <div>
+    <a-card size="small" :bordered="false" class="estimatedOrderList-wrap searchBoxNormal">
+      <!-- 搜索条件 -->
+      <div class="table-page-search-wrapper" ref="tableSearch">
+        <a-form-model
+          id="estimatedOrderList-form"
+          ref="ruleForm"
+          class="form-model-con"
+          layout="inline"
+          :model="queryParam"
+          :rules="rules">
+          <a-row :gutter="15">
+            <a-col :md="5" :sm="24">
+              <a-form-model-item label="年份" prop="confYear">
+                <a-select
+                  id="estimatedOrderList-confYear"
+                  style="width: 100%"
+                  placeholder="请选择年份"
+                  :value="queryParam.confYear"
+                  @change="changeYear">
+                  <a-select-option :id="'estimatedOrderList-'+item" v-for="item in years" :value="item" :key="item">
+                    {{ item }}
+                  </a-select-option>
+                </a-select>
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="4" :sm="24">
+              <a-button
+                type="primary"
+                @click="handleSearch"
+                :disabled="disabled"
+                id="estimatedOrderList-refresh">查询</a-button>
+              <a-button
+                style="margin-left: 8px"
+                @click="resetSearchForm"
+                :disabled="disabled"
+                id="estimatedOrderList-reset">重置</a-button>
+            </a-col>
+          </a-row>
+        </a-form-model>
+      </div>
+    </a-card>
+    <a-card size="small" :bordered="false">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <!-- 列表 -->
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.no"
+          rowKeyName="no"
+          :style="{ height: tableHeight+70+'px' }"
+          :columns="columns"
+          :data="loadData"
+          :scroll="{ y: tableHeight}"
+          :defaultLoadData="false"
+          :showPagination="false"
+          bordered>
+          <!-- 1月~12月 -->
+          <template
+            v-for="col in 12"
+            :slot="'month'+col"
+            slot-scope="text, record"
+          >
+            <div :key="col">
+              <a-input-number
+                style="width:100%;"
+                v-if="record.editable"
+                size="small"
+                :min="0"
+                :max="pageType === 'REGIONAL_ESTIMATED_ORDER'?999999999.99:999999999"
+                placeholder="请输入"
+                :precision="pageType === 'REGIONAL_ESTIMATED_ORDER'?2:0"
+                :value="text"
+                :id="'estimatedOrderList-input-'+record.id"
+                @blur="e => handleChange(e.target.value,record, col)" />
+              <template v-else>
+                {{ pageType === 'REGIONAL_ESTIMATED_ORDER'?toThousands(text) :text }}
+              </template>
+            </div>
+          </template>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <span v-if="record.editable">
+              <a-button
+                size="small"
+                type="link"
+                class="button-info"
+                @click="handleSave(record)"
+                :id="'estimatedOrderList-save-btn'+record.id"
+              >
+                保存
+              </a-button>
+              <a-popconfirm title="确定取消吗?" :id="'estimatedOrderList-cancel-btn'+record.id" @confirm="() => handleCancel(record)">
+                <a>取消</a>
+              </a-popconfirm>
+            </span>
+            <a-button
+              size="small"
+              type="link"
+              v-else-if="$hasPermissions('B_dailyReportSettings_edit')&&!record.editable"
+              class="button-info"
+              :disabled="editingKey !== ''"
+              @click="handleEdit(record)"
+              :id="'estimatedOrderList-edit-btn'+record.id"
+            >
+              编辑
+            </a-button>
+            <span v-else>--</span>
+          </template>
+        </s-table>
+      </a-spin>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+// 组件
+import { STable } from '@/components'
+// 接口
+import { reportDailyConfList, dailyReportConfSave } from '@/api/reportDailyConf'
+export default {
+  name: 'EstimatedOrderList',
+  mixins: [commonMixin],
+  components: { STable },
+  props: {
+    pageType: { //  弹框显示状态
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      disabled: false, //  查询、重置按钮是否可操作
+      tableHeight: 0, // 表格高度
+      toYears: new Date().getFullYear(), // 今年
+      editingKey: '', // 按钮是否禁用
+      //  查询条件
+      queryParam: {
+        confType: undefined, // 页面类型
+        confYear: new Date().getFullYear() // 年份
+      },
+      rules: {
+        confYear: [{ required: true, message: '请选择年份', trigger: 'change' }]
+      },
+      dataSources: null, // 表格数据
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        // 获取列表数据  无分页
+        this.queryParam.confType = this.pageType
+        const params = Object.assign(parameter, this.queryParam)
+        return reportDailyConfList(params).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            // 计算表格序号
+            for (var i = 0; i < data.length; i++) {
+              data[i].no = i + 1
+              data[i].editable = false
+            }
+          }
+          this.disabled = false
+          this.spinning = false
+          if (this.pageType === 'REGIONAL_ESTIMATED_ORDER') {
+            this.dataSources = this.processData(data, 'productTypeKey')
+          } else {
+            this.dataSources = data
+          }
+          return data
+        })
+      }
+    }
+  },
+  computed: {
+    // 获取年份数据
+    years () {
+      const years = []
+      const lens = (this.toYears - 2023) + 1
+      for (let i = 0; i < lens; i++) {
+        years.push(this.toYears - i)
+      }
+      return years
+    },
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '区域', dataIndex: 'subareaName', width: '12%', align: 'center', customRender: function (text) { return text || '--' }, ellipsis: true },
+        { title: '1月', dataIndex: 'value01', width: '8%', align: 'right', scopedSlots: { customRender: 'month1' } },
+        { title: '2月', dataIndex: 'value02', width: '8%', align: 'right', scopedSlots: { customRender: 'month2' } },
+        { title: '3月', dataIndex: 'value03', width: '8%', align: 'right', scopedSlots: { customRender: 'month3' } },
+        { title: '4月', dataIndex: 'value04', width: '8%', align: 'right', scopedSlots: { customRender: 'month4' } },
+        { title: '5月', dataIndex: 'value05', width: '8%', align: 'right', scopedSlots: { customRender: 'month5' } },
+        { title: '6月', dataIndex: 'value06', width: '8%', align: 'right', scopedSlots: { customRender: 'month6' } },
+        { title: '7月', dataIndex: 'value07', width: '8%', align: 'right', scopedSlots: { customRender: 'month7' } },
+        { title: '8月', dataIndex: 'value08', width: '8%', align: 'right', scopedSlots: { customRender: 'month8' } },
+        { title: '9月', dataIndex: 'value09', width: '8%', align: 'right', scopedSlots: { customRender: 'month9' } },
+        { title: '10月', dataIndex: 'value10', width: '8%', align: 'right', scopedSlots: { customRender: 'month10' } },
+        { title: '11月', dataIndex: 'value11', width: '8%', align: 'right', scopedSlots: { customRender: 'month11' } },
+        { title: '12月', dataIndex: 'value12', width: '8%', align: 'right', scopedSlots: { customRender: 'month12' } },
+        { title: '合计', dataIndex: 'summation', width: '11%', align: 'right', customRender: function (text) { return ((text || text == 0) ? (_this.pageType === 'REGIONAL_ESTIMATED_ORDER' ? _this.toThousands(text) : text) : '--') } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '11%', align: 'center' }
+      ]
+      if (_this.pageType === 'REGIONAL_ESTIMATED_ORDER') {
+        arr.splice(0, 0, { title: '品类',
+          dataIndex: 'productTypeName',
+          width: '12%',
+          align: 'center',
+          ellipsis: true,
+          customRender: (value, row, index) => ({
+            children: value,
+            attrs: { rowSpan: row.rowSpan }
+          })
+        })
+      }
+      return arr
+    }
+  },
+  methods: {
+    // 添加数据处理方法
+    processData (data, field) {
+      let count = 0
+      data.forEach((item, index) => {
+        if (index === 0 || item[field] !== data[index - 1][field]) {
+          count = 1
+          // 向后查找相同项
+          for (let i = index + 1; i < data.length; i++) {
+            if (item[field] === data[i][field]) count++
+            else break
+          }
+          item.rowSpan = count // 设置合并行数
+        } else {
+          item.rowSpan = 0 // 后续相同项设置为0(不渲染)
+        }
+      })
+      return data
+    },
+    // 查询
+    handleSearch () {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.editingKey = ''
+          this.$refs.table.refresh(true)
+        } else {
+          this.$message.error('请选择年份')
+          return false
+        }
+      })
+    },
+    // 选择查询年份  change
+    changeYear (val) {
+      this.editingKey = ''
+      if (!val) {
+        this.queryParam.confYear = void 0
+      } else {
+        this.queryParam.confYear = val
+      }
+    },
+    // 编辑
+    handleEdit (row) {
+      this.editingKey = row.no
+      row.editable = true
+    },
+    // 保存
+    handleSave (row) {
+      row.confYear = this.queryParam.confYear
+      dailyReportConfSave(row).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          row.editable = false
+          this.editingKey = ''
+          this.$refs.table.refresh(true)
+        }
+      })
+    },
+    // 取消
+    handleCancel (row) {
+      row.editable = false
+      this.editingKey = ''
+      this.$refs.table.refresh(true)
+    },
+    // input   change事件
+    handleChange (val, row, column) {
+      const _this = this
+      const newColumn = _this.padZero(column)
+      row['value' + newColumn] = val || 0
+      row.summation = _this.calculateTotal(row)
+      // _this.dataSources[column * 1 - 1] = row
+    },
+    // 补零方法
+    padZero (num) {
+      return String(num).padStart(2, '0')
+    },
+    // 计算合计
+    calculateTotal (rowData) {
+      const keys = Array.from({ length: 12 }, (_, i) => 'value' + this.padZero(i + 1))
+      const totalNum = keys.reduce((sum, key) => sum + (Number(rowData[key]) || 0), 0)
+      return totalNum
+    },
+    //  重置
+    resetSearchForm () {
+      this.editingKey = ''
+      this.queryParam.confType = undefined
+      this.queryParam.confYear = new Date().getFullYear()
+      this.$refs.ruleForm.resetFields()
+      this.$refs.table.refresh(true)
+    },
+    // 初始化
+    pageInit () {
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        this.setTableH()
+      })
+      this.resetSearchForm()
+    },
+    // 计算表格高度
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 280
+    }
+  },
+  mounted () {
+    this.pageInit()
+  }
+}
+</script>
+<style lang="less" scoped>
+/deep/.button-info[disabled] {
+  color: gray;
+}
+/deep/.ant-input-number-handler-wrap {
+  display: none;
+}
+</style>

+ 41 - 0
src/views/setting/dailyReportSettings/index.vue

@@ -0,0 +1,41 @@
+<template>
+  <div>
+    <a-card size="small" :bordered="false">
+      <a-tabs default-active-key="1" v-model="tabVal">
+        <a-tab-pane key="1" tab="区域预估订单" force-render>
+          <estimatedOrderList pageType="REGIONAL_ESTIMATED_ORDER"></estimatedOrderList>
+        </a-tab-pane>
+        <a-tab-pane key="2" tab="轮胎月目标" force-render>
+          <estimatedOrderList pageType="TIRE_MONTHLY_TARGET"></estimatedOrderList>
+        </a-tab-pane>
+        <a-tab-pane key="3" tab="品类月目标" force-render>
+          <categoryTargetList pageType="CATEGORY_MONTHLY_TARGET"></categoryTargetList>
+        </a-tab-pane>
+        <a-tab-pane key="4" tab="品类经理月目标" force-render>
+          <categoryTargetList pageType="CATEGORY_MANAGER_MONTHLY_TARGET"></categoryTargetList>
+        </a-tab-pane>
+        <a-tab-pane key="5" tab="分区月目标" force-render>
+          <partitionTargetList pageType="PARTITION_MONTHLY_TARGET"></partitionTargetList>
+        </a-tab-pane>
+      </a-tabs>
+    </a-card>
+  </div>
+</template>
+<script>
+import { commonMixin } from '@/utils/mixin'
+// 组件
+import estimatedOrderList from './estimatedOrderList.vue'
+import categoryTargetList from './categoryTargetList.vue'
+import partitionTargetList from './partitionTargetList.vue'
+export default {
+  name: 'DailyReportSettingsIndex',
+  mixins: [commonMixin],
+  components: { estimatedOrderList, categoryTargetList, partitionTargetList },
+  data () {
+    return {
+      tabVal: '1'// tab值  1轮胎月度费用报表 2轮胎季度费用报表 3轮胎年度费用报表 4轮胎费用明细报表
+    }
+  }
+}
+
+</script>

+ 358 - 0
src/views/setting/dailyReportSettings/partitionTargetList.vue

@@ -0,0 +1,358 @@
+<template>
+  <div>
+    <a-card size="small" :bordered="false" class="estimatedOrderList-wrap searchBoxNormal">
+      <!-- 搜索条件 -->
+      <div class="table-page-search-wrapper" ref="tableSearch">
+        <a-form-model
+          id="estimatedOrderList-form"
+          ref="ruleForm"
+          class="form-model-con"
+          layout="inline"
+          :model="queryParam"
+          :rules="rules">
+          <a-row :gutter="15">
+            <a-col :md="5" :sm="24">
+              <a-form-model-item label="年份" prop="confYear">
+                <a-select
+                  id="estimatedOrderList-confYear"
+                  style="width: 100%"
+                  placeholder="请选择年份"
+                  :value="queryParam.confYear"
+                  @change="changeYear">
+                  <a-select-option :id="'estimatedOrderList-'+item" v-for="item in years" :value="item" :key="item">
+                    {{ item }}
+                  </a-select-option>
+                </a-select>
+              </a-form-model-item>
+            </a-col>
+            <a-col :md="4" :sm="24">
+              <a-button
+                type="primary"
+                @click="handleSearch"
+                :disabled="disabled"
+                id="estimatedOrderList-refresh">查询</a-button>
+              <a-button
+                style="margin-left: 8px"
+                @click="resetSearchForm"
+                :disabled="disabled"
+                id="estimatedOrderList-reset">重置</a-button>
+            </a-col>
+          </a-row>
+        </a-form-model>
+      </div>
+    </a-card>
+    <a-card size="small" :bordered="false">
+      <a-spin :spinning="spinning" tip="Loading...">
+        <!-- 列表 -->
+        <s-table
+          class="sTable fixPagination"
+          ref="table"
+          size="small"
+          :rowKey="(record) => record.no"
+          rowKeyName="no"
+          :style="{ height: tableHeight+70+'px' }"
+          :columns="columns"
+          :data="loadData"
+          :rowClassName="(record, index) => record.subareaAreaName ==='合计' ? 'last-row':''"
+          :scroll="{ y: tableHeight}"
+          :showPagination="false"
+          :defaultLoadData="false"
+          bordered>
+          <!-- 1月~12月 -->
+          <template
+            v-for="col in 12"
+            :slot="'month'+col"
+            slot-scope="text, record"
+          >
+            <div :key="col">
+              <a-input-number
+                style="width:100%;"
+                v-if="record.editable"
+                size="small"
+                :min="0"
+                :max="999999999.99"
+                placeholder="请输入"
+                :precision="2"
+                :value="text"
+                :id="'estimatedOrderList-input-'+record.id"
+                @blur="e => handleChange(e.target.value,record, col)"/>
+              <template v-else>
+                {{ text?toThousands(text):'0.00' }}
+              </template>
+            </div>
+          </template>
+          <!-- 操作 -->
+          <template slot="action" slot-scope="text, record">
+            <span v-if="record.editable">
+              <a-button
+                size="small"
+                type="link"
+                class="button-info"
+                @click="handleSave(record)"
+                :id="'estimatedOrderList-save-btn'+record.id"
+              >
+                保存
+              </a-button>
+              <a-popconfirm title="确定取消吗?" :id="'estimatedOrderList-cancel-btn'+record.id" @confirm="() => handleCancel(record)">
+                <a>取消</a>
+              </a-popconfirm>
+            </span>
+            <a-button
+              size="small"
+              type="link"
+              v-else-if="$hasPermissions('B_dailyReportSettings_edit')&&!record.editable &&record.subareaAreaName!='合计'"
+              class="button-info"
+              :disabled="editingKey !== ''"
+              @click="handleEdit(record)"
+              :id="'estimatedOrderList-edit-btn'+record.id"
+            >
+              编辑
+            </a-button>
+            <span v-else>--</span>
+          </template>
+        </s-table>
+      </a-spin>
+    </a-card>
+  </div>
+</template>
+
+<script>
+import { commonMixin } from '@/utils/mixin'
+// 组件
+import { STable } from '@/components'
+// 接口
+import { reportDailyConfList, dailyReportConfSave } from '@/api/reportDailyConf'
+export default {
+  name: 'EstimatedOrderList',
+  mixins: [commonMixin],
+  components: { STable },
+  props: {
+    pageType: { //  弹框显示状态
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      spinning: false,
+      disabled: false, //  查询、重置按钮是否可操作
+      tableHeight: 0, // 表格高度
+      toYears: new Date().getFullYear(), // 今年
+      editingKey: '', // 按钮是否禁用
+      //  查询条件
+      queryParam: {
+        confType: undefined, // 页面类型
+        confYear: new Date().getFullYear() // 年份
+      },
+      rules: {
+        confYear: [{ required: true, message: '请选择年份', trigger: 'change' }]
+      },
+      dataSources: null, // 表格数据
+      // 加载数据方法 必须为 Promise 对象
+      loadData: parameter => {
+        this.disabled = true
+        this.spinning = true
+        // 获取列表数据  wu分页
+        this.queryParam.confType = this.pageType
+        const params = Object.assign(parameter, this.queryParam)
+        return reportDailyConfList(params).then(res => {
+          let data
+          if (res.status == 200) {
+            data = res.data
+            // 计算表格序号
+            for (var i = 0; i < data.length; i++) {
+              data[i].no = i + 1
+              data[i].editable = false
+            }
+          }
+          this.disabled = false
+          this.spinning = false
+          this.dataSources = data
+          return data
+        })
+      }
+    }
+  },
+  computed: {
+    // 获取年份数据
+    years () {
+      const years = []
+      const lens = (this.toYears - 2023) + 1
+      for (let i = 0; i < lens; i++) {
+        years.push(this.toYears - i)
+      }
+      return years
+    },
+    columns () {
+      const _this = this
+      const arr = [
+        { title: '分区',
+          dataIndex: 'subareaAreaName',
+          width: '12%',
+          align: 'center',
+          ellipsis: true,
+          customRender: (text, record, index) => {
+            const isLastRow = record.no == this.dataSources.length
+            return {
+              children: text,
+              attrs: {
+                colSpan: isLastRow ? 2 : 1// 合并前两列
+              }
+            }
+          } },
+        { title: '区域负责人',
+          dataIndex: 'userName',
+          width: '12%',
+          align: 'center',
+          customRender: (text, record, index) => {
+            const isLastRow = record.no == this.dataSources.length
+            return {
+              children: text || '--',
+              attrs: {
+                colSpan: isLastRow ? 0 : 1// 合并前两列
+              }
+            }
+          },
+          ellipsis: true },
+        { title: '1月', dataIndex: 'value01', width: '8%', align: 'right', scopedSlots: { customRender: 'month1' } },
+        { title: '2月', dataIndex: 'value02', width: '8%', align: 'right', scopedSlots: { customRender: 'month2' } },
+        { title: '3月', dataIndex: 'value03', width: '8%', align: 'right', scopedSlots: { customRender: 'month3' } },
+        { title: '4月', dataIndex: 'value04', width: '8%', align: 'right', scopedSlots: { customRender: 'month4' } },
+        { title: '5月', dataIndex: 'value05', width: '8%', align: 'right', scopedSlots: { customRender: 'month5' } },
+        { title: '6月', dataIndex: 'value06', width: '8%', align: 'right', scopedSlots: { customRender: 'month6' } },
+        { title: '7月', dataIndex: 'value07', width: '8%', align: 'right', scopedSlots: { customRender: 'month7' } },
+        { title: '8月', dataIndex: 'value08', width: '8%', align: 'right', scopedSlots: { customRender: 'month8' } },
+        { title: '9月', dataIndex: 'value09', width: '8%', align: 'right', scopedSlots: { customRender: 'month9' } },
+        { title: '10月', dataIndex: 'value10', width: '8%', align: 'right', scopedSlots: { customRender: 'month10' } },
+        { title: '11月', dataIndex: 'value11', width: '8%', align: 'right', scopedSlots: { customRender: 'month11' } },
+        { title: '12月', dataIndex: 'value12', width: '8%', align: 'right', scopedSlots: { customRender: 'month12' } },
+        { title: '合计', dataIndex: 'summation', width: '11%', align: 'right', customRender: function (text) { return ((text || text == 0) ? _this.toThousands(text) : '--') } },
+        { title: '操作', scopedSlots: { customRender: 'action' }, width: '11%', align: 'center' }
+      ]
+      return arr
+    }
+  },
+  methods: {
+    // 添加数据处理方法
+    processData (data, field) {
+      let count = 0
+      data.forEach((item, index) => {
+        if (index === 0 || item[field] !== data[index - 1][field]) {
+          count = 1
+          // 向后查找相同项
+          for (let i = index + 1; i < data.length; i++) {
+            if (item[field] === data[i][field]) count++
+            else break
+          }
+          item.rowSpan = count // 设置合并行数
+        } else {
+          item.rowSpan = 0 // 后续相同项设置为0(不渲染)
+        }
+      })
+      return data
+    },
+    // 查询
+    handleSearch () {
+      this.$refs.ruleForm.validate(valid => {
+        if (valid) {
+          this.editingKey = ''
+          this.$refs.table.refresh(true)
+        } else {
+          this.$message.error('请选择年份')
+          return false
+        }
+      })
+    },
+    // 选择查询年份  change
+    changeYear (val) {
+      this.editingKey = ''
+      if (!val) {
+        this.queryParam.confYear = void 0
+      } else {
+        this.queryParam.confYear = val
+      }
+    },
+    // 编辑
+    handleEdit (row) {
+      this.editingKey = row.no
+      row.editable = true
+    },
+    // 保存
+    handleSave (row) {
+      row.confYear = this.queryParam.confYear
+      dailyReportConfSave(row).then(res => {
+        if (res.status == 200) {
+          this.$message.success(res.message)
+          row.editable = false
+          this.editingKey = ''
+          this.$refs.table.refresh(true)
+        }
+      })
+    },
+    // 取消
+    handleCancel (row) {
+      row.editable = false
+      this.editingKey = ''
+      this.$refs.table.refresh(true)
+    },
+    // input   change事件
+    handleChange (val, row, column) {
+      const _this = this
+      const newColumn = _this.padZero(column)
+      row['value' + newColumn] = val || 0
+      row.summation = _this.calculateTotal(row)
+      // _this.dataSources[column * 1 - 1] = row
+    },
+    // 补零方法
+    padZero (num) {
+      return String(num).padStart(2, '0')
+    },
+    // 计算合计
+    calculateTotal (rowData) {
+      const keys = Array.from({ length: 12 }, (_, i) => 'value' + this.padZero(i + 1))
+      const totalNum = keys.reduce((sum, key) => sum + (Number(rowData[key]) || 0), 0)
+      console.log('sdsdsd:', totalNum)
+      return totalNum
+    },
+    //  重置
+    resetSearchForm () {
+      this.editingKey = ''
+      this.queryParam.confType = undefined
+      this.queryParam.confYear = new Date().getFullYear()
+      this.$refs.ruleForm.resetFields()
+      this.$refs.table.refresh(true)
+    },
+    // 初始化
+    pageInit () {
+      this.$nextTick(() => { // 页面渲染完成后的回调
+        this.setTableH()
+      })
+      this.resetSearchForm()
+    },
+    // 计算表格高度
+    setTableH () {
+      const tableSearchH = this.$refs.tableSearch.offsetHeight
+      this.tableHeight = window.innerHeight - tableSearchH - 280
+    }
+  },
+  mounted () {
+    this.pageInit()
+  }
+}
+</script>
+<style lang="less" scoped>
+.button-info[disabled] {
+  color: gray;
+}
+/* 最后一行样式 */
+/deep/.last-row {
+    background: #fafafa !important; /* 橙色背景 */
+    /* 固定定位 */
+    position: sticky;
+    bottom: 0;
+    z-index: 2;
+  }
+/deep/.ant-input-number-handler-wrap {
+    display: none;
+  }
+</style>

+ 2 - 3
vue.config.js

@@ -54,13 +54,12 @@ const vueConfig = {
       new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
     ],
     // if prod is on, add externals
-    externals: isProd() ? prodExternals : {}
+    externals: isProd() ? prodExternals : {},
   },
 
   chainWebpack: (config) => {
     config.resolve.alias
       .set('@$', resolve('src'))
-
     const svgRule = config.module.rule('svg')
     svgRule.uses.clear()
     svgRule
@@ -108,7 +107,7 @@ const vueConfig = {
     // If you want to turn on the proxy, please remosve the mockjs /src/main.jsL11
     proxy: {
       '/api': {
-        // target: 'http://192.168.2.103/ocs-admin',
+        // target: 'http://192.168.2.10/ocs-admin',
         // target: 'https://t.ocs.360arrow.com/ocs-admin', //  练习
         target: 'https://p.ocs.360arrow.com/ocs-admin', //  预发布
         ws: false,